1. Are you planning to upload your awesome map 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. DID YOU KNOW - That you can unlock new rank icons by posting on the forums or winning contests? Click here to customize your rank or read our User Rank Policy to see a list of ranks that you can unlock. Have you won a contest and still haven't received your rank award? Then please contact the administration.
    Dismiss Notice
  4. Ride into the sunset with the 32nd Modeling Contest.
    Dismiss Notice
  5. This adventure has come to an end. Congratulate our heroes in the 16th Mini Mapping Contest Results.
    Dismiss Notice
  6. From the gates of hell, the 5th Special Effect Contest Results have emerged.
    Dismiss Notice
  7. Race against the odds and Reforge, Don't Refund. The 14th Techtree Contest has begun!
    Dismiss Notice
  8. 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.

Trigger Viewer

Godfall_Conquest.w3x
Variables
Battallioni General
Move to point Compy
Regroup
Regroup wait
Auto reinforce
Battalion reinforce
Battalion train
Selection Selection thingie
Deselection Selection thingie
UnLoad
Research
Battalion order target
Battalion order no target
Battalion order point
Battalion death Ctrl
Autogenerate battallions
Battalion death Ctrl Crew
Crew regroup
Capture
Summon Companion
Batalion initialization
Initialization
Build
Initialize Buildings
------------Mines---------------
Entangle Initialization
Entangle Hall Built
------------Build---------------
NoCancel
------------Death---------------
Hall death
Mine death
Building Cancel
Short Invulnerabilty
------------New---------------
Set Hall values
Begins Build
Death Build
Finished Build
Build menu
Force Build P1
Force Build P2
Force Build P3
Force Build P4
Build
Force Cancel P1
Force Cancel P2
Force Cancel P3
Force Cancel P4
Cancelled
Building
----Put edited stuff here----
Selection Selection thingie Copy Copy 2
SpellsNew
Sanctuary
Initialization Spells
Battalion spells
Comandeer
Familiar
Vulture
Battalion death Ctrl New Copy
AI
Shake it baby
Cheats
test parameters
Flush
------------Hero---------------
Hero Learn Just Trained
Hero Learn
Hero Retreat
------------Training---------------
BuildTrain P1
BuildTrain P2
BuildTrain P3
BuildTrain P4
Training check start
Training check end
Goldmines
Main dies
--------------Attacking-------------
Attack group P1
Attack group P2
Attack group P3
Attack group P4
Group attacking Jass
Remove group Jass
New base of operations
-------------Defending--------------
Defenders
Reinforce Jass
Defend
-------------Unused--------------
Selection Selection thingie Copy Copy
ResourceGathering
FlagConvert
Con Income
HeroExperiment
HeroLimit
Human Hero Die
Human Hero Check
Human Hero Cancel
Game
Choose Race Ivo
Jass Globals
PaladinResearch
Start
SetupMusic2 Copy
DetectingPlayer Copy
Defeatandvictory3 Copy
Enter map-specific custom script code below. This text will be included in the map script after variables are declared and before any trigger code.
//TESH.scrollpos=0
//TESH.alwaysfold=0
function EnemyTroops takes nothing returns boolean
    return IsUnitEnemy( GetFilterUnit(), ConvertedPlayer( udg_AI_PlayerNumber ) ) and IsUnitAliveBJ( GetFilterUnit() ) //and GetConvertedPlayerId(GetOwningPlayer(GetFilterUnit())) < 6
endfunction

// ********************************************************************
// checks if the unit type is a captain of the batalion
// returns array index defined in initialization, otherwise returns 0
function IsCaptain takes integer captain returns integer
    local integer i = 1
    loop
        if ( captain == udg_BattalionCaptain[i] ) then
            return i
        endif
        exitwhen i > udg_NrTypes
        set i = i + 1
    endloop
    return 0
endfunction
// ********************************************************************
// returns captain unit of the batalion
function GetCaptain takes group batalion returns unit
    local unit captain
    local group tempgroup = CreateGroup()
    call GroupAddGroup(batalion,tempgroup)
    loop
        set captain = FirstOfGroup(tempgroup)
        exitwhen LoadInteger(udg_hashtable, GetHandleId(captain), 1) == 1 // or captain == null
        call GroupRemoveUnit( tempgroup, captain )
    endloop
    call DestroyGroup(tempgroup)
    set tempgroup = null
    return captain
endfunction
// ********************************************************************
// checks if batalion has all his units
function IsComplete takes unit captain returns boolean
    local integer battallionIndex = LoadInteger(udg_hashtable, GetHandleId(captain), 0)
    if ( battallionIndex == 0 ) then
        return true
    endif
    if ( CountUnitsInGroup( udg_Battallion[battallionIndex] ) == udg_BattalionSize[IsCaptain(GetUnitTypeId( captain ))] +1 ) then
        return true
    else
        return false
    endif
endfunction
// ********************************************************************
// checks if AI attack group units are close enough
function CloseTogether takes group batalion, location waypoint returns boolean
    local real Xpos
    local real Ypos
    local real minX = 100000.0
    local real minY = 100000.0
    local real maxX = -100000.0
    local real maxY = -100000.0
    local unit wanderer
    local unit enemy
    local group tempgroup = CreateGroup()
    local group enemies = CreateGroup()
    local boolean nearbyenemies = false
    local boolean close = true
    call GroupAddGroup(batalion,tempgroup)
    loop
        set wanderer = FirstOfGroup(tempgroup)
        exitwhen wanderer == null
        if ( GetUnitX(wanderer) < minX ) then
            set minX = GetUnitX(wanderer)
        endif
        if ( GetUnitY(wanderer) < minY ) then
            set minY = GetUnitY(wanderer)
        endif
        if ( GetUnitX(wanderer) > maxX ) then
            set maxX = GetUnitX(wanderer)
        endif
        if ( GetUnitY(wanderer) > maxY ) then
            set maxY = GetUnitY(wanderer)
        endif
        call GroupRemoveUnit( tempgroup, wanderer )
    endloop
    call GroupAddGroup(batalion,tempgroup)
    loop
        set wanderer = FirstOfGroup(tempgroup)
        exitwhen wanderer == null
        set Xpos = GetUnitX(wanderer) - GetLocationX(waypoint)
        set Ypos = GetUnitY(wanderer) - GetLocationY(waypoint)      
        if ( SquareRoot( Xpos*Xpos + Ypos*Ypos ) >= 200 + 100*CountUnitsInGroup( batalion ) ) then
            set close = false
	    set udg_AI_PlayerNumber = GetConvertedPlayerId( GetOwningPlayer(wanderer) )
            call GroupEnumUnitsInRange( enemies, GetUnitX(wanderer), GetUnitY(wanderer), 1000.0, Condition(function EnemyTroops))
            if ( CountUnitsInGroup( enemies ) > 0 ) then
                set nearbyenemies = true
                set enemy = GroupPickRandomUnit(enemies)
                call GroupPointOrder( batalion, "attack", GetUnitX(enemy), GetUnitY(enemy))
            endif
        endif
        call GroupRemoveUnit( tempgroup, wanderer )
    endloop
    if not ( nearbyenemies ) then
        call GroupPointOrderLoc( batalion, "attack", waypoint )
    endif
    set wanderer = null
    call DestroyGroup(tempgroup)
    set tempgroup = null    
    return close
endfunction

function IsEnemyTownhall takes nothing returns boolean
    return ( IsUnitType(GetFilterUnit(), UNIT_TYPE_TOWNHALL) == true and IsPlayerEnemy(GetOwningPlayer(GetFilterUnit()), udg_AI_Player_Copy) == true and IsUnitAliveBJ(GetFilterUnit()) == true )
endfunction

function IsTower takes nothing returns boolean
    return GetUnitTypeId(GetFilterUnit()) == 'h003' or GetUnitTypeId(GetFilterUnit()) == 'n011' or GetUnitTypeId(GetFilterUnit()) == 'n007' or GetUnitTypeId(GetFilterUnit()) == 'h00S'
endfunction
// ********************************************************************
// calculates strength of a group of units for AI purposes
// returns a very subjective coefficent representing strength
function OverallStrength takes group units returns integer
    local unit tempunit
    local integer strength = 0
    local group tempgroup = CreateGroup()
    call GroupAddGroup(units, tempgroup)
    loop
        set tempunit = FirstOfGroup(tempgroup)
        call GroupRemoveUnit(tempgroup, tempunit)
        exitwhen tempunit == null
        if ( LoadInteger(udg_hashtable, GetHandleId(tempunit), 1) == 1) then
            set strength = strength + CountUnitsInGroup( udg_Battallion[LoadInteger(udg_hashtable, GetHandleId(tempunit), 0)]) * GetUnitLevel(tempunit)
        else
            set strength = strength + GetUnitLevel(tempunit)
        endif
    endloop
    call DestroyGroup(tempgroup)
    set tempgroup = null    
    return strength
endfunction
// ********************************************************************
// sets the AI's next target
// returns the nearest enemy hall with beatable strength
function MinDistanceHall takes unit origin, real strength returns unit
    local group halls = CreateGroup()
    local group tempgroup = CreateGroup()
    local integer playernumber = GetConvertedPlayerId( GetOwningPlayer(origin))
    local integer enemies
    local integer allies
    local unit hall = null
    local unit tempunit
    local real Xpos
    local real Ypos
    local real distance = 10000000.00
    set udg_AI_Player_Copy = GetOwningPlayer(origin)
    set udg_AI_PlayerNumber = playernumber
    call GroupEnumUnitsInRect( halls, GetPlayableMapRect(), Condition(function IsEnemyTownhall) )
    loop 
        set tempunit = FirstOfGroup(halls)
        call GroupRemoveUnit(halls,tempunit)
        call GroupEnumUnitsInRange(tempgroup, GetUnitX(tempunit), GetUnitY(tempunit), 1000., Condition(function EnemyTroops))
        set enemies = OverallStrength( tempgroup )
        call GroupEnumUnitsInRange(tempgroup, GetUnitX(tempunit), GetUnitY(tempunit), 1000., Condition(function IsTower))
        set enemies = enemies + 5*CountUnitsInGroup(tempgroup)
        set allies = OverallStrength(udg_AI_AttackGroup[playernumber])        
        exitwhen tempunit == null
        set Xpos = GetUnitX(tempunit) - GetUnitX(origin)
        set Ypos = GetUnitY(tempunit) - GetUnitY(origin)
        if ( SquareRoot(Xpos*Xpos + Ypos*Ypos) < distance ) then
            set distance = SquareRoot(Xpos*Xpos + Ypos*Ypos)
            set hall = tempunit
        endif
    endloop
    call DestroyGroup(halls)
    call DestroyGroup(tempgroup)
    set halls = null    
    set tempgroup = null    
    return hall
endfunction


function EnumBuildings takes nothing returns boolean
    return ( IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE) == true and GetUnitState(GetFilterUnit(), UNIT_STATE_LIFE) > 0 )
endfunction

function Training takes nothing returns boolean
    return ( GetOwningPlayer( GetFilterUnit()) == udg_AI_Player_Copy and not IsUnitInGroup( GetFilterUnit(), udg_AI_TrainingBuildings ) )
endfunction
// ********************************************************************
// executes build command for AI
function Build takes integer building, unit hall, integer number returns nothing
    local group townbuildings
    local group buildingtype
    local real angle = GetRandomReal(0, 2*bj_PI)
    local real x = GetUnitX(hall) + 600.0 * Cos(angle)
    local real y = GetUnitY(hall) + 600.0 * Sin(angle)
    local real Xpos
    local real Ypos
    local integer inrange
    local integer filteredunits
    local integer builder
    local player owner = GetOwningPlayer( hall )
    if ( udg_check == true or GetUnitState(hall, UNIT_STATE_LIFE) <= 0 ) then
        return
    endif
    set townbuildings = CreateGroup()
    call GroupEnumUnitsInRange( townbuildings, GetUnitX( hall ), GetUnitY( hall ), 1000.00, Condition(function EnumBuildings))
    set inrange = CountUnitsInGroup( townbuildings )
    set buildingtype = GetUnitsOfPlayerAndTypeId(udg_AI_Player_Copy,building)
    call GroupRemoveGroup( buildingtype, townbuildings)
    set filteredunits = CountUnitsInGroup( townbuildings )
    if ( inrange - filteredunits >= number) then    //stevilo zgradb zraven - stevilo zgradb zraven brez tega tipa
        call DestroyGroup( townbuildings )
        call DestroyGroup( buildingtype )
    else
        set bj_lastCreatedUnit = CreateUnit( udg_AI_Player_Copy, building, x, y, bj_UNIT_FACING)
        set Xpos = GetUnitX(bj_lastCreatedUnit)
        set Ypos = GetUnitX(bj_lastCreatedUnit)
        set Xpos = Xpos - x
        set Ypos = Ypos - y
        call RemoveUnit(bj_lastCreatedUnit)
        if ( GetPlayerRace(owner) == RACE_HUMAN ) then
            set builder = 'e00B'
        elseif ( GetPlayerRace(owner) == RACE_ORC ) then
            set builder = 'e00E'
        elseif ( GetPlayerRace(owner) == RACE_UNDEAD ) then
            set builder = 'e00C'
        elseif ( GetPlayerRace(owner) == RACE_NIGHTELF ) then
            set builder = 'e00D'
        endif
        set bj_lastCreatedUnit = CreateUnit( udg_AI_Player_Copy, builder, x, y, bj_UNIT_FACING)
        call IssueBuildOrderById( bj_lastCreatedUnit, building, x, y )
        call DestroyGroup( townbuildings )
        call DestroyGroup( buildingtype )
        set townbuildings = null
        set buildingtype = null
        set udg_check = true
    endif
endfunction
// ********************************************************************
// executes train command for AI
function Train takes integer men, integer factory, integer number returns nothing
    local group tempgroup = GetUnitsOfPlayerAndTypeId(udg_AI_Player_Copy,men)
    local unit factory1
    local integer alive = CountUnitsInGroup( tempgroup )
    local integer training = LoadIntegerBJ(GetConvertedPlayerId(udg_AI_Player_Copy), men, udg_hashtable)
    if ( udg_check == true ) then
        return
    endif
    call DestroyGroup( tempgroup )
    set tempgroup = GetUnitsOfPlayerAndTypeId(udg_AI_Player_Copy,factory)
    call GroupRemoveGroup( udg_AI_TrainingBuildings, tempgroup )
    if (alive + training >= number)  then
        call DestroyGroup( tempgroup )
    else
        set factory1 = GroupPickRandomUnit( tempgroup )
        call IssueTrainOrderByIdBJ( factory1, men )
        call DestroyGroup( tempgroup )
        set tempgroup = null
        set udg_check = true
    endif
endfunction

function UnitDead takes nothing returns boolean
    return (IsUnitDeadBJ(GetFilterUnit()) == true)
endfunction

function HideUnits takes nothing returns nothing
    call SetUnitOwner( GetEnumUnit(), ConvertedPlayer( GetConvertedPlayerId(GetOwningPlayer(GetEnumUnit())) + udg_TranslatePlayerNumber ), false )
endfunction

function ShowUnits takes nothing returns nothing
    call SetUnitOwner( GetEnumUnit(), ConvertedPlayer( GetConvertedPlayerId(GetOwningPlayer(GetEnumUnit())) - udg_TranslatePlayerNumber ), true )
endfunction
// ********************************************************************
// creates attack group for AI
// returns whether the listed units are avalaible
function Assemble takes integer playernumber, integer first, integer second, integer third, integer fourth, integer fifth, integer sixth, integer seventh, integer eighth returns boolean
    local integer i = 0
    local integer array unittypes
    local integer array races
    local group tempgroup = CreateGroup()
    local group deadunits = GetUnitsOfPlayerMatching(ConvertedPlayer(playernumber), Condition(function UnitDead) )
    local group oftypes
    set unittypes[0] = first
    set unittypes[1] = second
    set unittypes[2] = third
    set unittypes[3] = fourth
    set unittypes[4] = fifth
    set unittypes[5] = sixth
    set unittypes[6] = seventh
    set unittypes[7] = eighth
    if ( GetPlayerRace(Player(playernumber-1)) == RACE_HUMAN ) then
        set races[0] = udg_AI_HumanUnits[0]
        set races[1] = udg_AI_HumanUnits[1]
        set races[2] = udg_AI_HumanUnits[2]
        set races[3] = udg_AI_HumanUnits[3]
        set races[4] = udg_AI_HumanUnits[4]
        set races[5] = udg_AI_HumanUnits[5]
        set races[6] = udg_AI_HumanUnits[6]
        set races[7] = udg_AI_HumanUnits[7]
    elseif ( GetPlayerRace(Player(playernumber-1)) == RACE_ORC ) then
        set races[0] = udg_AI_VampireUnits[0]
        set races[1] = udg_AI_VampireUnits[1]
        set races[2] = udg_AI_VampireUnits[2]
        set races[3] = udg_AI_VampireUnits[3]
        set races[4] = udg_AI_VampireUnits[4]
        set races[5] = udg_AI_VampireUnits[5]
        set races[6] = udg_AI_VampireUnits[6]
        set races[7] = udg_AI_VampireUnits[7]
    elseif ( GetPlayerRace(Player(playernumber-1)) == RACE_UNDEAD ) then
        set races[0] = udg_AI_DrowUnits[0]
        set races[1] = udg_AI_DrowUnits[1]
        set races[2] = udg_AI_DrowUnits[2]
        set races[3] = udg_AI_DrowUnits[3]
        set races[4] = udg_AI_DrowUnits[4]
        set races[5] = udg_AI_DrowUnits[5]
        set races[6] = udg_AI_DrowUnits[6]
        set races[7] = udg_AI_DrowUnits[7]
    elseif ( GetPlayerRace(Player(playernumber-1)) == RACE_NIGHTELF ) then
        set races[0] = udg_AI_ElfUnits[0]
        set races[1] = udg_AI_ElfUnits[1]
        set races[2] = udg_AI_ElfUnits[2]
        set races[3] = udg_AI_ElfUnits[3]
        set races[4] = udg_AI_ElfUnits[4]
        set races[5] = udg_AI_ElfUnits[5]
        set races[6] = udg_AI_ElfUnits[6]
        set races[7] = udg_AI_ElfUnits[7]
    endif
    call GroupClear( udg_AI_AttackGroup[playernumber] )
    call ForGroup( deadunits, function HideUnits )
    loop
        exitwhen ( i > 7 )
        set oftypes = GetUnitsOfPlayerAndTypeId( ConvertedPlayer(playernumber), races[i] )
        set tempgroup = GetRandomSubGroup( unittypes[i], oftypes )
        if ( CountUnitsInGroup( tempgroup ) >= unittypes[i] ) then
            call GroupAddGroup( tempgroup, udg_AI_AttackGroup[playernumber] )
            call GroupRemoveGroup( tempgroup,  udg_AI_Defenders[playernumber] )
        else
            call GroupAddGroup( udg_AI_AttackGroup[playernumber], udg_AI_Defenders[playernumber] )
            return false
        endif
        set i = i + 1
    endloop
    call ForGroup( deadunits, function ShowUnits )
    //call BJDebugMsg("gathering troops")
    call DestroyGroup(tempgroup)
    call DestroyGroup(deadunits)
    call DestroyGroup(oftypes)
    return true
endfunction

function GetOrderAbility takes integer batalionOrder, integer caster returns integer
    local integer i = 1
    loop
        exitwhen i == 30
        if ( batalionOrder == udg_BattalionSpellOrderID[i] and caster == udg_BattalionSpellCaster[i] ) then
            return i
        endif
        set i = i + 1        
    endloop
    return 0
endfunction

function GetBatalionAbility takes integer batalionSpell returns integer
    local integer i = 1
    loop
        exitwhen i == 30
        if ( batalionSpell == udg_BattalionSpellAbility[i] ) then
            return i
        endif
        set i = i + 1        
    endloop
    return 0
endfunction
Name Type Is Array Initial Value
AI_AttackDestination location Yes
AI_AttackGroup group Yes
AI_Captain unit Yes
AI_Defenders group Yes
AI_DefendingGroup group Yes
AI_DrowUnits unitcode Yes
AI_Dummy unit Yes
AI_ElfUnits unitcode Yes
AI_Factory unit No
AI_Hero group Yes
AI_HumanUnits unitcode Yes
AI_Movement group Yes
AI_Player player Yes
AI_Player_Copy player No
AI_PlayerNumber integer No 2
AI_ProductionBuilding unitcode Yes
AI_TooStrong group Yes
AI_Townhall unit Yes
AI_TownHall location Yes
AI_TrainingBuildings group No
AI_VampireUnits unitcode Yes
AI_Wave integer Yes
AI_Waypoints location Yes
AllUnits group No
Ang_WingedWitches_Copy quest No
angle real No
Arden unit No
BatalionHash_Beast integer No 9
BatalionHash_Crew integer No 8
BatalionHash_Guards integer No 6
BatalionHash_Order integer No 2
BatalionHash_Summonable integer No 7
BatalionHash_TargetUnit integer No 5
BatalionHash_TargetX integer No 3
BatalionHash_TargetY integer No 4
BattalionCaptain unitcode Yes
BattalionGoldCost integer Yes
BattalionManaCost real Yes
BattalionPowerCost integer Yes
BattalionSize integer Yes
BattalionSpellAbility abilcode Yes
BattalionSpellCaster unitcode Yes
BattalionSpellOrderID integer Yes
BattalionSpellOrderString string Yes
BattalionTimer real Yes
BattalionTroop unitcode Yes
Battallion group Yes
BattallionCount integer No
BattallionIndex integer No
BattallionLimit integer No 200
BattallionQueued group No
BattallionRegroup real No 600.00
BlinkStrike real No
Build_Birth group No
Build_Hall unit Yes
Build_HallType unitcode Yes
Build_Players force No
Build_Structure unitcode Yes
Build_TreeType unitcode Yes
Build_WaitTimer timer Yes
BuildDB_Avalaible abilcode Yes
BuildDB_Builders unitcode Yes
BuildDB_Buildings unitcode Yes
BuildDB_Cost integer Yes
BuildDB_Item abilcode Yes
BuildDB_Limit integer Yes
BuildDB_Requirements unitcode Yes
BuildDB_Unavalaible abilcode Yes
caster unit No
check boolean No
CurrentCamera camerasetup No
DialogBox dialog Yes
DialogButtons button Yes
DummyBuilder unitcode No
EssenceofUnlifeHealth real No
FakeUnits group No
FanofKnivesGroup group No
flyingheight real Yes
FoK_hashtable hashtable No
handle integer No
hashtable hashtable No
Message integer No
NrTypes integer No 80
ownerplayer player No
Players force No
point1 location No
point2 location No
point3 location No
RZ_EssenceAmount integer Yes
Selected1 group Yes
Status integer Yes
Summon integer No 6
target unit No
TempCommander unit No
TempGroiup group No
TempHero unit No
Tempint integer No
TempLoc00 location No
TempLoc01 location No
TempLoc02 location No
Tempplayer player No
TempPoint location No
Temppoint location No
Temppoint01 location No
TempRealX real No
Tempunit unit No
testint integer No
timer real No
tolerateddistance real No 100.00
TranslatePlayerNumber integer No 5
Unittype unitcode No
Keep units to march in relatively proper formations, because the batalion system cannot use default ones for everything.

Use unit point values for their rank in batalions (like melee in front, lower number, and ranged in the back, higher number)
//TESH.scrollpos=18
//TESH.alwaysfold=0
function Selection takes nothing returns boolean
    return ( IsUnitSelected(GetFilterUnit(), GetOwningPlayer(GetOrderedUnit())) == true )
endfunction

function Trig_Move_to_point_Compy_Conditions takes nothing returns boolean
    if ( IsUnitType(GetOrderedUnit(), UNIT_TYPE_STRUCTURE) == false ) then
        if ( GetIssuedOrderId() == 851971 or GetIssuedOrderId() == 851986 or GetIssuedOrderId() == 851983  ) then
                //call BJDebugMsg(OrderId2String( GetIssuedOrderId() ))
            return true
        endif
    endif
    return false
endfunction

function Trig_Move_to_point_Compy_Actions takes nothing returns nothing
    local real orderX = GetOrderPointX()
    local real orderY = GetOrderPointY()
    local integer order = GetIssuedOrderId()
    local integer counter = 0
    local integer counter1 = 0
    local integer counter2 = 0
    local integer index
    local integer min
    local real Xpos
    local real Ypos
    local real XposUnit
    local real YposUnit
    local real minX = 100000.0
    local real minY = 100000.0
    local real maxX = -100000.0
    local real maxY = -100000.0
    local real angle
    local unit wanderer
    local unit array units
    local unit array swap
    local group tempgroup = CreateGroup()

    if ( GetPlayerController(GetOwningPlayer(GetOrderedUnit())) == MAP_CONTROL_USER ) then
        set tempgroup = GetUnitsOfPlayerMatching(GetOwningPlayer(GetOrderedUnit()), Condition(function Selection))
    endif
    if ( IsUnitGroupEmptyBJ(udg_AI_Movement[GetConvertedPlayerId(GetOwningPlayer(GetOrderedUnit()))]) == false ) then
        call GroupAddGroup( udg_AI_Movement[GetConvertedPlayerId(GetOwningPlayer(GetOrderedUnit()))], tempgroup)
    endif
    if ( CountUnitsInGroup(tempgroup) < 2 ) then
        call DestroyGroup(tempgroup)
        call GroupClear(udg_AI_Movement[GetConvertedPlayerId(GetOwningPlayer(GetOrderedUnit()))])
        call EnableTrigger( GetTriggeringTrigger() )
        return
    endif
    loop
        set wanderer = FirstOfGroup(tempgroup)
        exitwhen wanderer == null
        if ( GetUnitX(wanderer) < minX ) then
            set minX = GetUnitX(wanderer)
        endif
        if ( GetUnitY(wanderer) < minY ) then
            set minY = GetUnitY(wanderer)
        endif
        if ( GetUnitX(wanderer) > maxX ) then
            set maxX = GetUnitX(wanderer)
        endif
        if ( GetUnitY(wanderer) > maxY ) then
            set maxY = GetUnitY(wanderer)
        endif
        call GroupRemoveUnit( tempgroup, wanderer )
        set Xpos = minX + (maxX - minX )/2
        set Ypos = minY + (maxY - minY )/2
    endloop
    if ( GetPlayerController(GetOwningPlayer(GetOrderedUnit())) == MAP_CONTROL_USER ) then
        set tempgroup = GetUnitsOfPlayerMatching(GetOwningPlayer(GetOrderedUnit()), Condition(function Selection))
    endif
    if ( IsUnitGroupEmptyBJ(udg_AI_Movement[GetConvertedPlayerId(GetOwningPlayer(GetOrderedUnit()))]) == false ) then
        call GroupAddGroup( udg_AI_Movement[GetConvertedPlayerId(GetOwningPlayer(GetOrderedUnit()))], tempgroup)
    endif
    call GroupClear(udg_AI_Movement[GetConvertedPlayerId(GetOwningPlayer(GetOrderedUnit()))])
    loop
        set wanderer = FirstOfGroup(tempgroup)
        exitwhen wanderer == null
        set units[counter] = wanderer
        call GroupRemoveUnit( tempgroup, wanderer )        
        set counter = counter + 1
    endloop    
    if not (minX <= orderX and orderX <= maxX and minY <= orderY and orderY <= maxY) or GetPlayerController(GetOwningPlayer(GetOrderedUnit())) == MAP_CONTROL_COMPUTER then
        set angle = Atan2(orderY - Ypos, orderX - Xpos)
     //call BJDebugMsg(I2S(counter))
        //sort of
        //call BJDebugMsg("start sorting")
loop
    exitwhen counter1 >= counter
    set counter2 = counter1
    set index = counter1
    set min = GetUnitPointValue( units[counter1] )
    loop
        exitwhen counter2 >= counter
        if GetUnitPointValue( units[counter2] ) < min then
            set min = GetUnitPointValue( units[counter2] )
            set index = counter2
        endif
        //call BJDebugMsg("counting")
        set counter2 = counter2 + 1
    endloop
    //call BJDebugMsg("preswap")
    //call BJDebugMsg(I2S(GetUnitPointValue( units[0] )))
    set wanderer = units[index]
        //call BJDebugMsg(I2S(GetUnitPointValue( wanderer )))
    //set units[index] = null
    set units[index] = units[counter1]
    //set units[counter1] = null
    set units[counter1] = wanderer
    set counter1 = counter1 + 1
   // call BJDebugMsg("swap")
            //call BJDebugMsg(I2S(GetUnitPointValue( units[0] )))
endloop

        //if ( RAbsBJ(Sin(Deg2Rad(GetUnitFacing( FirstOfGroup(tempgroup)))) - Sin(angle)) > 1 ) then
        //    call BJDebugMsg(R2S(RAbsBJ(Deg2Rad(GetUnitFacing( FirstOfGroup(tempgroup))))))
        //    call BJDebugMsg("switching")
        //    set tempgroup = InvertGroup( tempgroup )
        //endif
    if (counter == 2 ) then
        call DisableTrigger( GetTriggeringTrigger() )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[0]
        set XposUnit = orderX + 000.0*(Cos(angle)) + 150.0*(Cos(angle - 3.14159265/2))
        set YposUnit = orderY + 000.0*(Sin(angle)) + 150.0*(Sin(angle - 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[1]
        set XposUnit = orderX + 000.0*(Cos(angle)) + 150.0*(Cos(angle + 3.14159265/2))
        set YposUnit = orderY + 000.0*(Sin(angle)) + 150.0*(Sin(angle + 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )  
        call EnableTrigger( GetTriggeringTrigger() )
    elseif (counter == 4 ) then
        call DisableTrigger( GetTriggeringTrigger() )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[0]
        set XposUnit = orderX + 100.0*(Cos(angle)) + 150.0*(Cos(angle -3.14159265/2))
        set YposUnit = orderY + 100.0*(Sin(angle)) + 150.0*(Sin(angle -3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[1]
        set XposUnit = orderX + 100.0*(Cos(angle)) + 150.0*(Cos(angle+ 3.14159265/2))
        set YposUnit = orderY + 100.0*(Sin(angle)) + 150.0*(Sin(angle+ 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[2]
        set XposUnit = orderX - 100.0*(Cos(angle)) + 150.0*(Cos(angle -3.14159265/2))
        set YposUnit = orderY - 100.0*(Sin(angle)) + 150.0*(Sin(angle -3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[3]
        set XposUnit = orderX - 100.0*(Cos(angle)) + 150.0*(Cos(angle+ 3.14159265/2))
        set YposUnit = orderY - 100.0*(Sin(angle)) + 150.0*(Sin(angle+ 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )        
        call EnableTrigger( GetTriggeringTrigger() )      
    elseif (counter == 3 ) then
        call DisableTrigger( GetTriggeringTrigger() )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[0]
        set XposUnit = orderX + 100.0*(Cos(angle)) + 150.0*(Cos(angle+ -3.14159265/2))
        set YposUnit = orderY + 100.0*(Sin(angle)) + 150.0*(Sin(angle+ -3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[1]
        set XposUnit = orderX + 100.0*(Cos(angle)) + 150.0*(Cos(angle+ 3.14159265/2))
        set YposUnit = orderY + 100.0*(Sin(angle)) + 150.0*(Sin(angle+ 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[2]
        set XposUnit = orderX - 100.0*(Cos(angle))
        set YposUnit = orderY - 100.0*(Sin(angle))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call EnableTrigger( GetTriggeringTrigger() )      
    elseif (counter == 5 ) then
        call DisableTrigger( GetTriggeringTrigger() )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[0]
        set XposUnit = orderX + 100.0*(Cos(angle)) + 300.0*(Cos(angle - 3.14159265/2))
        set YposUnit = orderY + 100.0*(Sin(angle)) + 300.0*(Sin(angle - 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[1]
        set XposUnit = orderX + 100.0*(Cos(angle))
        set YposUnit = orderY + 100.0*(Sin(angle))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[2]
        set XposUnit = orderX + 100.0*(Cos(angle)) + 300.0*(Cos(angle + 3.14159265/2))
        set YposUnit = orderY + 100.0*(Sin(angle)) + 300.0*(Sin(angle + 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[3]
        set XposUnit = orderX - 100.0*(Cos(angle)) + 150.0*(Cos(angle - 3.14159265/2))
        set YposUnit = orderY - 100.0*(Sin(angle)) + 150.0*(Sin(angle - 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[4]
        set XposUnit = orderX - 100.0*(Cos(angle)) + 150.0*(Cos(angle + 3.14159265/2))
        set YposUnit = orderY - 100.0*(Sin(angle)) + 150.0*(Sin(angle + 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )        
        call EnableTrigger( GetTriggeringTrigger() )
    elseif (counter == 6 ) then
        call DisableTrigger( GetTriggeringTrigger() )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[0]
        set XposUnit = orderX + 100.0*(Cos(angle)) + 300.0*(Cos(angle - 3.14159265/2))
        set YposUnit = orderY + 100.0*(Sin(angle)) + 200.0*(Sin(angle - 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[1]
        set XposUnit = orderX + 100.0*(Cos(angle))
        set YposUnit = orderY + 100.0*(Sin(angle))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[2]
        set XposUnit = orderX + 100.0*(Cos(angle)) + 300.0*(Cos(angle + 3.14159265/2))
        set YposUnit = orderY + 100.0*(Sin(angle)) + 300.0*(Sin(angle + 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[3]
        set XposUnit = orderX - 100.0*(Cos(angle)) + 300.0*(Cos(angle - 3.14159265/2))
        set YposUnit = orderY - 100.0*(Sin(angle)) + 300.0*(Sin(angle - 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[4]
        set XposUnit = orderX - 100.0*(Cos(angle))
        set YposUnit = orderY - 100.0*(Sin(angle))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[5]
        set XposUnit = orderX - 100.0*(Cos(angle)) + 300.0*(Cos(angle + 3.14159265/2))
        set YposUnit = orderY - 100.0*(Sin(angle)) + 300.0*(Sin(angle + 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )        
        call EnableTrigger( GetTriggeringTrigger() )
   elseif (counter == 7 ) then
        call DisableTrigger( GetTriggeringTrigger() )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[0]
        set XposUnit = orderX + 200.0*(Cos(angle)) + 300.0*(Cos(angle - 3.14159265/2))
        set YposUnit = orderY + 200.0*(Sin(angle)) + 300.0*(Sin(angle - 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[1]
        set XposUnit = orderX + 200.0*(Cos(angle))
        set YposUnit = orderY + 200.0*(Sin(angle))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[2]
        set XposUnit = orderX + 100.0*(Cos(angle)) + 300.0*(Cos(angle + 3.14159265/2))
        set YposUnit = orderY + 100.0*(Sin(angle)) + 300.0*(Sin(angle + 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[3]
        set XposUnit = orderX - 00.0*(Cos(angle)) + 300.0*(Cos(angle - 3.14159265/2))
        set YposUnit = orderY - 00.0*(Sin(angle)) + 300.0*(Sin(angle - 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[4]
        set XposUnit = orderX - 00.0*(Cos(angle))
        set YposUnit = orderY - 00.0*(Sin(angle))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[5]
        set XposUnit = orderX - 00.0*(Cos(angle)) + 300.0*(Cos(angle + 3.14159265/2))
        set YposUnit = orderY - 00.0*(Sin(angle)) + 300.0*(Sin(angle + 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[6]
        set XposUnit = orderX - 200.0*(Cos(angle))
        set YposUnit = orderY - 200.0*(Sin(angle))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )        
        call EnableTrigger( GetTriggeringTrigger() )
   elseif (counter == 8 ) then
        call DisableTrigger( GetTriggeringTrigger() )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[0]
        set XposUnit = orderX + 200.0*(Cos(angle)) + 300.0*(Cos(angle - 3.14159265/2))
        set YposUnit = orderY + 200.0*(Sin(angle)) + 300.0*(Sin(angle - 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[1]
        set XposUnit = orderX + 200.0*(Cos(angle))
        set YposUnit = orderY + 200.0*(Sin(angle))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[2]
        set XposUnit = orderX + 200.0*(Cos(angle)) + 300.0*(Cos(angle + 3.14159265/2))
        set YposUnit = orderY + 200.0*(Sin(angle)) + 300.0*(Sin(angle + 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[3]
        set XposUnit = orderX - 00.0*(Cos(angle)) + 300.0*(Cos(angle - 3.14159265/2))
        set YposUnit = orderY - 00.0*(Sin(angle)) + 300.0*(Sin(angle - 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[4]
        set XposUnit = orderX - 00.0*(Cos(angle))
        set YposUnit = orderY - 00.0*(Sin(angle))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[5]
        set XposUnit = orderX - 00.0*(Cos(angle)) + 300.0*(Cos(angle + 3.14159265/2))
        set YposUnit = orderY - 00.0*(Sin(angle)) + 300.0*(Sin(angle + 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[6]
        set XposUnit = orderX - 200.0*(Cos(angle)) + 150.0*(Cos(angle - 3.14159265/2))
        set YposUnit = orderY - 200.0*(Sin(angle)) + 150.0*(Sin(angle - 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[7]
        set XposUnit = orderX - 200.0*(Cos(angle)) + 150.0*(Cos(angle + 3.14159265/2))
        set YposUnit = orderY - 200.0*(Sin(angle)) + 150.0*(Sin(angle + 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )        
        call EnableTrigger( GetTriggeringTrigger() )      
   elseif (counter == 9 ) then
        call DisableTrigger( GetTriggeringTrigger() )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[0]
        set XposUnit = orderX + 200.0*(Cos(angle)) + 300.0*(Cos(angle - 3.14159265/2))
        set YposUnit = orderY + 200.0*(Sin(angle)) + 300.0*(Sin(angle - 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[1]
        set XposUnit = orderX + 200.0*(Cos(angle))
        set YposUnit = orderY + 200.0*(Sin(angle))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[2]
        set XposUnit = orderX + 200.0*(Cos(angle)) + 300.0*(Cos(angle + 3.14159265/2))
        set YposUnit = orderY + 200.0*(Sin(angle)) + 300.0*(Sin(angle + 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[3]
        set XposUnit = orderX - 00.0*(Cos(angle)) + 300.0*(Cos(angle - 3.14159265/2))
        set YposUnit = orderY - 00.0*(Sin(angle)) + 300.0*(Sin(angle - 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[4]
        set XposUnit = orderX - 00.0*(Cos(angle))
        set YposUnit = orderY - 00.0*(Sin(angle))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[5]
        set XposUnit = orderX - 00.0*(Cos(angle)) + 300.0*(Cos(angle + 3.14159265/2))
        set YposUnit = orderY - 00.0*(Sin(angle)) + 300.0*(Sin(angle + 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[6]
        set XposUnit = orderX - 200.0*(Cos(angle)) + 300.0*(Cos(angle - 3.14159265/2))
        set YposUnit = orderY - 200.0*(Sin(angle)) + 300.0*(Sin(angle - 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[7]
        set XposUnit = orderX - 200.0*(Cos(angle))
        set YposUnit = orderY - 200.0*(Sin(angle))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )  
        call TriggerWaitForSound(null, 0)
        set wanderer = units[8]
        set XposUnit = orderX - 200.0*(Cos(angle)) + 300.0*(Cos(angle + 3.14159265/2))
        set YposUnit = orderY - 200.0*(Sin(angle)) + 300.0*(Sin(angle + 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )  
        call EnableTrigger( GetTriggeringTrigger() )
   elseif (counter == 10 ) then
        call DisableTrigger( GetTriggeringTrigger() )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[0]
        set XposUnit = orderX + 200.0*(Cos(angle)) + 450.0*(Cos(angle - 3.14159265/2))
        set YposUnit = orderY + 200.0*(Sin(angle)) + 450.0*(Sin(angle - 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[1]
        set XposUnit = orderX + 200.0*(Cos(angle)) + 150.0*(Cos(angle - 3.14159265/2))
        set YposUnit = orderY + 200.0*(Sin(angle)) + 150.0*(Sin(angle - 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[2]
        set XposUnit = orderX + 200.0*(Cos(angle)) + 150.0*(Cos(angle + 3.14159265/2))
        set YposUnit = orderY + 200.0*(Sin(angle)) + 150.0*(Sin(angle + 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[3]
        set XposUnit = orderX + 200.0*(Cos(angle)) + 450.0*(Cos(angle + 3.14159265/2))
        set YposUnit = orderY + 200.0*(Sin(angle)) + 450.0*(Sin(angle + 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )        
        call TriggerWaitForSound(null, 0)
        set wanderer = units[4]
        set XposUnit = orderX - 00.0*(Cos(angle)) + 450.0*(Cos(angle - 3.14159265/2))
        set YposUnit = orderY - 00.0*(Sin(angle)) + 450.0*(Sin(angle - 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[5]
        set XposUnit = orderX - 00.0*(Cos(angle)) + 150.0*(Cos(angle - 3.14159265/2))
        set YposUnit = orderY - 00.0*(Sin(angle)) + 150.0*(Sin(angle - 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[6]
        set XposUnit = orderX - 00.0*(Cos(angle)) + 150.0*(Cos(angle + 3.14159265/2))
        set YposUnit = orderY - 00.0*(Sin(angle)) + 150.0*(Sin(angle + 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[7]
        set XposUnit = orderX - 00.0*(Cos(angle)) + 450.0*(Cos(angle + 3.14159265/2))
        set YposUnit = orderY - 00.0*(Sin(angle)) + 450.0*(Sin(angle + 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )        
        call TriggerWaitForSound(null, 0)
        set wanderer = units[8]
        set XposUnit = orderX - 200.0*(Cos(angle)) + 150.0*(Cos(angle - 3.14159265/2))
        set YposUnit = orderY - 200.0*(Sin(angle)) + 150.0*(Sin(angle - 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[9]
        set XposUnit = orderX - 200.0*(Cos(angle)) + 150.0*(Cos(angle + 3.14159265/2))
        set YposUnit = orderY - 200.0*(Sin(angle)) + 150.0*(Sin(angle + 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )  
        call EnableTrigger( GetTriggeringTrigger() )
   elseif (counter == 11 ) then
        call DisableTrigger( GetTriggeringTrigger() )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[0]
        set XposUnit = orderX + 200.0*(Cos(angle)) + 450.0*(Cos(angle - 3.14159265/2))
        set YposUnit = orderY + 200.0*(Sin(angle)) + 450.0*(Sin(angle - 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[1]
        set XposUnit = orderX + 200.0*(Cos(angle)) + 150.0*(Cos(angle - 3.14159265/2))
        set YposUnit = orderY + 200.0*(Sin(angle)) + 150.0*(Sin(angle - 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[2]
        set XposUnit = orderX + 200.0*(Cos(angle)) + 150.0*(Cos(angle + 3.14159265/2))
        set YposUnit = orderY + 200.0*(Sin(angle)) + 150.0*(Sin(angle + 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[3]
        set XposUnit = orderX + 200.0*(Cos(angle)) + 450.0*(Cos(angle + 3.14159265/2))
        set YposUnit = orderY + 200.0*(Sin(angle)) + 450.0*(Sin(angle + 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )        
        call TriggerWaitForSound(null, 0)
        set wanderer = units[4]
        set XposUnit = orderX - 00.0*(Cos(angle)) + 450.0*(Cos(angle - 3.14159265/2))
        set YposUnit = orderY - 00.0*(Sin(angle)) + 450.0*(Sin(angle - 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[5]
        set XposUnit = orderX - 00.0*(Cos(angle)) + 150.0*(Cos(angle - 3.14159265/2))
        set YposUnit = orderY - 00.0*(Sin(angle)) + 150.0*(Sin(angle - 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[6]
        set XposUnit = orderX - 00.0*(Cos(angle)) + 150.0*(Cos(angle + 3.14159265/2))
        set YposUnit = orderY - 00.0*(Sin(angle)) + 150.0*(Sin(angle + 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[7]
        set XposUnit = orderX - 00.0*(Cos(angle)) + 450.0*(Cos(angle + 3.14159265/2))
        set YposUnit = orderY - 00.0*(Sin(angle)) + 450.0*(Sin(angle + 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )        
        call TriggerWaitForSound(null, 0)
        set wanderer = units[8]
        set XposUnit = orderX - 200.0*(Cos(angle)) + 300.0*(Cos(angle - 3.14159265/2))
        set YposUnit = orderY - 200.0*(Sin(angle)) + 300.0*(Sin(angle - 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[9]
        set XposUnit = orderX - 200.0*(Cos(angle))
        set YposUnit = orderY - 200.0*(Sin(angle))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )  
        call TriggerWaitForSound(null, 0)
        set wanderer = units[10]
        set XposUnit = orderX - 200.0*(Cos(angle)) + 300.0*(Cos(angle + 3.14159265/2))
        set YposUnit = orderY - 200.0*(Sin(angle)) + 300.0*(Sin(angle + 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )  
        call EnableTrigger( GetTriggeringTrigger() )
   elseif (counter == 12 ) then
        call DisableTrigger( GetTriggeringTrigger() )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[0]
        set XposUnit = orderX + 200.0*(Cos(angle)) + 450.0*(Cos(angle - 3.14159265/2))
        set YposUnit = orderY + 200.0*(Sin(angle)) + 450.0*(Sin(angle - 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[1]
        set XposUnit = orderX + 200.0*(Cos(angle)) + 150.0*(Cos(angle - 3.14159265/2))
        set YposUnit = orderY + 200.0*(Sin(angle)) + 150.0*(Sin(angle - 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[2]
        set XposUnit = orderX + 200.0*(Cos(angle)) + 150.0*(Cos(angle + 3.14159265/2))
        set YposUnit = orderY + 200.0*(Sin(angle)) + 150.0*(Sin(angle + 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[3]
        set XposUnit = orderX + 200.0*(Cos(angle)) + 450.0*(Cos(angle + 3.14159265/2))
        set YposUnit = orderY + 200.0*(Sin(angle)) + 450.0*(Sin(angle + 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )        
        call TriggerWaitForSound(null, 0)
        set wanderer = units[4]
        set XposUnit = orderX - 00.0*(Cos(angle)) + 450.0*(Cos(angle - 3.14159265/2))
        set YposUnit = orderY - 00.0*(Sin(angle)) + 450.0*(Sin(angle - 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[5]
        set XposUnit = orderX - 00.0*(Cos(angle)) + 150.0*(Cos(angle - 3.14159265/2))
        set YposUnit = orderY - 00.0*(Sin(angle)) + 100.0*(Sin(angle - 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[6]
        set XposUnit = orderX - 00.0*(Cos(angle)) + 150.0*(Cos(angle + 3.14159265/2))
        set YposUnit = orderY - 00.0*(Sin(angle)) + 150.0*(Sin(angle + 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[7]
        set XposUnit = orderX - 00.0*(Cos(angle)) + 450.0*(Cos(angle + 3.14159265/2))
        set YposUnit = orderY - 00.0*(Sin(angle)) + 450.0*(Sin(angle + 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )        
        call TriggerWaitForSound(null, 0)
        set wanderer = units[8]
        set XposUnit = orderX - 200.0*(Cos(angle)) + 450.0*(Cos(angle - 3.14159265/2))
        set YposUnit = orderY - 200.0*(Sin(angle)) + 450.0*(Sin(angle - 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)
        set wanderer = units[9]
        set XposUnit = orderX - 200.0*(Cos(angle)) + 150.0*(Cos(angle - 3.14159265/2))
        set YposUnit = orderY - 200.0*(Sin(angle)) + 150.0*(Sin(angle - 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)        
        set wanderer = units[10]
        set XposUnit = orderX - 200.0*(Cos(angle)) + 150.0*(Cos(angle + 3.14159265/2))
        set YposUnit = orderY - 200.0*(Sin(angle)) + 150.0*(Sin(angle + 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )
        call TriggerWaitForSound(null, 0)        
        set wanderer = units[11]
        set XposUnit = orderX - 200.0*(Cos(angle)) + 450.0*(Cos(angle + 3.14159265/2))
        set YposUnit = orderY - 200.0*(Sin(angle)) + 450.0*(Sin(angle + 3.14159265/2))
        call IssuePointOrderById( wanderer, order, XposUnit, YposUnit )          
        call EnableTrigger( GetTriggeringTrigger() )
    endif
    endif
    set wanderer = null
    //call GroupClear(udg_AI_Movement[GetConvertedPlayerId(GetOwningPlayer(GetOrderedUnit()))])
    call DestroyGroup(tempgroup)
endfunction

//===========================================================================
function InitTrig_Move_to_point_Compy takes nothing returns nothing
    set gg_trg_Move_to_point_Compy = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Move_to_point_Compy, EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER )
    call TriggerAddCondition( gg_trg_Move_to_point_Compy, Condition(function Trig_Move_to_point_Compy_Conditions) )
    call TriggerAddAction( gg_trg_Move_to_point_Compy, function Trig_Move_to_point_Compy_Actions )
endfunction

 
Make a wandering unit belonging to a batalion returning back if straying too far. After catching the wanderer, run a Regroup wait trigger. This trigger may be potentially demanding and should not have leaks.
//TESH.scrollpos=0
//TESH.alwaysfold=0
function Trig_Regroup_Actions takes nothing returns nothing
    local real Xpos
    local real Ypos
    local integer order
    local integer i = 1
    local unit wanderer
    local unit commander
    local unit target
    local group batalion = CreateGroup()
    loop
        exitwhen i > udg_BattallionCount
        if ( not ( IsUnitGroupEmptyBJ( udg_Battallion[i] ) ) ) then
            set commander = GetCaptain(udg_Battallion[i])
            call GroupAddGroup( udg_Battallion[i], batalion )
            loop
                set wanderer = FirstOfGroup(batalion)
                exitwhen (wanderer == null)
                set Xpos = GetUnitX(wanderer) - GetUnitX(commander)
                set Ypos = GetUnitY(wanderer) - GetUnitY(commander)
                if ( SquareRoot( Xpos*Xpos + Ypos*Ypos ) >= udg_BattallionRegroup and not (IsUnitInGroup(wanderer, udg_BattallionQueued ) ) ) then
                    set udg_Tempunit = wanderer
                    set udg_TempCommander = commander
                    call IssuePointOrder( wanderer, "move", GetUnitX(commander), GetUnitY(commander) )
                    call TriggerExecute( gg_trg_Regroup_wait )
                endif
                call GroupRemoveUnit(batalion, wanderer)
                set wanderer = null
            endloop
            call GroupClear( batalion )
            set commander = null
        endif
        set i = i + 1
    endloop
    //call DestroyGroup( batalion )
endfunction

//===========================================================================
function InitTrig_Regroup takes nothing returns nothing
    set gg_trg_Regroup = CreateTrigger(  )
    call TriggerRegisterTimerEventPeriodic( gg_trg_Regroup, 2.0)
    call TriggerAddAction( gg_trg_Regroup, function Trig_Regroup_Actions )
endfunction

 
Order the wandering unit to have the same order as the leader's current order.
//TESH.scrollpos=4
//TESH.alwaysfold=0
function Trig_Regroup_wait_Actions takes nothing returns nothing
    local unit wanderer = udg_Tempunit
    local unit commander = udg_TempCommander
    local unit target
    local real Xpos
    local real Ypos
    local integer order
    local integer battallionIndex = LoadInteger(udg_hashtable, GetHandleId(commander), 0)
    call IssuePointOrder( wanderer, "move", GetUnitX(commander), GetUnitY(commander) )
    call GroupAddUnit( udg_BattallionQueued, wanderer )
    loop
        set commander = GetCaptain( udg_Battallion[battallionIndex] )
        set Xpos = GetUnitX(wanderer) - GetUnitX(commander)
        set Ypos = GetUnitY(wanderer) - GetUnitY(commander)        
        exitwhen ( SquareRoot( Xpos*Xpos + Ypos*Ypos ) <= 150 or IsUnitDeadBJ( wanderer ) or IsUnitDeadBJ( commander ) )
        call IssuePointOrder(wanderer, "move", GetUnitX(commander), GetUnitY(commander) )
        call TriggerSleepAction( 0.5 )
    endloop
    set Xpos = LoadReal( udg_hashtable, GetHandleId(commander) , udg_BatalionHash_TargetX)
    set Ypos = LoadReal( udg_hashtable, GetHandleId(commander) , udg_BatalionHash_TargetY)
    set order = LoadInteger( udg_hashtable, GetHandleId(commander), udg_BatalionHash_Order )
    set target = LoadUnitHandle( udg_hashtable, GetHandleId(commander), udg_BatalionHash_TargetUnit )
    if ( order != 0 and GetUnitCurrentOrder(commander) != String2OrderIdBJ("") ) then
        if ( target == null ) then
            //call BJDebugMsg("pointing")
            call IssuePointOrderById(wanderer, order, Xpos, Ypos )
        else
            //call BJDebugMsg("acquiring")
            call IssueTargetOrderById(wanderer, order, target )
        endif
    endif
    set target = null
    call GroupRemoveUnit( udg_BattallionQueued, wanderer )
endfunction

//===========================================================================
function InitTrig_Regroup_wait takes nothing returns nothing
    set gg_trg_Regroup_wait = CreateTrigger(  )
    call TriggerAddAction( gg_trg_Regroup_wait, function Trig_Regroup_wait_Actions )
endfunction

 
A shortcut for reinforcing batalion, so there is no need to select the building first.
Auto reinforce
  Events
    Unit - A unit Begins casting an ability
  Conditions
    (Owner of (Target unit of ability being cast)) Equal to (Owner of (Casting unit))
    ((Casting unit) is A structure) Equal to False
    (Ability being cast) Equal to Reinforce (Battalion)
  Actions
    Unit - Order (Target unit of ability being cast) to Orc Shadow Hunter - Hex.(Casting unit)
Reinforce a batalion to the full strength or less if not enough resources.
//TESH.scrollpos=0
//TESH.alwaysfold=0
function Trig_Battalion_reinforce_Conditions takes nothing returns boolean
    if ( GetSpellAbilityId() == 'A002' and LoadInteger(udg_hashtable, GetHandleId(GetSpellTargetUnit()), 1) == 1 and LoadInteger(udg_hashtable, GetHandleId(GetSpellTargetUnit()), udg_Summon) == 0 and IsUnitType(GetSpellAbilityUnit(), UNIT_TYPE_STRUCTURE) == true)  then
        return true
    else
        return false
    endif
endfunction

function Trig_Battalion_reinforce_Actions takes nothing returns nothing
    local integer captain = IsCaptain(GetUnitTypeId(GetSpellTargetUnit()))
    local integer battallionIndex = LoadInteger(udg_hashtable, GetHandleId(GetSpellTargetUnit()), 0)
    local integer size = CountUnitsInGroup(udg_Battallion[battallionIndex])
    local location temppoint1 = GetUnitLoc(GetSpellTargetUnit())
    local unit reinforcedUnit = GetSpellTargetUnit()
    loop
        exitwhen size > udg_BattalionSize[captain]
        if ( GetPlayerState(GetOwningPlayer(reinforcedUnit), PLAYER_STATE_RESOURCE_GOLD) >= udg_BattalionGoldCost[captain] and GetPlayerState(GetOwningPlayer(reinforcedUnit), PLAYER_STATE_RESOURCE_LUMBER) >= udg_BattalionPowerCost[captain] ) then
            //call BJDebugMsg("reinforcing")
            call SetPlayerState(GetOwningPlayer(reinforcedUnit), PLAYER_STATE_RESOURCE_GOLD, GetPlayerState(GetOwningPlayer(reinforcedUnit), PLAYER_STATE_RESOURCE_GOLD) - udg_BattalionGoldCost[captain])
            call SetPlayerState(GetOwningPlayer(reinforcedUnit), PLAYER_STATE_RESOURCE_LUMBER, GetPlayerState(GetOwningPlayer(reinforcedUnit), PLAYER_STATE_RESOURCE_LUMBER) - udg_BattalionPowerCost[captain])
            set bj_lastCreatedUnit = CreateUnitAtLoc(ConvertedPlayer( GetConvertedPlayerId(GetOwningPlayer(reinforcedUnit)) + udg_TranslatePlayerNumber ), udg_BattalionTroop[captain], temppoint1, bj_UNIT_FACING)
            call SetUnitColor( GetLastCreatedUnit(), GetPlayerColor(GetOwningPlayer(reinforcedUnit)) )
            call GroupAddUnit( udg_Battallion[battallionIndex], GetLastCreatedUnit() )
            call SaveInteger( udg_hashtable, GetHandleId(GetLastCreatedUnit()),  0, battallionIndex )
            call RemoveGuardPosition( GetLastCreatedUnit() )
            call IssueTargetOrder( GetLastCreatedUnit(), "move", reinforcedUnit )
        else
            call DisplayTextToForce( GetForceOfPlayer(GetOwningPlayer(GetSpellTargetUnit())), "Not enough resources" )
            call RemoveLocation(temppoint1)
            return
        endif
        set size = size + 1
    endloop
    call RemoveLocation(temppoint1)
    set reinforcedUnit = null
endfunction

//===========================================================================
function InitTrig_Battalion_reinforce takes nothing returns nothing
    set gg_trg_Battalion_reinforce = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Battalion_reinforce, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Battalion_reinforce, Condition( function Trig_Battalion_reinforce_Conditions ) )
    call TriggerAddAction( gg_trg_Battalion_reinforce, function Trig_Battalion_reinforce_Actions )
endfunction
Create units accompanying just created batalion leader.
//TESH.scrollpos=21
//TESH.alwaysfold=0
function Trig_Battalion_train_Conditions takes nothing returns boolean
    if ( IsCaptain(GetUnitTypeId(GetTrainedUnit())) > 0 ) then
        set udg_Tempunit = GetTrainedUnit()
        return true
    endif
    return false
endfunction

function Trig_Battalion_train_Actions takes nothing returns nothing
    local unit trigger_unit = udg_Tempunit
    local integer captain = IsCaptain(GetUnitTypeId(trigger_unit))
    local integer batallionIndex = 1
    local integer size = 1
    local boolean found = false
    local location temppoint1 = GetUnitLoc(trigger_unit)
    local location temppoint2
    loop
        exitwhen batallionIndex > 8911 or found == true
        if ( IsUnitGroupEmptyBJ(udg_Battallion[batallionIndex]) == true ) then
            call GroupAddUnit( udg_Battallion[batallionIndex], trigger_unit )
            call SaveInteger( udg_hashtable, GetHandleId(trigger_unit),  0, batallionIndex )
            call SaveInteger( udg_hashtable, GetHandleId(trigger_unit), 1, 1 )
           
            // Drider
            //if ( udg_Status[captain] > udg_BatalionHash_Guards ) then
            //    call SaveInteger( udg_hashtable, GetHandleId(trigger_unit), udg_Summon, udg_BatalionHash_Guards )
            //endif
            // Machinery
            //if ( udg_Status[captain] == udg_BatalionHash_Crew ) then
            //    call SaveInteger( udg_hashtable, GetHandleId(trigger_unit), udg_Summon, udg_BatalionHash_Crew )
            //endif
           
            if ( udg_Status[captain] > 0 ) then
                call SaveInteger( udg_hashtable, GetHandleId(trigger_unit), udg_Summon, udg_Status[captain] )
            endif
           
            loop
                exitwhen size > udg_BattalionSize[captain] or udg_Status[captain] == udg_BatalionHash_Guards
                set temppoint2 = PolarProjectionBJ(temppoint1, GetRandomReal(0, 50.00), GetRandomDirectionDeg() )
                set bj_lastCreatedUnit = CreateUnitAtLoc(ConvertedPlayer( GetConvertedPlayerId(GetOwningPlayer(trigger_unit)) + udg_TranslatePlayerNumber ), udg_BattalionTroop[captain], temppoint2, bj_UNIT_FACING)
                call SetUnitColor( GetLastCreatedUnit(), GetPlayerColor(GetOwningPlayer(trigger_unit)) )
                call SaveInteger( udg_hashtable, GetHandleId(GetLastCreatedUnit()),  0, batallionIndex )
                call GroupAddUnit( udg_Battallion[batallionIndex], GetLastCreatedUnit() )
                call RemoveGuardPosition( GetLastCreatedUnit() )
                //call IssueTargetOrder( GetLastCreatedUnit(), "move", GetTrainedUnit() )
               
                // Machinery
                if ( udg_Status[captain] == udg_BatalionHash_Crew ) then
                    call UnitRemoveAbility( GetLastCreatedUnit(), 'A01A' )
                endif
                //if ( udg_Status[captain] == udg_BatalionHash_Summonable ) then
                //    call SaveInteger( udg_hashtable, GetHandleId(GetLastCreatedUnit()), udg_Summon, udg_BatalionHash_Summonable )
                //    call UnitApplyTimedLife( GetLastCreatedUnit(), 'BTLF', 20 )
                //endif
               
                if ( udg_Status[captain] > 0 ) then
                    call SaveInteger( udg_hashtable, GetHandleId(GetLastCreatedUnit()), udg_Summon, udg_Status[captain] )
                    if ( udg_Status[captain] == udg_BatalionHash_Summonable ) then
                        call UnitApplyTimedLife( GetLastCreatedUnit(), 'BTLF', 20 )
                    endif
                endif
               
                set size = size + 1
            endloop
            set found = true
        endif
        set batallionIndex = batallionIndex + 1
    endloop
    set udg_BattallionCount = udg_BattallionCount + 1
    call RemoveLocation(temppoint1)
    call RemoveLocation(temppoint2)
endfunction

//===========================================================================
function InitTrig_Battalion_train takes nothing returns nothing
    set gg_trg_Battalion_train = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Battalion_train, EVENT_PLAYER_UNIT_TRAIN_FINISH )
    call TriggerAddCondition( gg_trg_Battalion_train, Condition( function Trig_Battalion_train_Conditions ) )
    call TriggerAddAction( gg_trg_Battalion_train, function Trig_Battalion_train_Actions )
endfunction

 
Memorize currently selected units to show the current number of units in the batalion and to preserve selection if one of selected leader falls in the battle.
Selection Selection thingie
  Events
    Player - Player 1 (Red) Selects a unit
    Player - Player 2 (Blue) Selects a unit
    Player - Player 3 (Teal) Selects a unit
    Player - Player 4 (Purple) Selects a unit
    Player - Player 5 (Yellow) Selects a unit
    Player - Player 6 (Orange) Selects a unit
    Player - Player 7 (Green) Selects a unit
    Player - Player 8 (Pink) Selects a unit
  Conditions
    (Load 0 of (Key (Triggering unit).) from hashtable.) Greater than 0
    (Load 1 of (Key (Triggering unit).) from hashtable.) Equal to 1
    (Owner of (Triggering unit)) Equal to (Triggering player)
    ((Triggering player) controller) Equal to User
    ((Triggering unit) is A Hero) Equal to False
  Actions
    Unit Group - Add (Triggering unit) to Selected1[(Player number of (Triggering player))]
    Set VariableSet BattallionIndex = (Load 0 of (Key (Triggering unit).) from hashtable.)
    Floating Text - Create floating text that reads (String((Number of units in Battallion[BattallionIndex]))) above (Triggering unit) with Z offset 0, using font size 10, color (100.00%, 0.00%, 0.00%), and 0% transparency
    Floating Text - Hide (Last created floating text) for (All players)
    Floating Text - Show (Last created floating text) for (Player group((Owner of (Triggering unit))))
    Floating Text - Change (Last created floating text): Disable permanence
    Floating Text - Change the lifespan of (Last created floating text) to 1.00 seconds
Memorize currently selected units to preserve selection if one of selected leader falls in the battle.
Deselection Selection thingie
  Events
    Player - Player 1 (Red) Deselects a unit
    Player - Player 2 (Blue) Deselects a unit
    Player - Player 3 (Teal) Deselects a unit
    Player - Player 4 (Purple) Deselects a unit
    Player - Player 5 (Yellow) Deselects a unit
    Player - Player 6 (Orange) Deselects a unit
    Player - Player 7 (Green) Deselects a unit
    Player - Player 8 (Pink) Deselects a unit
  Conditions
    (Load 0 of (Key (Triggering unit).) from hashtable.) Greater than 0
    (Load 1 of (Key (Triggering unit).) from hashtable.) Equal to 1
    (Owner of (Triggering unit)) Equal to (Triggering player)
    ((Triggering player) controller) Equal to User
  Actions
    Unit Group - Remove (Triggering unit) from Selected1[(Player number of (Triggering player))].
Support for transport of batalions. Should be leak free.
//TESH.scrollpos=9
//TESH.alwaysfold=0
function Trig_UnLoad_Conditions takes nothing returns boolean
    if ( IsCaptain(GetUnitTypeId(GetTriggerUnit())) > 0 ) then
        return true
    else
        return false
    endif
    return false
endfunction

function UnitHide takes nothing returns nothing
    if ( GetEnumUnit() != GetLoadedUnit() ) then
        call ShowUnit(GetEnumUnit(), false)
    endif
endfunction

function UnitShow takes nothing returns nothing
    if ( GetEnumUnit() != GetLoadedUnit() ) then
        call ShowUnit(GetEnumUnit(), true)
        call SetUnitPosition( GetEnumUnit(), GetUnitX(GetLoadedUnit()), GetUnitY(GetLoadedUnit()) )
    endif
endfunction

function Trig_UnLoad_Actions takes nothing returns nothing
    local integer battallionIndex = LoadInteger(udg_hashtable, GetHandleId(GetLoadedUnit()), 0)
    call ForGroup( udg_Battallion[battallionIndex] , function UnitHide )
    loop
        exitwhen ( IsUnitInTransport(GetTriggerUnit(), GetTransportUnit()) == false )
        call TriggerSleepAction( 0.5 )
    endloop
    call ForGroup( udg_Battallion[battallionIndex] , function UnitShow )
endfunction

//===========================================================================
function InitTrig_UnLoad takes nothing returns nothing
    set gg_trg_UnLoad = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_UnLoad, EVENT_PLAYER_UNIT_LOADED )
    call TriggerAddCondition( gg_trg_UnLoad, Condition( function Trig_UnLoad_Conditions ) )
    call TriggerAddAction( gg_trg_UnLoad, function Trig_UnLoad_Actions )
endfunction

 
Apply research also to batalion units.
Research
  Events
    Unit - A unit Finishes research
  Conditions
  Actions
    Player - Set the current research level of (Researched tech-type) to (Current research level of (Researched tech-type) for (Owner of (Researching unit))) for (Player(((Player number of (Owner of (Researching unit))) + TranslatePlayerNumber)))
Order batalion units to follow leader's order which targets a unit. Store the order.
//TESH.scrollpos=0
//TESH.alwaysfold=0
function Trig_Battalion_order_target_Conditions takes nothing returns boolean
    if ( LoadInteger(udg_hashtable, GetHandleId(GetOrderedUnit()), 1) == 1 and LoadInteger(udg_hashtable, GetHandleIdBJ(GetOrderedUnit()), udg_Summon) != 2) then
        return true
    else
        return false
    endif
endfunction

function Trig_Battalion_order_target_Actions takes nothing returns nothing
    local unit orderunit = GetOrderedUnit()
    local unit target = GetOrderTargetUnit()
    local integer generalOrder = GetIssuedOrderId()
    local integer BattallionIndex = LoadInteger(udg_hashtable, GetHandleId(GetOrderedUnit()), 0)
    //call DisableTrigger( GetTriggeringTrigger() )
    call GroupRemoveUnit( udg_Battallion[BattallionIndex], orderunit )
    call SaveInteger( udg_hashtable, GetHandleId(orderunit), udg_BatalionHash_Order, generalOrder )
    call SaveUnitHandle( udg_hashtable, GetHandleId(GetOrderedUnit()), udg_BatalionHash_TargetUnit, GetOrderTargetUnit() )
    call SaveReal( udg_hashtable, GetHandleId(orderunit), udg_BatalionHash_TargetX, 0 )
    call SaveReal( udg_hashtable, GetHandleId(orderunit), udg_BatalionHash_TargetY, 0 )
    if ( GetOrderAbility( generalOrder, GetUnitTypeId(orderunit) ) > 0 ) then
        call GroupTargetOrder( udg_Battallion[BattallionIndex], "move", orderunit)
    else
        call GroupTargetOrderById( udg_Battallion[BattallionIndex], generalOrder, target)
    endif
    call GroupAddUnit( udg_Battallion[BattallionIndex], orderunit )
    set target = null
    set orderunit = null
    //call EnableTrigger( GetTriggeringTrigger() )
endfunction

//===========================================================================
function InitTrig_Battalion_order_target takes nothing returns nothing
    set gg_trg_Battalion_order_target = CreateTrigger(  )
    //call DisableTrigger( gg_trg_Battalion_order_target )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Battalion_order_target, EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER )
    call TriggerAddCondition( gg_trg_Battalion_order_target, Condition( function Trig_Battalion_order_target_Conditions ) )
    call TriggerAddAction( gg_trg_Battalion_order_target, function Trig_Battalion_order_target_Actions )
endfunction

 
Order batalion units to follow leader's order which has no targets, immediate order. Store the order.
//TESH.scrollpos=21
//TESH.alwaysfold=0
function Trig_Battalion_order_no_target_Conditions takes nothing returns boolean
    if ( LoadInteger(udg_hashtable, GetHandleIdBJ(GetOrderedUnit()), 1) == 1 and LoadInteger(udg_hashtable, GetHandleIdBJ(GetOrderedUnit()), udg_Summon) != 2 and IsUnitAliveBJ( GetOrderedUnit() ) ) then
        return true
    else
        return false
    endif
endfunction

function AddAbility takes nothing returns nothing
    call UnitAddAbility(GetEnumUnit(), udg_BattalionSpellAbility[GetOrderAbility(GetIssuedOrderId(), GetUnitTypeId(GetOrderedUnit()))])
endfunction

function RemoveAbility takes nothing returns nothing
    call UnitRemoveAbility(GetEnumUnit(), udg_BattalionSpellAbility[GetOrderAbility(GetIssuedOrderId(), GetUnitTypeId(GetOrderedUnit()))])
endfunction

function Trig_Battalion_order_no_target_Actions takes nothing returns nothing
    local integer generalOrder = GetIssuedOrderId()
    local unit orderunit = GetOrderedUnit()
    local integer BattallionIndex = LoadInteger(udg_hashtable, GetHandleId(GetOrderedUnit()), 0)
    //call DisableTrigger( GetTriggeringTrigger() )
    //call BJDebugMsg("call stop")
    call GroupRemoveUnit( udg_Battallion[BattallionIndex], orderunit )
    if ( GetOrderAbility( generalOrder, GetUnitTypeId(orderunit) ) > 0 ) then
        call ForGroup( udg_Battallion[BattallionIndex], function AddAbility )
        //call BJDebugMsg(I2S( GetOrderAbility( generalOrder, GetUnitTypeId(orderunit) ) ))
        //call BJDebugMsg(I2S( generalOrder ) )
    endif
   
    call GroupImmediateOrderById( udg_Battallion[BattallionIndex], generalOrder)
    call SaveReal( udg_hashtable, GetHandleId(orderunit), udg_BatalionHash_TargetX, 0 )
    call SaveReal( udg_hashtable, GetHandleId(orderunit), udg_BatalionHash_TargetY, 0 )
    call RemoveSavedHandle( udg_hashtable, GetHandleId(orderunit), udg_BatalionHash_TargetUnit)
    call TriggerSleepAction( 0.27 )
    if ( GetIssuedOrderId() == String2OrderIdBJ("stop") and GetUnitCurrentOrder(GetOrderedUnit()) == String2OrderIdBJ("") ) then
        call SaveInteger(udg_hashtable, GetHandleId(orderunit), udg_BatalionHash_Order, 0 )
    endif
    if ( GetOrderAbility( generalOrder, GetUnitTypeId(orderunit) ) > 0 ) then
        call ForGroup( udg_Battallion[BattallionIndex], function RemoveAbility )
        call IssueImmediateOrder(orderunit, "stop")
    endif
    call GroupAddUnit( udg_Battallion[BattallionIndex], orderunit )
    set orderunit = null
    //call EnableTrigger( GetTriggeringTrigger() )
endfunction

//===========================================================================
function InitTrig_Battalion_order_no_target takes nothing returns nothing
    set gg_trg_Battalion_order_no_target = CreateTrigger(  )
    //call DisableTrigger( gg_trg_Battalion_order_no_target )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Battalion_order_no_target, EVENT_PLAYER_UNIT_ISSUED_ORDER )
    call TriggerAddCondition( gg_trg_Battalion_order_no_target, Condition( function Trig_Battalion_order_no_target_Conditions ) )
    call TriggerAddAction( gg_trg_Battalion_order_no_target, function Trig_Battalion_order_no_target_Actions )
endfunction

 
Order batalion units to follow leader's order which targets a point. Store the order.
//TESH.scrollpos=11
//TESH.alwaysfold=0
function Trig_Battalion_order_point_Conditions takes nothing returns boolean
    if ( LoadInteger(udg_hashtable, GetHandleId(GetOrderedUnit()), 1) == 1 and LoadInteger(udg_hashtable, GetHandleId(GetOrderedUnit()), udg_Summon) != 2) then
        return true
    else
        return false
    endif
endfunction

function Trig_Battalion_order_point_Actions takes nothing returns nothing
    local real Xmove = GetOrderPointX()
    local real Ymove = GetOrderPointY()
    local integer generalOrder = GetIssuedOrderId()
    local unit orderunit = GetOrderedUnit()
    local integer BattallionIndex = LoadInteger(udg_hashtable, GetHandleId(GetOrderedUnit()), 0)
    call DisableTrigger( GetTriggeringTrigger() )
    call SaveInteger( udg_hashtable, GetHandleId(orderunit), udg_BatalionHash_Order, generalOrder )
    call SaveReal( udg_hashtable, GetHandleId(orderunit), udg_BatalionHash_TargetX, Xmove )
    call SaveReal( udg_hashtable, GetHandleId(orderunit), udg_BatalionHash_TargetY, Ymove )
    call RemoveSavedHandle( udg_hashtable, GetHandleId(orderunit), udg_BatalionHash_TargetUnit)
    if ( GetOrderAbility( generalOrder, GetUnitTypeId(orderunit) ) > 0 ) then
        call GroupRemoveUnit( udg_Battallion[BattallionIndex], orderunit )
        call GroupTargetOrder( udg_Battallion[BattallionIndex], "move", orderunit)
        call GroupAddUnit( udg_Battallion[BattallionIndex], orderunit )
    else    
        call GroupPointOrderById( udg_Battallion[BattallionIndex ], generalOrder, Xmove, Ymove)
    endif    
    set orderunit = null
    call EnableTrigger( GetTriggeringTrigger() )
endfunction

//===========================================================================
function InitTrig_Battalion_order_point takes nothing returns nothing
    set gg_trg_Battalion_order_point = CreateTrigger(  )
    //call DisableTrigger( gg_trg_Battalion_order_point )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Battalion_order_point, EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER )
    call TriggerAddCondition( gg_trg_Battalion_order_point, Condition( function Trig_Battalion_order_point_Conditions ) )
    call TriggerAddAction( gg_trg_Battalion_order_point, function Trig_Battalion_order_point_Actions )
endfunction

 
If dead unit is a leader, ressurect it and swap it with another random batalion unit and kill it to preserve ctrl groups. Apply the stored order to the ressurected leader.
//TESH.scrollpos=48
//TESH.alwaysfold=0
function Trig_Battalion_death_Ctrl_Conditions takes nothing returns boolean
    local integer status = LoadInteger(udg_hashtable, GetHandleId(GetDyingUnit()), udg_Summon)
    if ( status == udg_BatalionHash_Crew or status == udg_BatalionHash_Beast ) then
        return false
    else
        return true
    endif
endfunction

function KillAll takes nothing returns nothing
    call KillUnit( GetEnumUnit() )
endfunction

function Trig_Battalion_death_Ctrl_Actions takes nothing returns nothing
    local integer battallionIndex = LoadInteger(udg_hashtable, GetHandleId(GetDyingUnit()), 0)
    local integer tempint
    local real Xpos
    local real Ypos
    local boolean noOrder = false
    local unit tempunit = GetDyingUnit()
    local unit tempcommander
    local location temppoint1
    local location temppoint2
    local location temppoint3
    // Final death
    if ( CountUnitsInGroup(udg_Battallion[battallionIndex]) == 1 and battallionIndex > 0 ) then
        call GroupClear( udg_Battallion[battallionIndex])
        return
    endif
    // Drider
    if ( LoadInteger(udg_hashtable, GetHandleId(GetDyingUnit()), udg_Summon ) == udg_BatalionHash_Guards ) then
        call ForGroupBJ( udg_Battallion[battallionIndex], function KillAll )
        return
    endif
    // Common troop
    if ( LoadInteger(udg_hashtable, GetHandleId(GetDyingUnit()), 1 ) != 1 ) then
        call GroupRemoveUnit( udg_Battallion[battallionIndex], GetDyingUnit())
        return
    else
        call GroupRemoveUnit( udg_Battallion[battallionIndex], GetDyingUnit())
        //if ( LoadInteger(udg_hashtable, GetHandleId(GetDyingUnit()), udg_Summon ) == udg_BatalionHash_Summonable ) then
        //    set tempunit = GroupPickRandomUnit(udg_Battallion[battallionIndex])
        //    call ReplaceUnitBJ( udg_Tempunit, GetUnitTypeId(GetDyingUnit()), bj_UNIT_STATE_METHOD_RELATIVE )
        //    call SetUnitOwner( tempunit, GetOwningPlayer(GetDyingUnit()), true )
        //    call

    endif
    set tempunit = GroupPickRandomUnit(udg_Battallion[battallionIndex])
    if ( GetUnitCurrentOrder(tempunit) == String2OrderIdBJ("") ) then
        //call BJDebugMsg("no order")
        set noOrder = true
    endif
    call GroupAddUnit( udg_Battallion[battallionIndex], GetDyingUnit())
    set tempcommander = GetDyingUnit()
    set temppoint1 = GetUnitLoc(GetDyingUnit())
    set temppoint2 = GetUnitLoc(tempunit)
    set temppoint3 = GetRectCenter(GetPlayableMapRect())
    call DisableTrigger( GetTriggeringTrigger() )
    call DisableTrigger( gg_trg_Battalion_order_no_target )
    // dummy
    set bj_lastCreatedUnit = CreateUnitAtLoc(GetOwningPlayer(GetDyingUnit()), 'e001', temppoint1, bj_UNIT_FACING)
    call IssueImmediateOrder( bj_lastCreatedUnit, "resurrection" )
    call RemoveUnit( bj_lastCreatedUnit )
    // swap units
    call SetUnitPositionLoc( tempunit, temppoint3 )
    call SetUnitPositionLoc( GetDyingUnit(), temppoint2 )
    call SetUnitPositionLoc( tempunit, temppoint1 )
    // kill unit and remove from group
    call ReplaceUnitBJ( tempunit, GetUnitTypeId(GetDyingUnit()), bj_UNIT_STATE_METHOD_MAXIMUM )
    set tempunit = GetLastReplacedUnitBJ()
    call SetUnitOwner( tempunit, GetOwningPlayer(GetDyingUnit()), true )
    call KillUnit( tempunit )
    call GroupRemoveUnit( udg_Battallion[battallionIndex], tempunit )
    // reselect
    if ( IsUnitInGroup(GetDyingUnit(), udg_Selected1[GetConvertedPlayerId(GetOwningPlayer(GetDyingUnit()))]) == true ) then
        call SelectUnitAddForPlayer( GetDyingUnit(), GetOwningPlayer(GetDyingUnit()) )
    endif
    call EnableTrigger( gg_trg_Battalion_order_no_target )
    // pass order
    set Xpos = LoadReal( udg_hashtable, GetHandleId(tempcommander) , udg_BatalionHash_TargetX )
    set Ypos = LoadReal( udg_hashtable, GetHandleId(tempcommander) , udg_BatalionHash_TargetY )
    set tempint = LoadInteger( udg_hashtable, GetHandleId(tempcommander), udg_BatalionHash_Order )
    set tempunit = LoadUnitHandle( udg_hashtable, GetHandleId(tempcommander), udg_BatalionHash_TargetUnit )
    if ( tempint != 0 and not (noOrder) ) then
        if ( Xpos == 0 and Ypos == 0 ) then
            call IssueTargetOrderById(tempcommander, tempint, tempunit )
        else
            call IssuePointOrderById(tempcommander, tempint, Xpos, Ypos )
        endif
    endif
    call RemoveLocation(temppoint1)
    call RemoveLocation(temppoint2)
    call RemoveLocation(temppoint3)
    // prevent moving
    if (  GetPlayerController(GetOwningPlayer(GetDyingUnit())) == MAP_CONTROL_COMPUTER ) then
        call RemoveGuardPosition( tempcommander )
    endif
    set tempunit = null
    set tempcommander = null
    call EnableTrigger( GetTriggeringTrigger() )
endfunction

//===========================================================================
function InitTrig_Battalion_death_Ctrl takes nothing returns nothing
    set gg_trg_Battalion_death_Ctrl = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Battalion_death_Ctrl, EVENT_PLAYER_UNIT_DEATH )
    call TriggerAddCondition( gg_trg_Battalion_death_Ctrl, Condition( function Trig_Battalion_death_Ctrl_Conditions ) )
    call TriggerAddAction( gg_trg_Battalion_death_Ctrl, function Trig_Battalion_death_Ctrl_Actions )
endfunction

 
Generate a bataltion for each batalion unit on the map at the start.
Autogenerate battallions
  Events
    Time - Elapsed game time is 1.00 seconds
  Conditions
  Actions
    For each (Integer Tempint) from 1 to NrTypes, do (Actions)
      Loop - Actions
        Unit Group - Pick every unit in (Units of type BattalionCaptain[Tempint]) and do (Actions)
          Loop - Actions
            Custom script: local location udg_Temppoint01 = GetUnitLoc(GetEnumUnit())
            For each (Integer A) from 1 to BattallionLimit, do (Actions)
              Loop - Actions
                If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                  If - Conditions
                    (Battallion[(Integer A)] is empty) Equal to True
                    check Equal to False
                  Then - Actions
                    Unit Group - Add (Picked unit) to AI_Defenders[(Player number of (Owner of (Picked unit)))]
                    Hashtable - Save (Integer A) as 0 of (Key (Picked unit).) in hashtable.
                    Hashtable - Save 1 as 1 of (Key (Picked unit).) in hashtable.
                    Unit Group - Add (Picked unit) to Battallion[(Integer A)]
                    -------- Drider --------
                    If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                      If - Conditions
                        Status[Tempint] Equal to BatalionHash_Guards
                      Then - Actions
                        Hashtable - Save BatalionHash_Guards as Summon of (Key (Picked unit).) in hashtable.
                      Else - Actions
                        For each (Integer B) from 1 to BattalionSize[Tempint], do (Actions)
                          Loop - Actions
                            Set VariableSet Temppoint01 = (Temppoint01 offset by (Random real number between 0 and 50.00) towards (Random angle) degrees.)
                            Unit - Create 1.BattalionTroop[Tempint] for (Player(((Player number of (Owner of (Picked unit))) + TranslatePlayerNumber))) at Temppoint01 facing (Random angle) degrees
                            Unit - Change color of (Last created unit) to (Color of (Owner of (Picked unit)))
                            Hashtable - Save (Integer A) as 0 of (Key (Last created unit).) in hashtable.
                            Unit Group - Add (Last created unit) to Battallion[(Integer A)]
                            Unit - Remove Repair (Forced) from (Last created unit)
                            AI - Ignore (Last created unit)'s guard position
                            -------- Machinery --------
                            If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                              If - Conditions
                                Or - Any (Conditions) are true
                                  Conditions
                                    Status[Tempint] Equal to BatalionHash_Crew
                                    Status[Tempint] Equal to BatalionHash_Beast
                              Then - Actions
                                Hashtable - Save Status[Tempint] as Summon of (Key (Last created unit).) in hashtable.
                              Else - Actions
                    -------- Machinery --------
                    If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                      If - Conditions
                        Or - Any (Conditions) are true
                          Conditions
                            Status[Tempint] Equal to BatalionHash_Crew
                            Status[Tempint] Equal to BatalionHash_Beast
                      Then - Actions
                        Hashtable - Save Status[Tempint] as Summon of (Key (Picked unit).) in hashtable.
                      Else - Actions
                    Set VariableSet BattallionCount = (BattallionCount + 1)
                    Set VariableSet check = True
                  Else - Actions
            Set VariableSet check = False
            Custom script: call RemoveLocation(udg_Temppoint01)
    AI - Ignore the guard positions of all Player 6 (Orange) units
    AI - Ignore the guard positions of all Player 7 (Green) units
Execute when a part of artillery batalion dies. If the last worker dies, set the artillery piece to neutral passive. If the artillery piece dies, "free" the workers, giving them to the owner's player.
//TESH.scrollpos=0
//TESH.alwaysfold=0
function Trig_Battalion_death_Ctrl_Crew_Conditions takes nothing returns boolean
    local integer status = LoadInteger(udg_hashtable, GetHandleId(GetDyingUnit()), udg_Summon)
    //call BJDebugMsg(I2S(status))
    if ( status == udg_BatalionHash_Crew or status == udg_BatalionHash_Beast ) then
        return true
    else
        return false
    endif
endfunction

function NeutralCannon takes nothing returns nothing
    local integer status = LoadInteger(udg_hashtable, GetHandleId(GetDyingUnit()), udg_Summon)
    //call UnitAddAbility( GetEnumUnit(), 'A01A' )
    //call UnitAddAbilityBJ( 'A01A', GetEnumUnit() )
    if ( status == udg_BatalionHash_Crew ) then
        call SetUnitOwner( GetEnumUnit(), Player(PLAYER_NEUTRAL_PASSIVE), true )
    elseif ( status == udg_BatalionHash_Beast ) then
        call SetUnitOwner( GetEnumUnit(), Player(PLAYER_NEUTRAL_AGGRESSIVE), true )
    endif
    //call BJDebugMsg("neutral cannon")
endfunction

function FreeCrew takes nothing returns nothing
    local integer battallionIndex = LoadInteger(udg_hashtable, GetHandleId(GetDyingUnit()), 0)
    call SetUnitOwner( GetEnumUnit(), GetOwningPlayer(GetDyingUnit()), false )
    call UnitAddAbility( GetEnumUnit(), 'A01A' )
    call GroupRemoveUnit( udg_Battallion[battallionIndex], GetEnumUnit() )
    //call BJDebugMsg("free crew")
endfunction

function Trig_Battalion_death_Ctrl_Crew_Actions takes nothing returns nothing
    local integer battallionIndex = LoadInteger(udg_hashtable, GetHandleId(GetDyingUnit()), 0)
    if ( LoadIntegerBJ(1, GetHandleIdBJ(GetDyingUnit()), udg_hashtable) == 1 ) then //cannon destroyed
        call ForGroup( udg_Battallion[battallionIndex], function FreeCrew )
        call GroupClear( udg_Battallion[battallionIndex] )
    else //crew killed
        call GroupRemoveUnit( udg_Battallion[battallionIndex], GetDyingUnit() )
        if ( CountUnitsInGroup(udg_Battallion[battallionIndex]) == 1 ) then
            call ForGroup( udg_Battallion[battallionIndex], function NeutralCannon )
        else
        endif
    endif
    //call BJDebugMsg("unit died")
endfunction

//===========================================================================
function InitTrig_Battalion_death_Ctrl_Crew takes nothing returns nothing
    set gg_trg_Battalion_death_Ctrl_Crew = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Battalion_death_Ctrl_Crew, EVENT_PLAYER_UNIT_DEATH )
    call TriggerAddCondition( gg_trg_Battalion_death_Ctrl_Crew, Condition( function Trig_Battalion_death_Ctrl_Crew_Conditions ) )
    call TriggerAddAction( gg_trg_Battalion_death_Ctrl_Crew, function Trig_Battalion_death_Ctrl_Crew_Actions )
endfunction

 
Let workers follow the artillery wherever it moves. Warning, it may block it.
//TESH.scrollpos=2
//TESH.alwaysfold=0
function ArtilleryType takes nothing returns boolean
    local integer status = LoadInteger(udg_hashtable, GetHandleId(GetFilterUnit()), udg_Summon )
    return (status == udg_BatalionHash_Crew or status == udg_BatalionHash_Beast) and LoadInteger(udg_hashtable, GetHandleId(GetFilterUnit()), 1 ) == 1
endfunction

function Trig_Crew_regroup_Actions takes nothing returns nothing
    local integer batallionIndex
    local group cannons = CreateGroup()
    local unit tempunit
    local location dest
    call GroupEnumUnitsInRect(cannons, GetPlayableMapRect(), Filter(function ArtilleryType) )
    loop
        set tempunit = FirstOfGroup(cannons)
        exitwhen (tempunit == null)
        set batallionIndex = LoadInteger(udg_hashtable, GetHandleId(tempunit), 0)
        set dest = GetUnitLoc(tempunit)
        if ( GetUnitCurrentOrder(tempunit) != String2OrderIdBJ("") ) then
            //call BJDebugMsg("Crew moving")
            call GroupRemoveUnit( udg_Battallion[batallionIndex], tempunit )
            call GroupPointOrderLoc( udg_Battallion[batallionIndex], "move", dest )
            call GroupAddUnit( udg_Battallion[batallionIndex], tempunit )
            call RemoveLocation(dest)
        endif
        call GroupRemoveUnit(cannons, tempunit)
    endloop
    call DestroyGroup(cannons)
endfunction

//===========================================================================
function InitTrig_Crew_regroup takes nothing returns nothing
    set gg_trg_Crew_regroup = CreateTrigger(  )
    call TriggerRegisterTimerEventPeriodic( gg_trg_Crew_regroup, 1.00 )
    call TriggerAddAction( gg_trg_Crew_regroup, function Trig_Crew_regroup_Actions )
endfunction

 
Capture
  Events
    Unit - A unit Starts the effect of an ability
  Conditions
    (Ability being cast) Equal to Capture (Battallion)
    (Load Summon of (Key (Target unit of ability being cast).) from hashtable.) Equal to BatalionHash_Crew
    (Load 1 of (Key (Target unit of ability being cast).) from hashtable.) Equal to 1
    Or - Any (Conditions) are true
      Conditions
        (Owner of (Target unit of ability being cast)) Equal to (Owner of (Casting unit))
        (Owner of (Target unit of ability being cast)) Equal to Neutral Passive
  Actions
    Set VariableSet BattallionIndex = (Load 0 of (Key (Target unit of ability being cast).) from hashtable.)
    If (All Conditions are True) then do (Then Actions) else do (Else Actions)
      If - Conditions
        (Number of units in Battallion[BattallionIndex]) Less than 3
      Then - Actions
        Unit - Change ownership of (Target unit of ability being cast) to (Owner of (Casting unit)) and Change color
        Unit - Change ownership of (Casting unit) to (Player(((Player number of (Owner of (Casting unit))) + TranslatePlayerNumber))) and Retain color
        Unit Group - Add (Casting unit) to Battallion[BattallionIndex]
        Unit - Remove Repair (Forced) from (Casting unit)
        Hashtable - Save BattallionIndex as 0 of (Key (Casting unit).) in hashtable.
        Hashtable - Save BatalionHash_Crew as Summon of (Key (Casting unit).) in hashtable.
        AI - Ignore (Target unit of ability being cast)'s guard position
      Else - Actions
Summon Companion
  Events
    Unit - A unit Spawns a summoned unit
  Conditions
  Actions
    Custom script: local integer summoner = GetUnitTypeId(GetSummoningUnit())
    Custom script: set udg_Tempint = IsCaptain(summoner)
    If (All Conditions are True) then do (Then Actions) else do (Else Actions)
      If - Conditions
        Status[Tempint] Equal to BatalionHash_Guards
        (Unit-type of (Summoned unit)) Equal to BattalionTroop[Tempint]
      Then - Actions
        Unit - Remove (Summoned unit) from the game
        Set VariableSet Temppoint01 = (Position of (Summoning unit))
        Set VariableSet BattallionIndex = (Load 0 of (Key (Summoning unit).) from hashtable.)
        For each (Integer A) from (Number of units in Battallion[BattallionIndex]) to BattalionSize[Tempint], do (Actions)
          Loop - Actions
            Unit - Create 1.BattalionTroop[Tempint] for (Player(((Player number of (Owner of (Summoning unit))) + TranslatePlayerNumber))) at Temppoint01 facing (Random angle) degrees
            Unit - Change color of (Last created unit) to (Color of (Owner of (Summoning unit)))
            Unit Group - Add (Last created unit) to Battallion[BattallionIndex]
            Hashtable - Save BattallionIndex as 0 of (Key (Last created unit).) in hashtable.
            AI - Ignore (Last created unit)'s guard position
            If (All Conditions are True) then do (Then Actions) else do (Else Actions)
              If - Conditions
                BattalionTimer[Tempint] Greater than 0.00
              Then - Actions
                Unit - Add a BattalionTimer[Tempint] second Generic expiration timer to (Last created unit)
              Else - Actions
        Custom script: call RemoveLocation(udg_Temppoint01)
      Else - Actions
Add your own unit types here. Set battalion arrays and NrTypes to the total number of battalion types
Initialization
  Events
    Map initialization
  Conditions
  Actions
    Hashtable - Create a hashtable
    Set VariableSet hashtable = (Last created hashtable)
    -------- Halberdier --------
    Set VariableSet BattalionCaptain[1] = Halberdier (Captain)
    Set VariableSet BattalionTroop[1] = Halberdier
    Set VariableSet BattalionGoldCost[1] = 20
    Set VariableSet BattalionPowerCost[1] = 0
    Set VariableSet BattalionSize[1] = 5
    Set VariableSet AI_ProductionBuilding[1] = Barracks
    -------- Riflemen --------
    Set VariableSet BattalionCaptain[2] = Rifleman (Captain)
    Set VariableSet BattalionTroop[2] = Rifleman
    Set VariableSet BattalionGoldCost[2] = 10
    Set VariableSet BattalionPowerCost[2] = 0
    Set VariableSet BattalionSize[2] = 5
    Set VariableSet AI_ProductionBuilding[2] = Barracks
    -------- Cavalier --------
    Set VariableSet BattalionCaptain[3] = Cavalier (Captain)
    Set VariableSet BattalionTroop[3] = Cavalier
    Set VariableSet BattalionGoldCost[3] = 60
    Set VariableSet BattalionPowerCost[3] = 0
    Set VariableSet BattalionSize[3] = 4
    Set VariableSet AI_ProductionBuilding[3] = Barracks
    -------- CannonTeam --------
    Set VariableSet BattalionCaptain[4] = Field Mortar
    Set VariableSet BattalionTroop[4] = Engineer
    Set VariableSet BattalionSize[4] = 2
    Set VariableSet Status[4] = BatalionHash_Crew
    -------- CannonTeam2 --------
    Set VariableSet BattalionCaptain[5] = Cyclone Cannon
    Set VariableSet BattalionTroop[5] = Engineer
    Set VariableSet BattalionSize[5] = 2
    Set VariableSet Status[5] = BatalionHash_Crew
    -------- SpiderRider --------
    Set VariableSet BattalionCaptain[8] = Spider Rider (Captain)
    Set VariableSet BattalionTroop[8] = Spider Rider
    Set VariableSet BattalionGoldCost[8] = 24
    Set VariableSet BattalionPowerCost[8] = 0
    Set VariableSet BattalionSize[8] = 4
    Set VariableSet AI_ProductionBuilding[8] = Warriors Kabal
    -------- Paladin --------
    Set VariableSet BattalionCaptain[29] = Paladin (Captain)
    Set VariableSet BattalionTroop[29] = Paladin
    Set VariableSet BattalionGoldCost[29] = 60
    Set VariableSet BattalionSize[29] = 4
    Set VariableSet AI_ProductionBuilding[29] = Barracks
    -------- Deadman --------
    Set VariableSet BattalionCaptain[9] = Deadman (Captain)
    Set VariableSet BattalionTroop[9] = Deadman
    Set VariableSet BattalionSize[9] = 5
    -------- Wolf --------
    Set VariableSet BattalionCaptain[10] = Wolf (Neutral, Alpha)
    Set VariableSet BattalionTroop[10] = Wolf (Neutral, Omega)
    Set VariableSet BattalionSize[10] = 7
    -------- Havoc --------
    Set VariableSet BattalionCaptain[12] = Reaper (Captain)
    Set VariableSet BattalionTroop[12] = Reaper
    Set VariableSet BattalionGoldCost[12] = 20
    Set VariableSet BattalionPowerCost[12] = 0
    Set VariableSet BattalionSize[12] = 5
    Set VariableSet AI_ProductionBuilding[12] = Warriors Kabal
    -------- Scout --------
    Set VariableSet BattalionCaptain[13] = Scout (Captain)
    Set VariableSet BattalionTroop[13] = Scout
    Set VariableSet BattalionGoldCost[13] = 20
    Set VariableSet BattalionPowerCost[13] = 0
    Set VariableSet BattalionSize[13] = 5
    Set VariableSet AI_ProductionBuilding[13] = Elven Barracks
    -------- Scouts2 --------
    Set VariableSet BattalionCaptain[32] =
    Set VariableSet BattalionTroop[32] =
    Set VariableSet BattalionGoldCost[32] = 20
    Set VariableSet BattalionSize[32] = 5
    Set VariableSet AI_ProductionBuilding[32] = Elven Barracks
    -------- Wild Riders --------
    Set VariableSet BattalionCaptain[14] = Wild Riders (Captain)
    Set VariableSet BattalionTroop[14] = Wild Riders
    Set VariableSet BattalionGoldCost[14] = 24
    Set VariableSet BattalionPowerCost[14] = 0
    Set VariableSet BattalionSize[14] = 4
    Set VariableSet AI_ProductionBuilding[14] = Elven Barracks
    -------- ElvenWindDancer --------
    Set VariableSet BattalionCaptain[15] =
    Set VariableSet BattalionTroop[15] =
    Set VariableSet BattalionGoldCost[15] = 40
    Set VariableSet BattalionSize[15] = 2
    -------- Pixies --------
    Set VariableSet BattalionCaptain[16] = Pixie (Captain)
    Set VariableSet BattalionTroop[16] = Pixie
    Set VariableSet BattalionGoldCost[16] = 15
    Set VariableSet BattalionPowerCost[16] = 0
    Set VariableSet BattalionSize[16] = 7
    Set VariableSet AI_ProductionBuilding[16] = Fae Tree
    -------- Manticore --------
    Set VariableSet BattalionCaptain[17] = Manticore Ballista
    Set VariableSet BattalionTroop[17] = Wood Elf
    Set VariableSet BattalionSize[17] = 2
    Set VariableSet Status[17] = BatalionHash_Crew
    Set VariableSet AI_ProductionBuilding[17] = Elven Barracks
    -------- Wights --------
    Set VariableSet BattalionCaptain[18] = Everlife Sage
    Set VariableSet BattalionTroop[18] = Wood Elf
    Set VariableSet BattalionSize[18] = 2
    Set VariableSet Status[18] = BatalionHash_Crew
    Set VariableSet AI_ProductionBuilding[18] = Tree of Wisdom
    -------- Returned Cavalry --------
    Set VariableSet BattalionCaptain[19] = Juggernaugt (Captain)
    Set VariableSet BattalionTroop[19] = Juggernaugt
    Set VariableSet BattalionGoldCost[19] = 30
    Set VariableSet BattalionPowerCost[19] = 0
    Set VariableSet BattalionSize[19] = 4
    -------- GoblinRogue --------
    Set VariableSet BattalionCaptain[20] = Clobber (Captain)
    Set VariableSet BattalionTroop[20] = Clobber
    Set VariableSet BattalionSize[20] = 7
    -------- Immortals --------
    Set VariableSet BattalionCaptain[21] = Goblin Raider (Captain)
    Set VariableSet BattalionTroop[21] = Goblin Raider
    Set VariableSet BattalionGoldCost[21] = 30
    Set VariableSet BattalionPowerCost[21] = 0
    Set VariableSet BattalionSize[21] = 5
    -------- Warmonger --------
    Set VariableSet BattalionCaptain[22] = Warmonger (Captain)
    Set VariableSet BattalionTroop[22] = Warmonger
    Set VariableSet BattalionGoldCost[22] = 24
    Set VariableSet BattalionSize[22] = 4
    -------- EldritchStaff --------
    Set VariableSet BattalionCaptain[25] = Voidfire
    Set VariableSet BattalionTroop[25] = Slave
    Set VariableSet BattalionSize[25] = 2
    Set VariableSet Status[25] = BatalionHash_Crew
    -------- Familiar --------
    Set VariableSet BattalionCaptain[33] = Archon
    Set VariableSet BattalionTroop[33] = Familiar
    Set VariableSet BattalionSize[33] = 1
    Set VariableSet Status[33] = BatalionHash_Guards
    -------- Paladin --------
    Set VariableSet BattalionCaptain[35] =
    Set VariableSet BattalionTroop[35] =
    Set VariableSet BattalionSize[35] = 4
    Set VariableSet BattalionGoldCost[35] = 60
    -------- EternalServitudeGhouls --------
    Set VariableSet BattalionCaptain[36] =
    Set VariableSet BattalionTroop[36] =
    Set VariableSet BattalionSize[36] = 5
    Set VariableSet BattalionGoldCost[36] = 0
    -------- EternalServitudeCavalry --------
    Set VariableSet BattalionCaptain[37] =
    Set VariableSet BattalionTroop[37] =
    Set VariableSet BattalionGoldCost[37] = 30
    Set VariableSet BattalionSize[37] = 4
    -------- Nomad/Vulture --------
    Set VariableSet BattalionCaptain[38] = Nomad
    Set VariableSet BattalionTroop[38] = Vulture
    Set VariableSet BattalionSize[38] = 1
    Set VariableSet Status[38] = BatalionHash_Guards
    -------- FireCatapult --------
    Set VariableSet BattalionCaptain[39] = Catapult
    Set VariableSet BattalionTroop[39] = Goblin Peon
    Set VariableSet BattalionSize[39] = 2
    Set VariableSet Status[39] = BatalionHash_Crew
    -------- Wood Wraith --------
    Set VariableSet BattalionCaptain[30] = Wood Wraith (Captain)
    Set VariableSet BattalionTroop[30] = Wood Wraith
    Set VariableSet BattalionSize[30] = 4
    Set VariableSet BattalionGoldCost[30] = 60
    -------- HalberdierMinutemen --------
Initialize Buildings
  Events
    Map initialization
  Conditions
  Actions
    -------- Barracks --------
    Set VariableSet BuildDB_Buildings[1] = Barracks
    Set VariableSet BuildDB_Builders[1] = Imperial Fort
    Set VariableSet BuildDB_Requirements[1] = Imperial Fort
    Set VariableSet BuildDB_Cost[1] = 300
    Set VariableSet BuildDB_Avalaible[1] = H Charge Gold For Barracks (Human)
    Set VariableSet BuildDB_Unavalaible[1] = H Build Barracks
    Set VariableSet BuildDB_Item[1] = Build Barracks (item)
    -------- Magistrate --------
    Set VariableSet BuildDB_Buildings[2] = Magistrate
    Set VariableSet BuildDB_Builders[2] = Imperial Fort
    Set VariableSet BuildDB_Requirements[2] = Barracks
    Set VariableSet BuildDB_Cost[2] = 350
    Set VariableSet BuildDB_Avalaible[2] = H Charge Gold For Magistrate (Human)
    Set VariableSet BuildDB_Unavalaible[2] = H Build Magistrate
    Set VariableSet BuildDB_Item[2] = Build Quartermaster (item)
    -------- Factory --------
    Set VariableSet BuildDB_Buildings[3] = Factory
    Set VariableSet BuildDB_Builders[3] = Imperial Fort
    Set VariableSet BuildDB_Requirements[3] = Barracks
    Set VariableSet BuildDB_Cost[3] = 350
    Set VariableSet BuildDB_Avalaible[3] = H Charge Gold For Factory (Human)
    Set VariableSet BuildDB_Unavalaible[3] = H Build Factory
    Set VariableSet BuildDB_Item[3] = Build Siege Works (item)
    -------- Hospital --------
    Set VariableSet BuildDB_Buildings[4] = Hospital
    Set VariableSet BuildDB_Builders[4] = Imperial Fort
    Set VariableSet BuildDB_Requirements[4] = Magistrate
    Set VariableSet BuildDB_Cost[4] = 350
    Set VariableSet BuildDB_Avalaible[4] = H Charge Hospital (Human)
    Set VariableSet BuildDB_Unavalaible[4] = H Build Hospital
    Set VariableSet BuildDB_Item[4] = Build Church (item)
    -------- Tower --------
    Set VariableSet BuildDB_Buildings[5] = Guard Tower
    Set VariableSet BuildDB_Builders[5] = Imperial Fort
    Set VariableSet BuildDB_Requirements[5] = Barracks
    Set VariableSet BuildDB_Cost[5] = 300
    Set VariableSet BuildDB_Avalaible[5] = H Charge Gold For Tower (Human)
    Set VariableSet BuildDB_Unavalaible[5] = H Build Guard Tower
    Set VariableSet BuildDB_Item[5] = Build Tower (item)
    Set VariableSet BuildDB_Limit[5] = 2
    -------- Arena --------
    Set VariableSet BuildDB_Buildings[6] = Orc Arena
    Set VariableSet BuildDB_Builders[6] = Orc Fort
    Set VariableSet BuildDB_Requirements[6] = Orc Fort
    Set VariableSet BuildDB_Cost[6] = 300
    Set VariableSet BuildDB_Avalaible[6] = V Charge Gold For Arena (Orc)
    Set VariableSet BuildDB_Unavalaible[6] = V Build Arena
    Set VariableSet BuildDB_Item[6] = Build Barracks (item)
    -------- Beast Pit --------
    Set VariableSet BuildDB_Buildings[7] = Beast Pit
    Set VariableSet BuildDB_Builders[7] = Orc Fort
    Set VariableSet BuildDB_Requirements[7] = Orc Arena
    Set VariableSet BuildDB_Cost[7] = 350
    Set VariableSet BuildDB_Avalaible[7] = V Charge Gold For Beast Pit (Orc)
    Set VariableSet BuildDB_Unavalaible[7] = V Build Beast Pit
    Set VariableSet BuildDB_Item[7] = Build Church (item)
    -------- Orc Furnace --------
    Set VariableSet BuildDB_Buildings[25] = Orc Furnace
    Set VariableSet BuildDB_Builders[25] = Orc Fort
    Set VariableSet BuildDB_Requirements[25] = Orc Arena
    Set VariableSet BuildDB_Cost[25] = 350
    Set VariableSet BuildDB_Avalaible[25] = V Charge Gold For Furnace (Orc)
    Set VariableSet BuildDB_Unavalaible[25] = V Build Furnace
    Set VariableSet BuildDB_Item[25] = Build Quartermaster (item)
    -------- Orc War Banner --------
    Set VariableSet BuildDB_Buildings[26] = War Banner
    Set VariableSet BuildDB_Builders[26] = Orc Fort
    Set VariableSet BuildDB_Requirements[26] = Orc Furnace
    Set VariableSet BuildDB_Cost[26] = 350
    Set VariableSet BuildDB_Avalaible[26] = V Charge Gold For War Banner (Orc)
    Set VariableSet BuildDB_Unavalaible[26] = V Build War Banner
    Set VariableSet BuildDB_Item[26] = Build Siege Works (item)
    -------- Orc Tower --------
    Set VariableSet BuildDB_Buildings[27] = Orc Tower
    Set VariableSet BuildDB_Builders[27] = Orc Fort
    Set VariableSet BuildDB_Requirements[27] = Orc Furnace
    Set VariableSet BuildDB_Cost[27] = 300
    Set VariableSet BuildDB_Avalaible[27] = V Charge Gold For Orc Tower (Orc)
    Set VariableSet BuildDB_Unavalaible[27] = V Build Orc Tower
    Set VariableSet BuildDB_Item[27] = Build Tower (item)
    Set VariableSet BuildDB_Limit[27] = 2
    -------- Elven Barracks --------
    Set VariableSet BuildDB_Buildings[10] = Elven Barracks
    Set VariableSet BuildDB_Builders[10] = Elders Hall
    Set VariableSet BuildDB_Requirements[10] = Elders Hall
    Set VariableSet BuildDB_Cost[10] = 300
    Set VariableSet BuildDB_Avalaible[10] = E Charge Gold For Elven Barracks (Elf)
    Set VariableSet BuildDB_Unavalaible[10] = E Build Elven Barracks
    Set VariableSet BuildDB_Item[10] = Build Barracks (item)
    -------- Rangers lodge --------
    Set VariableSet BuildDB_Buildings[11] = Rangers Lodge
    Set VariableSet BuildDB_Builders[11] = Elders Hall
    Set VariableSet BuildDB_Requirements[11] = Elven Barracks
    Set VariableSet BuildDB_Cost[11] = 350
    Set VariableSet BuildDB_Avalaible[11] = E Charge Gold For Rangers Lodge (Elf)
    Set VariableSet BuildDB_Unavalaible[11] = E Build Rangers Lodge
    Set VariableSet BuildDB_Item[11] = Build Quartermaster (item)
    -------- Fae tree --------
    Set VariableSet BuildDB_Buildings[12] = Fae Tree
    Set VariableSet BuildDB_Builders[12] = Elders Hall
    Set VariableSet BuildDB_Requirements[12] = Elven Barracks
    Set VariableSet BuildDB_Cost[12] = 350
    Set VariableSet BuildDB_Avalaible[12] = E Charge Gold For Fae Tree (Elf)
    Set VariableSet BuildDB_Unavalaible[12] = E Build Fae Tree
    Set VariableSet BuildDB_Item[12] = Build Church (item)
    -------- Weavers hall --------
    Set VariableSet BuildDB_Buildings[14] = Tree of Wisdom
    Set VariableSet BuildDB_Builders[14] = Elders Hall
    Set VariableSet BuildDB_Requirements[14] = Fae Tree
    Set VariableSet BuildDB_Cost[14] = 350
    Set VariableSet BuildDB_Avalaible[14] = E Charge Gold For Tree of Wisdom (Elf)
    Set VariableSet BuildDB_Unavalaible[14] = E Build Tree of Wisdom
    Set VariableSet BuildDB_Item[14] = Build Siege Works (item)
    -------- Watch tower --------
    Set VariableSet BuildDB_Buildings[15] = Treeman
    Set VariableSet BuildDB_Builders[15] = Elders Hall
    Set VariableSet BuildDB_Requirements[15] = Rangers Lodge
    Set VariableSet BuildDB_Cost[15] = 300
    Set VariableSet BuildDB_Avalaible[15] = E Charge Gold For Watch Tower (Elf)
    Set VariableSet BuildDB_Unavalaible[15] = E Build Watch Tower
    Set VariableSet BuildDB_Item[15] = Build Tower (item)
    Set VariableSet BuildDB_Limit[15] = 2
    -------- Warriors Kabal --------
    Set VariableSet BuildDB_Buildings[20] = Warriors Kabal
    Set VariableSet BuildDB_Builders[20] = Tower of Elysium
    Set VariableSet BuildDB_Requirements[20] = Tower of Elysium
    Set VariableSet BuildDB_Cost[20] = 300
    Set VariableSet BuildDB_Avalaible[20] = D Charge Gold For Warriors Kabal (Drow)
    Set VariableSet BuildDB_Unavalaible[20] = D Build Warriors Kabal
    Set VariableSet BuildDB_Item[20] = Build Barracks (item)
    -------- Dark Arcanum --------
    Set VariableSet BuildDB_Buildings[21] = Dark Arcanum
    Set VariableSet BuildDB_Builders[21] = Tower of Elysium
    Set VariableSet BuildDB_Requirements[21] = Warriors Kabal
    Set VariableSet BuildDB_Cost[21] = 350
    Set VariableSet BuildDB_Avalaible[21] = D Charge Gold For Dark Arcanum (Drow)
    Set VariableSet BuildDB_Unavalaible[21] = D Build Dark Arcanum
    Set VariableSet BuildDB_Item[21] = Build Quartermaster (item)
    -------- Temple of Murder --------
    Set VariableSet BuildDB_Buildings[22] = Slave Cages
    Set VariableSet BuildDB_Builders[22] = Tower of Elysium
    Set VariableSet BuildDB_Requirements[22] = Warriors Kabal
    Set VariableSet BuildDB_Cost[22] = 350
    Set VariableSet BuildDB_Avalaible[22] = D Charge Gold For Slave Cages (Drow)
    Set VariableSet BuildDB_Unavalaible[22] = D Build Slave Cages
    Set VariableSet BuildDB_Item[22] = Build Church (item)
    -------- Dark Arcanum --------
    Set VariableSet BuildDB_Buildings[23] = Altar of Blood
    Set VariableSet BuildDB_Builders[23] = Tower of Elysium
    Set VariableSet BuildDB_Requirements[23] = Dark Arcanum
    Set VariableSet BuildDB_Cost[23] = 350
    Set VariableSet BuildDB_Avalaible[23] = D Charge Gold For Altar of Blood (Drow)
    Set VariableSet BuildDB_Unavalaible[23] = D Build Altar of Blood
    Set VariableSet BuildDB_Item[23] = Build Siege Works (item)
    -------- Eldritch tower --------
    Set VariableSet BuildDB_Buildings[24] = Eldritch Tower
    Set VariableSet BuildDB_Builders[24] = Tower of Elysium
    Set VariableSet BuildDB_Requirements[24] = Dark Arcanum
    Set VariableSet BuildDB_Cost[24] = 300
    Set VariableSet BuildDB_Avalaible[24] = D Charge Gold For Eldritch Tower (Drow)
    Set VariableSet BuildDB_Unavalaible[24] = D Build Eldritch Tower
    Set VariableSet BuildDB_Item[24] = Build Tower (item)
    Set VariableSet BuildDB_Limit[24] = 2
Commences mine entanglement for all halls on the map
Entangle Initialization
  Events
    Time - Elapsed game time is 2.00 seconds
  Conditions
  Actions
    For each (Integer B) from 1 to 4, do (Actions)
      Loop - Actions
        Unit Group - Pick every unit in (Units of type Build_TreeType[(Integer B)]) and do (Actions)
          Loop - Actions
            Unit - Order (Picked unit) to Night Elf Tree Of Life - Entangle.(Random unit from (Units within 2000.00 of (Position of (Picked unit)) matching ((Unit-type of (Matching unit)) Equal to Gold Mine).))
Entangling mine after the new hall is build via capture
Entangle Hall Built
  Events
    Unit - A unit Finishes construction
  Conditions
    ((Constructed structure) is A town-hall-type unit) Equal to True
  Actions
    Hashtable - Save ((Number of units in (Units within 1000.00 of (Position of (Constructed structure)) matching (((((Matching unit) is A structure) Equal to True) and (((Matching unit) is alive) Equal to True)) and ((Owner of (Constructed structure)) Equal to (Owner of (Matching unit)))).)) - 1) as 10 of (Key (Constructed structure).) in hashtable.
    Hashtable - Save 1 as (Point-value of (Unit-type of (Constructed structure))) of (Key (Constructed structure).) in hashtable.
    Unit - Create 1.Build_TreeType[(Player number of (Owner of (Constructed structure)))] for (Owner of (Constructed structure)) at (Position of (Constructed structure)) facing Default building facing degrees
    Unit Group - Pick every unit in (Units owned by (Owner of (Constructed structure)) of type Build_TreeType[(Player number of (Owner of (Constructed structure)))]) and do (Actions)
      Loop - Actions
        If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          If - Conditions
            (Distance between (Position of (Picked unit)) and (Position of (Constructed structure))) Less than or equal to 1500.00
          Then - Actions
            Unit - Order (Picked unit) to Night Elf Tree Of Life - Entangle.(Random unit from (Units within 2000.00 of (Position of (Constructed structure)) matching ((Unit-type of (Matching unit)) Equal to Gold Mine).))
          Else - Actions
Disable canceling the Hall building when it is building itself to prevent exploits
NoCancel
  Events
    Unit - A unit Is issued an order with no target
  Conditions
    ((Triggering unit) is A town-hall-type unit) Equal to True
    ((Triggering unit) is in Build_Birth.) Equal to True
  Actions
    Custom script: if GetIssuedOrderId() == 851976 then
    Unit - Pause (Triggering unit)
    Unit - Unpause (Triggering unit)
    Custom script: endif
Get killing unit (including batalion's) and then create a dummy which builds the hall for the killing player
Hall death
  Events
    Unit - A unit Dies
  Conditions
    Or - Any (Conditions) are true
      Conditions
        (Unit-type of (Dying unit)) Equal to Imperial Fort
        (Unit-type of (Dying unit)) Equal to Orc Fort
        (Unit-type of (Dying unit)) Equal to Tower of Elysium
        (Unit-type of (Dying unit)) Equal to Elders Hall
        (Unit-type of (Dying unit)) Equal to Settlement
  Actions
    Unit Group - Pick every unit in (Units within 2000.00 of (Position of (Dying unit)) matching ((((Matching unit) is A structure) Equal to True) and ((Owner of (Matching unit)) Equal to (Owner of (Dying unit)))).) and do (Actions)
      Loop - Actions
        Unit - Kill (Picked unit)
    Unit Group - Pick every unit in (Units owned by (Owner of (Dying unit)) of type Build_TreeType[(Player number of (Owner of (Dying unit)))]) and do (Actions)
      Loop - Actions
        If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          If - Conditions
            (Distance between (Position of (Picked unit)) and (Position of (Dying unit))) Less than or equal to 1500.00
          Then - Actions
            Unit - Remove (Picked unit) from the game
          Else - Actions
    If (All Conditions are True) then do (Then Actions) else do (Else Actions)
      If - Conditions
        (Load 0 of (Key (Killing unit).) from hashtable.) Greater than 0
        (Load 1 of (Key (Killing unit).) from hashtable.) Equal to 0
      Then - Actions
        Set VariableSet Tempplayer = (Player(((Player number of (Owner of (Killing unit))) - TranslatePlayerNumber)))
      Else - Actions
        Set VariableSet Tempplayer = (Owner of (Killing unit))
    -------- new --------
    Set VariableSet Temppoint = (Position of (Dying unit))
    Unit - Create 1.Place Structure (Hall) for Tempplayer at Temppoint facing Default building facing degrees
    Unit - Add a 1.00 second Generic expiration timer to (Last created unit)
    Unit - Order (Last created unit) to build a Build_HallType[(Player number of Tempplayer)] at Temppoint
    Wait 0.27 seconds
Rebuild the mine after it is destroyed and the hall is still alive
Mine death
  Events
    Unit - A unit Dies
  Conditions
    Or - Any (Conditions) are true
      Conditions
        (Unit-type of (Dying unit)) Equal to Gold Mine (Drow)
        (Unit-type of (Dying unit)) Equal to Gold Mine (Elf)
        (Unit-type of (Dying unit)) Equal to Gold Mine (Human)
        (Unit-type of (Dying unit)) Equal to Gold Mine (Sahugin)
        (Unit-type of (Dying unit)) Equal to Gold Mine (Orc)
  Actions
    Wait 10.00 seconds
    Unit Group - Pick every unit in (Units of type Build_TreeType[(Player number of (Owner of (Dying unit)))]) and do (Actions)
      Loop - Actions
        Unit - Order (Picked unit) to Night Elf Tree Of Life - Entangle.(Random unit from (Units within 2000.00 of (Position of (Picked unit)) matching ((Unit-type of (Matching unit)) Equal to Gold Mine).))
Refund money for cancelled buildings.
Building Cancel
  Events
    Unit - A unit Cancels construction
  Conditions
  Actions
    For each (Integer A) from 1 to 40, do (Actions)
      Loop - Actions
        If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          If - Conditions
            (Unit-type of (Cancelled structure)) Equal to BuildDB_Buildings[(Integer A)]
          Then - Actions
            Player - Add BuildDB_Cost[(Integer A)] to (Owner of (Cancelled structure)).Current gold
          Else - Actions
Make the hall invulnerable few seconds after it started building
Short Invulnerabilty
  Events
    Unit - A unit Begins construction
  Conditions
    ((Constructing structure) is A town-hall-type unit) Equal to True
  Actions
    Unit - Make (Constructing structure) Invulnerable
    Wait 5.00 seconds
    Unit - Make (Constructing structure) Vulnerable
Set Hall values
  Events
    Time - Elapsed game time is 0.50 seconds
  Conditions
  Actions
    Unit Group - Pick every unit in (Units in (Playable map area) matching (((Matching unit) is A town-hall-type unit) Equal to True)) and do (Actions)
      Loop - Actions
        Hashtable - Save 1 as (Point-value of (Unit-type of (Picked unit))) of (Key (Picked unit).) in hashtable.
    For each (Integer A) from 1 to 4, do (Actions)
      Loop - Actions
        If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          If - Conditions
            (Race of (Player((Integer A)))) Equal to Human
          Then - Actions
            Set VariableSet Build_HallType[(Integer A)] = Imperial Fort
            Set VariableSet Build_TreeType[(Integer A)] = Tree of Life (Human)
          Else - Actions
        If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          If - Conditions
            (Race of (Player((Integer A)))) Equal to Orc
          Then - Actions
            Set VariableSet Build_HallType[(Integer A)] = Orc Fort
            Set VariableSet Build_TreeType[(Integer A)] = Tree of Life (Orc)
          Else - Actions
        If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          If - Conditions
            (Race of (Player((Integer A)))) Equal to Undead
          Then - Actions
            Set VariableSet Build_HallType[(Integer A)] = Tower of Elysium
            Set VariableSet Build_TreeType[(Integer A)] = Tree of Life (Drow)
          Else - Actions
        If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          If - Conditions
            (Race of (Player((Integer A)))) Equal to Night Elf
          Then - Actions
            Set VariableSet Build_HallType[(Integer A)] = Elders Hall
            Set VariableSet Build_TreeType[(Integer A)] = Tree of Life (Elf)
          Else - Actions
Begins Build
  Events
    Unit - A unit Begins construction
  Conditions
  Actions
    Unit Group - Add (Constructing structure) to Build_Birth
    Set VariableSet Tempint = 0
    For each (Integer A) from 1 to 40, do (Actions)
      Loop - Actions
        If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          If - Conditions
            (Unit-type of (Constructing structure)) Equal to BuildDB_Buildings[(Integer A)]
          Then - Actions
            Set VariableSet Tempint = (Integer A)
          Else - Actions
    -------- Skip if the building is not in any group --------
    If (All Conditions are True) then do (Then Actions) else do (Else Actions)
      If - Conditions
        Tempint Equal to 0
      Then - Actions
        Skip remaining actions
      Else - Actions
    -------- Mark building as being built and reset build menu --------
    Custom script: set bj_wantDestroyGroup = true
    Unit Group - Pick every unit in (Units within 2000.00 of (Position of (Constructing structure)) matching (((Matching unit) is A town-hall-type unit) Equal to True).) and do (Actions)
      Loop - Actions
        If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          If - Conditions
            BuildDB_Limit[Tempint] Equal to 0
          Then - Actions
            Hashtable - Save -1 as (Point-value of (Unit-type of (Constructing structure))) of (Key (Picked unit).) in hashtable.
          Else - Actions
            Set VariableSet Tempint = (Load (Point-value of (Unit-type of (Constructing structure))) of (Key (Picked unit).) from hashtable.)
            Set VariableSet Tempint = (Tempint + 1)
            Hashtable - Save Tempint as (Point-value of (Unit-type of (Constructing structure))) of (Key (Picked unit).) in hashtable.
        Cinematic - Ping minimap for (All players) at (Position of (Picked unit)) for 1 seconds
Death Build
  Events
    Unit - A unit Dies
  Conditions
    ((Dying unit) is A structure) Equal to True
  Actions
    Set VariableSet Tempint = 0
    For each (Integer A) from 1 to 40, do (Actions)
      Loop - Actions
        If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          If - Conditions
            (Unit-type of (Dying unit)) Equal to BuildDB_Buildings[(Integer A)]
          Then - Actions
            Set VariableSet Tempint = (Integer A)
          Else - Actions
    -------- Skip if the building is not in any group --------
    If (All Conditions are True) then do (Then Actions) else do (Else Actions)
      If - Conditions
        Tempint Equal to 0
      Then - Actions
        Skip remaining actions
      Else - Actions
    -------- Unmark building and reset build menu --------
    Custom script: set bj_wantDestroyGroup = true
    Unit Group - Pick every unit in (Units within 2000.00 of (Position of (Dying unit)) matching (((Matching unit) is A town-hall-type unit) Equal to True).) and do (Actions)
      Loop - Actions
        If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          If - Conditions
            BuildDB_Limit[Tempint] Equal to 0
          Then - Actions
            Game - Display to (All players) the text: death non tower
            Hashtable - Save 0 as (Point-value of (Unit-type of (Dying unit))) of (Key (Picked unit).) in hashtable.
          Else - Actions
            Game - Display to (All players) the text: death tower
            Set VariableSet Tempint = (Load (Point-value of (Unit-type of (Dying unit))) of (Key (Picked unit).) from hashtable.)
            Set VariableSet Tempint = (Tempint - 1)
            Hashtable - Save Tempint as (Point-value of (Unit-type of (Dying unit))) of (Key (Picked unit).) in hashtable.
    Custom script: set bj_wantDestroyGroup = true
    Unit Group - Pick every unit in (Units owned by (Owner of (Dying unit)) of type Build Menu (Menu)) and do (Actions)
      Loop - Actions
        Unit - Remove (Picked unit) from the game
    If (All Conditions are True) then do (Then Actions) else do (Else Actions)
      If - Conditions
        (Unit-type of (Random unit from (Units owned by (Owner of (Dying unit)) matching (((Matching unit) is selected by (Owner of (Dying unit)).) Equal to True).))) Equal to Build Menu (Menu)
      Then - Actions
        Unit Group - Pick every unit in (Units within 2000.00 of (Position of (Dying unit)) matching ((((Matching unit) is A town-hall-type unit) Equal to True) and ((Owner of (Matching unit)) Equal to (Owner of (Dying unit)))).) and do (Actions)
          Loop - Actions
            Unit - Order (Picked unit) to Build.
      Else - Actions
Mark the building as built for specific hall and then check if any build menus are currently opened and reopen it with possible requirements satisfied
Finished Build
  Events
    Unit - A unit Finishes construction
  Conditions
  Actions
    Set VariableSet Tempint = 0
    For each (Integer A) from 1 to 40, do (Actions)
      Loop - Actions
        If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          If - Conditions
            (Unit-type of (Constructed structure)) Equal to BuildDB_Buildings[(Integer A)]
          Then - Actions
            Set VariableSet Tempint = (Integer A)
          Else - Actions
    -------- Skip if the building is not in any group --------
    If (All Conditions are True) then do (Then Actions) else do (Else Actions)
      If - Conditions
        Tempint Equal to 0
      Then - Actions
        Skip remaining actions
      Else - Actions
    -------- Mark building as completed and reset build menu --------
    If (All Conditions are True) then do (Then Actions) else do (Else Actions)
      If - Conditions
        BuildDB_Limit[Tempint] Equal to 0
      Then - Actions
        Hashtable - Save 1 as (Point-value of (Unit-type of (Constructed structure))) of (Key (Random unit from (Units within 2000.00 of (Position of (Constructed structure)) matching ((Unit-type of (Matching unit)) Equal to BuildDB_Builders[Tempint]).)).) in hashtable.
      Else - Actions
    Unit Group - Remove (Constructed structure) from Build_Birth.
    Unit Group - Pick every unit in (Units owned by (Owner of (Constructed structure)) of type Build Menu (Menu)) and do (Actions)
      Loop - Actions
        Unit - Remove (Picked unit) from the game
    If (All Conditions are True) then do (Then Actions) else do (Else Actions)
      If - Conditions
        (Unit-type of (Random unit from (Units owned by (Owner of (Constructed structure)) matching (((Matching unit) is selected by (Owner of (Constructed structure)).) Equal to True).))) Equal to Build Menu (Menu)
      Then - Actions
        Set VariableSet Tempunit = (Random unit from (Units owned by (Owner of (Constructed structure)) matching (((Matching unit) is selected by (Owner of (Constructed structure)).) Equal to True).))
        Unit Group - Pick every unit in (Units within 2000.00 of (Position of Tempunit) matching ((((Matching unit) is A town-hall-type unit) Equal to True) and ((Owner of (Matching unit)) Equal to (Owner of (Constructed structure)))).) and do (Actions)
          Loop - Actions
            Unit - Order (Picked unit) to Build.
      Else - Actions
Set list of avalaible buildings on build menu dummy unit depending on requirements
Build menu
  Events
    Unit - A unit Starts the effect of an ability
  Conditions
    (Ability being cast) Equal to Build
  Actions
    Set VariableSet Build_Hall[(Player number of (Owner of (Casting unit)))] = (Casting unit)
    Unit - Create 1.Build Menu (Menu) for (Owner of (Casting unit)) at (Position of (Casting unit)) facing Default building facing degrees
    -------- Add appropriate buildings to the build list --------
    For each (Integer A) from 1 to 40, do (Actions)
      Loop - Actions
        If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          If - Conditions
            (Unit-type of (Casting unit)) Equal to BuildDB_Builders[(Integer A)]
            (Load (Point-value of BuildDB_Buildings[(Integer A)]) of (Key (Casting unit).) from hashtable.) Equal to 0
            BuildDB_Limit[(Integer A)] Equal to 0
          Then - Actions
            Game - Display to (All players) the text: (String(BuildDB_Buildings[(Integer A)]))
            If (All Conditions are True) then do (Then Actions) else do (Else Actions)
              If - Conditions
                (Load (Point-value of BuildDB_Requirements[(Integer A)]) of (Key (Casting unit).) from (Last created hashtable).) Greater than 0
              Then - Actions
                Game - Display to (All players) the text: avalaible
                Unit - Add BuildDB_Avalaible[(Integer A)] to (Last created unit)
              Else - Actions
                Game - Display to (All players) the text: unavalaible
                Unit - Add BuildDB_Unavalaible[(Integer A)] to (Last created unit)
          Else - Actions
            If (All Conditions are True) then do (Then Actions) else do (Else Actions)
              If - Conditions
                (Unit-type of (Casting unit)) Equal to BuildDB_Builders[(Integer A)]
                (Load (Point-value of BuildDB_Buildings[(Integer A)]) of (Key (Casting unit).) from hashtable.) Less than BuildDB_Limit[(Integer A)]
                BuildDB_Limit[(Integer A)] Greater than 0
              Then - Actions
                If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                  If - Conditions
                    (Load (Point-value of BuildDB_Requirements[(Integer A)]) of (Key (Casting unit).) from (Last created hashtable).) Greater than 0
                  Then - Actions
                    Game - Display to (All players) the text: avalaible
                    Unit - Add BuildDB_Avalaible[(Integer A)] to (Last created unit)
                  Else - Actions
                    Game - Display to (All players) the text: unavalaible
                    Unit - Add BuildDB_Unavalaible[(Integer A)] to (Last created unit)
              Else - Actions
    Selection - Select (Last created unit) for (Owner of (Casting unit))
Used to quickly go through ugly build screen to place building interface
Force Build P1
  Events
    Time - Build_WaitTimer[1] expires
  Conditions
  Actions
    Game - Force Player 1 (Red) to press the key B.
    Trigger - Turn on Force_Cancel_P1 <gen>
Used to quickly go through ugly build screen to place building interface
Force Build P2
  Events
    Time - Build_WaitTimer[2] expires
  Conditions
  Actions
    Game - Force Player 2 (Blue) to press the key B.
    Trigger - Turn on Force_Cancel_P2 <gen>
Used to quickly go through ugly build screen to place building interface
Force Build P3
  Events
    Time - Build_WaitTimer[3] expires
  Conditions
  Actions
    Game - Force Player 3 (Teal) to press the key B.
    Trigger - Turn on Force_Cancel_P3 <gen>
Used to quickly go through ugly build screen to place building interface
Force Build P4
  Events
    Time - Build_WaitTimer[4] expires
  Conditions
  Actions
    Game - Force Player 4 (Purple) to press the key B.
    Trigger - Turn on Force_Cancel_P4 <gen>
Store structure which was chosen at build menu and run timer to use Force build trigger
Build
  Events
    Unit - A unit Starts the effect of an ability
  Conditions
    Build Menu (Menu) Equal to (Unit-type of (Casting unit))
  Actions
    Set VariableSet Tempint = 0
    For each (Integer A) from 1 to 40, do (Actions)
      Loop - Actions
        If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          If - Conditions
            (Ability being cast) Equal to BuildDB_Avalaible[(Integer A)]
          Then - Actions
            Set VariableSet Tempint = (Integer A)
          Else - Actions
    -------- Create dummy builder --------
    If (All Conditions are True) then do (Then Actions) else do (Else Actions)
      If - Conditions
        Tempint Equal to 0
      Then - Actions
        Skip remaining actions
      Else - Actions
        Set VariableSet Temppoint = (Position of (Casting unit))
        Unit - Create 1.Place Structure (Human-item) for (Owner of (Casting unit)) at Temppoint facing Default building facing degrees
        Unit - Add BuildDB_Item[Tempint] to (Last created unit)
        Set VariableSet Build_Structure[(Player number of (Owner of (Casting unit)))] = BuildDB_Buildings[Tempint]
        Selection - Select (Last created unit) for (Owner of (Casting unit))
        Countdown Timer - Start Build_WaitTimer[(Player number of (Owner of (Casting unit)))] as a One-shot timer that will expire in 0.03 seconds
        Custom script: call RemoveLocation( udg_Temppoint )
        Custom script: call RemoveLocation( udg_Temppoint01 )
    -------- Computer stuff --------
    If (All Conditions are True) then do (Then Actions) else do (Else Actions)
      If - Conditions
        ((Owner of (Casting unit)) controller) Equal to Computer
      Then - Actions
        Set VariableSet Temppoint01 = (Temppoint offset by 500.00 towards (Random angle) degrees.)
        Unit - Order (Last created unit) to Special - Dark Summoning.Temppoint01
      Else - Actions
Used to cancel the whole building process if the player decides to not place the building
Force Cancel P1
  Events
    Time - Every 0.01 seconds of game time
  Conditions
  Actions
    Game - Force Player 1 (Red) to press the key A.
Used to cancel the whole building process if the player decides to not place the building
Force Cancel P2
  Events
    Time - Every 0.01 seconds of game time
  Conditions
  Actions
    Game - Force Player 2 (Blue) to press the key A.
Used to cancel the whole building process if the player decides to not place the building
Force Cancel P3
  Events
    Time - Every 0.01 seconds of game time
  Conditions
  Actions
    Game - Force Player 3 (Teal) to press the key A.
Used to cancel the whole building process if the player decides to not place the building
Force Cancel P4
  Events
    Time - Every 0.01 seconds of game time
  Conditions
  Actions
    Game - Force Player 4 (Purple) to press the key A.
Refund player if it cancels building or placement of it
Cancelled
  Events
    Unit - A unit Starts the effect of an ability
  Conditions
    (Ability being cast) Equal to Cancel
    ((Owner of (Casting unit)) is in Build_Players.) Equal to False
  Actions
    Trigger - Turn off Force_Cancel_P1 <gen>
    Trigger - Turn off Force_Cancel_P2 <gen>
    Trigger - Turn off Force_Cancel_P3 <gen>
    Trigger - Turn off Force_Cancel_P4 <gen>
    Selection - Remove (Casting unit) from selection for (Owner of (Casting unit))
    Unit - Remove (Casting unit) from the game
    -------- Refund --------
    For each (Integer B) from 1 to 40, do (Actions)
      Loop - Actions
        If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          If - Conditions
            Build_Structure[(Player number of (Owner of (Triggering unit)))] Equal to BuildDB_Buildings[(Integer B)]
          Then - Actions
            Player - Add BuildDB_Cost[(Integer B)] to (Owner of (Casting unit)).Current gold
          Else - Actions
Create a dummy builder which builds selected building and then disappears. Building count around the hall is increased by 1.

Building
  Events
    Unit - A unit Is issued an order targeting a point
  Conditions
    Place Structure (Human-item) Equal to (Unit-type of (Ordered unit))
    (Distance between (Position of (Ordered unit)) and (Target point of issued order)) Less than or equal to 1000.00
  Actions
    Player Group - Add (Owner of (Ordered unit)) to Build_Players
    Trigger - Turn off Force_Cancel_P1 <gen>
    Trigger - Turn off Force_Cancel_P2 <gen>
    Trigger - Turn off Force_Cancel_P3 <gen>
    Trigger - Turn off Force_Cancel_P4 <gen>
    Selection - Remove (Ordered unit) from selection for (Owner of (Ordered unit))
    Wait 0.27 seconds
    Custom script: set bj_wantDestroyGroup = true
    Unit Group - Pick every unit in (Units owned by (Owner of (Ordered unit)) of type Place Structure (Human-item)) and do (Actions)
      Loop - Actions
        Unit - Remove (Picked unit) from the game
    Player Group - Remove (Owner of (Ordered unit)) from Build_Players.
    Wait 0.27 seconds
    -------- If building cannot be placed --------
    If (All Conditions are True) then do (Then Actions) else do (Else Actions)
      If - Conditions
        (Number of units in (Units in (Region centered at (Target point of issued order) with size (200.00, 200.00)) matching ((Unit-type of (Matching unit)) Equal to Build_Structure[(Player number of (Owner of (Ordered unit)))]))) Equal to 0
      Then - Actions
        For each (Integer A) from 1 to 40, do (Actions)
          Loop - Actions
            If (All Conditions are True) then do (Then Actions) else do (Else Actions)
              If - Conditions
                Build_Structure[(Integer A)] Equal to BuildDB_Buildings[(Integer A)]
              Then - Actions
                Player - Add BuildDB_Cost[(Integer A)] to (Owner of (Casting unit)).Current gold
              Else - Actions
      Else - Actions
Memorize currently selected units to show the current number of units in the batalion and to preserve selection if one of selected leader falls in the battle.
Selection Selection thingie Copy Copy 2
  Events
    Player - Player 1 (Red) Selects a unit
    Player - Player 2 (Blue) Selects a unit
    Player - Player 3 (Teal) Selects a unit
    Player - Player 4 (Purple) Selects a unit
    Player - Player 5 (Yellow) Selects a unit
    Player - Player 6 (Orange) Selects a unit
    Player - Player 7 (Green) Selects a unit
    Player - Player 8 (Pink) Selects a unit
  Conditions
    ((Triggering unit) is A town-hall-type unit) Equal to True
  Actions
    Set VariableSet Tempint = (Load (Key (String((Unit-type of (Triggering unit)))).) of (Key (Triggering unit).) from hashtable.)
    Floating Text - Create floating text that reads (String(Tempint)) above (Triggering unit) with Z offset 0, using font size 10, color (100.00%, 0.00%, 0.00%), and 0% transparency
    Floating Text - Hide (Last created floating text) for (All players)
    Floating Text - Show (Last created floating text) for (Player group((Owner of (Triggering unit))))
    Floating Text - Change (Last created floating text): Disable permanence
    Floating Text - Change the lifespan of (Last created floating text) to 1.00 seconds
Sanctuary
  Events
    Unit - A unit Starts the effect of an ability
  Conditions
    (Ability being cast) Equal to Sanctuary (channel)
  Actions
    Unit - Create 1.Sanctuary for (Owner of (Triggering unit)) at (Target point of ability being cast) facing Default building facing degrees
    Unit - Add a 30.00 second Generic expiration timer to (Last created unit)
Current limit is up 10 spells. To increase go to Battalion spells trigger and increase exitwhen number
Initialization Spells
  Events
    Map initialization
  Conditions
  Actions
    -------- Web trap --------
    Set VariableSet BattalionSpellAbility[1] = Gravity Lapse
    Set VariableSet BattalionSpellCaster[1] = Sorceror Stone
    Set VariableSet BattalionSpellOrderID[1] = 852106
    Set VariableSet BattalionSpellOrderString[1] = ensnare
    -------- Temptation --------
    Set VariableSet BattalionSpellAbility[2] = Malediction
    Set VariableSet BattalionSpellCaster[2] = Archon
    Set VariableSet BattalionSpellOrderID[2] = 852668
    Set VariableSet BattalionSpellOrderString[2] = soulburn
    -------- Temptation --------
    Set VariableSet BattalionSpellAbility[3] = Arctic Hold
    Set VariableSet BattalionSpellCaster[3] = Spellweaver
    Set VariableSet BattalionSpellOrderID[3] = 852227
    Set VariableSet BattalionSpellOrderString[3] = sleep
    -------- Lifeboon --------
    Set VariableSet BattalionSpellAbility[4] = Healing Juice
    Set VariableSet BattalionSpellCaster[4] = Battle Priest
    Set VariableSet BattalionSpellOrderID[4] = 852160
    Set VariableSet BattalionSpellOrderString[4] = rejuvination
    -------- Vengeance --------
    Set VariableSet BattalionSpellAbility[5] = Mark Target
    Set VariableSet BattalionSpellCaster[5] = Imperial General
    Set VariableSet BattalionSpellOrderID[5] = 852662
    Set VariableSet BattalionSpellOrderString[5] = acidbomb
    -------- Invisibility Channel --------
    Set VariableSet BattalionSpellAbility[6] = Invisbility (Channel)
    Set VariableSet BattalionSpellCaster[6] = Glade Warden
    Set VariableSet BattalionSpellOrderID[6] = 6
    Set VariableSet BattalionSpellOrderString[6] = invisibility
    -------- Invisibility Cloaks --------
    Set VariableSet BattalionSpellAbility[8] = Elven Cloaks (Neutral Hostile)
    Set VariableSet BattalionSpellCaster[8] = Scout (Captain)
    Set VariableSet BattalionSpellOrderID[8] = 852129
    Set VariableSet BattalionSpellOrderString[8] = windwalk
    -------- Invisibility Shround --------
    Set VariableSet BattalionSpellAbility[7] = Shadow Shroud
    Set VariableSet BattalionSpellCaster[7] = Shadow Witch
    Set VariableSet BattalionSpellOrderID[7] = 852069
    Set VariableSet BattalionSpellOrderString[7] = invisibility
    -------- Whip of Frenzy --------
    Set VariableSet BattalionSpellAbility[9] = Whip of Frenzy
    Set VariableSet BattalionSpellCaster[9] = Shadow Witch
    Set VariableSet BattalionSpellOrderID[9] = 852209
    Set VariableSet BattalionSpellOrderString[9] = frenzy
//TESH.scrollpos=0
//TESH.alwaysfold=0

function Trig_Battalion_spells_Conditions takes nothing returns boolean
    local integer battallionIndex
    if ( LoadInteger(udg_hashtable, GetHandleId(GetSpellTargetUnit()), 0) > 0 and GetBatalionAbility(GetSpellAbilityId()) > 0) then
        return true
    else
        return false
    endif
endfunction

function CastSpell takes nothing returns nothing
    local unit dummy
    local integer abilityIndex = GetBatalionAbility(udg_Tempint)
    //call BJDebugMsg(I2S(GetSpellAbilityId()))    
    set dummy = CreateUnit( GetOwningPlayer(GetTriggerUnit()), 'h60H', GetUnitX(GetEnumUnit()), GetUnitY(GetEnumUnit()), bj_UNIT_FACING)
    call IssueTargetOrderById( dummy, udg_BattalionSpellOrderID[abilityIndex], GetEnumUnit() )
    call UnitApplyTimedLife( dummy, 'BTLF', 1.00 )
    set dummy = null
endfunction

function Trig_Battalion_spells_Actions takes nothing returns nothing
    local integer battallionIndexTarget = LoadInteger(udg_hashtable, GetHandleId(GetSpellTargetUnit()), 0)
    local integer battallionIndexCaster = LoadInteger(udg_hashtable, GetHandleId(GetTriggerUnit()), 0)
    set udg_Tempint = GetSpellAbilityId()
   
    call GroupRemoveUnit( udg_Battallion[battallionIndexCaster], GetTriggerUnit() )
    call GroupTargetOrder( udg_Battallion[battallionIndexCaster], "smart", GetTriggerUnit() )
    call GroupAddUnit( udg_Battallion[battallionIndexCaster], GetTriggerUnit() )
    call DisableTrigger( GetTriggeringTrigger() )
    call ForGroup( udg_Battallion[battallionIndexTarget], function CastSpell )
    call EnableTrigger( GetTriggeringTrigger() )
endfunction

//===========================================================================
function InitTrig_Battalion_spells takes nothing returns nothing
    set gg_trg_Battalion_spells = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Battalion_spells, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Battalion_spells, Condition( function Trig_Battalion_spells_Conditions ) )
    call TriggerAddAction( gg_trg_Battalion_spells, function Trig_Battalion_spells_Actions )
endfunction

 
Comandeer
  Events
    Unit - A unit Starts the effect of an ability
  Conditions
    (Ability being cast) Equal to Commandeer
  Actions
    Set VariableSet BattallionIndex = (Load 0 of (Key (Target unit of ability being cast).) from hashtable.)
    Unit Group - Pick every unit in Battallion[BattallionIndex] and do (Actions)
      Loop - Actions
        If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          If - Conditions
            (Unit-type of (Picked unit)) Not equal to (Unit-type of (Target unit of ability being cast))
          Then - Actions
            Unit - Kill (Picked unit)
          Else - Actions
    Unit - Create 1.Engineer for (Player(((Player number of (Owner of (Casting unit))) + TranslatePlayerNumber))) at (Position of (Target unit of ability being cast)) facing Default building facing degrees
    Unit - Change color of (Last created unit) to (Color of (Owner of (Casting unit)))
    Hashtable - Save BattallionIndex as 0 of (Key (Last created unit).) in hashtable.
    Hashtable - Save BatalionHash_Crew as Summon of (Key (Last created unit).) in hashtable.
    Unit Group - Add (Last created unit) to Battallion[BattallionIndex]
    Unit - Create 1.Engineer for (Player(((Player number of (Owner of (Casting unit))) + TranslatePlayerNumber))) at (Position of (Target unit of ability being cast)) facing Default building facing degrees
    Hashtable - Save BattallionIndex as 0 of (Key (Last created unit).) in hashtable.
    Hashtable - Save BatalionHash_Crew as Summon of (Key (Last created unit).) in hashtable.
    Unit - Change color of (Last created unit) to (Color of (Owner of (Casting unit)))
    Unit Group - Add (Last created unit) to Battallion[BattallionIndex]
Familiar
  Events
    Unit - A unit Finishes casting an ability
  Conditions
    (Unit-type of (Casting unit)) Equal to Archon
    (Ability being cast) Equal to Familiar (Battallion)
  Actions
    Set VariableSet Temppoint01 = (Position of (Casting unit))
    Set VariableSet Tempunit = (Casting unit)
    Set VariableSet BattallionIndex = (Load 0 of (Key (Casting unit).) from hashtable.)
    For each (Integer A) from 1 to NrTypes, do (Actions)
      Loop - Actions
        If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          If - Conditions
            (Unit-type of Tempunit) Equal to BattalionCaptain[(Integer A)]
          Then - Actions
            Set VariableSet Tempint = (Integer A)
          Else - Actions
    For each (Integer A) from (Number of units in Battallion[BattallionIndex]) to BattalionSize[Tempint], do (Actions)
      Loop - Actions
        Unit - Create 1.BattalionTroop[Tempint] for (Player(((Player number of (Owner of Tempunit)) + TranslatePlayerNumber))) at Temppoint01 facing (Random angle) degrees
        Unit - Change color of (Last created unit) to (Color of (Owner of Tempunit))
        Unit Group - Add (Last created unit) to Battallion[BattallionIndex]
        Hashtable - Save BattallionIndex as 0 of (Key (Last created unit).) in hashtable.
        Unit - Add a 60.00 second Generic expiration timer to (Last created unit)
        AI - Ignore (Last created unit)'s guard position
        Unit - Order (Last created unit) to Follow.Tempunit
    Custom script: call RemoveLocation(udg_Temppoint01)
Vulture
  Events
    Unit - A unit Finishes casting an ability
  Conditions
    (Unit-type of (Casting unit)) Equal to Nomad
    (Ability being cast) Equal to Vulture (Battallion)
  Actions
    Set VariableSet Temppoint01 = (Position of (Casting unit))
    Set VariableSet Tempunit = (Casting unit)
    Set VariableSet BattallionIndex = (Load 0 of (Key (Casting unit).) from hashtable.)
    For each (Integer A) from 1 to NrTypes, do (Actions)
      Loop - Actions
        If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          If - Conditions
            (Unit-type of Tempunit) Equal to BattalionCaptain[(Integer A)]
          Then - Actions
            Set VariableSet Tempint = (Integer A)
          Else - Actions
    For each (Integer A) from (Number of units in Battallion[BattallionIndex]) to BattalionSize[Tempint], do (Actions)
      Loop - Actions
        Unit - Create 1.BattalionTroop[Tempint] for (Player(((Player number of (Owner of Tempunit)) + TranslatePlayerNumber))) at Temppoint01 facing (Random angle) degrees
        Unit - Change color of (Last created unit) to (Color of (Owner of Tempunit))
        Unit Group - Add (Last created unit) to Battallion[BattallionIndex]
        Hashtable - Save BattallionIndex as 0 of (Key (Last created unit).) in hashtable.
        Unit - Add a 60.00 second Generic expiration timer to (Last created unit)
        AI - Ignore (Last created unit)'s guard position
        Unit - Order (Last created unit) to Follow.Tempunit
    Custom script: call RemoveLocation(udg_Temppoint01)
Battalion death Ctrl New Copy
  Events
    Unit - A unit Dies
  Conditions
    (Load Summon of (Key (Dying unit).) from hashtable.) Equal to 2
  Actions
    Set VariableSet BattallionIndex = (Load 0 of (Key (Dying unit).) from hashtable.)
    If (All Conditions are True) then do (Then Actions) else do (Else Actions)
      If - Conditions
        (Load 1 of (Key (Dying unit).) from hashtable.) Equal to 1
      Then - Actions
        Unit Group - Pick every unit in Battallion[BattallionIndex] and do (Actions)
          Loop - Actions
            Unit - Change ownership of (Picked unit) to (Owner of (Dying unit)) and Retain color
            Unit Group - Remove (Picked unit) from Battallion[BattallionIndex].
      Else - Actions
        Unit Group - Remove (Dying unit) from Battallion[BattallionIndex].
        If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          If - Conditions
            (Number of units in Battallion[BattallionIndex]) Equal to 1
          Then - Actions
            Unit Group - Pick every unit in Battallion[BattallionIndex] and do (Actions)
              Loop - Actions
                Unit - Change ownership of (Picked unit) to Neutral Passive and Change color
          Else - Actions
Shake it baby
  Events
  Conditions
  Actions
    For each (Integer A) from 1 to 2, do (Actions)
      Loop - Actions
        If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          If - Conditions
            ((Player((Integer A))) controller) Equal to Computer
          Then - Actions
            Game - Display to (All players) the text: shake it baby
            Custom script: set bj_wantDestroyGroup = true
            Unit Group - Pick every unit in (Units owned by (Player((Integer A))) matching ((Distance between (Position of (Matching unit)) and (Position of AI_Townhall[(Integer A)])) Less than 1000.00).) and do (Actions)
              Loop - Actions
                Special Effect - Create a special effect attached to the overhead (attachpoint) of (Picked unit) using Abilities\Spells\Other\TalkToMe\TalkToMe.mdl
                Unit - Order (Picked unit) to Move To.(Random point in (Region centered at AI_TownHall[(Integer A)] with size (2000.00, 2000.00)))
          Else - Actions
//TESH.scrollpos=0
//TESH.alwaysfold=0
function Trig_Untitled_Trigger_003_Actions takes nothing returns nothing
    call Cheat("warpten")
    call Cheat("greedisgood 20000")
    call Cheat("whosyourdaddy")
    call Cheat("iseedeadpeople")
endfunction

//===========================================================================
function InitTrig_Cheats takes nothing returns nothing
    set gg_trg_Cheats = CreateTrigger(  )
    call TriggerRegisterTimerEventSingle( gg_trg_Cheats, 1.00 )
    call TriggerAddAction( gg_trg_Cheats, function Trig_Untitled_Trigger_003_Actions )
endfunction

 
test parameters
  Events
    Map initialization
  Conditions
  Actions
    Visibility - Disable black mask
    Visibility - Disable fog of war
    Camera - Pan camera for Player 1 (Red) to (Player 4 (Purple) start location) over 0 seconds
    Set VariableSet AI_HumanUnits[0] = Halberdier (Captain)
    Set VariableSet AI_HumanUnits[1] = Rifleman (Captain)
    Set VariableSet AI_HumanUnits[2] =
    Set VariableSet AI_HumanUnits[3] = Field Mortar
    Set VariableSet AI_HumanUnits[4] = Cyclone Cannon
    Set VariableSet AI_HumanUnits[5] = Cavalier (Captain)
    Set VariableSet AI_HumanUnits[6] =
    Set VariableSet AI_HumanUnits[7] = Master Engineer
    Set VariableSet AI_VampireUnits[0] =
    Set VariableSet AI_VampireUnits[1] =
    Set VariableSet AI_VampireUnits[2] =
    Set VariableSet AI_VampireUnits[3] =
    Set VariableSet AI_VampireUnits[4] = Sorceror Stone
    Set VariableSet AI_VampireUnits[5] =
    Set VariableSet AI_VampireUnits[6] =
    Set VariableSet AI_VampireUnits[7] =
    Set VariableSet AI_ElfUnits[0] = Scout (Captain)
    Set VariableSet AI_ElfUnits[1] = Wild Riders (Captain)
    Set VariableSet AI_ElfUnits[2] = Pixie (Captain)
    Set VariableSet AI_ElfUnits[3] = Manticore Ballista
    Set VariableSet AI_ElfUnits[4] =
    Set VariableSet AI_ElfUnits[5] =
    Set VariableSet AI_ElfUnits[6] = Glade Warden
    Set VariableSet AI_ElfUnits[7] = Spellweaver
    Set VariableSet AI_DrowUnits[0] =
    Set VariableSet AI_DrowUnits[1] = Reaper (Captain)
    Set VariableSet AI_DrowUnits[2] = Spider Rider (Captain)
    Set VariableSet AI_DrowUnits[3] = Shadow Witch
    Set VariableSet AI_DrowUnits[4] = Voidfire
    Set VariableSet AI_DrowUnits[5] =
    Set VariableSet AI_DrowUnits[6] = Matriarch
    Set VariableSet AI_DrowUnits[7] = Archon
    Set VariableSet AI_Wave[(Player number of Player 1 (Red))] = 1
    Set VariableSet AI_Wave[(Player number of Player 2 (Blue))] = 1
    Set VariableSet AI_Wave[(Player number of Player 3 (Teal))] = 1
    Set VariableSet AI_Wave[(Player number of Player 4 (Purple))] = 1
    Trigger - Run Attack_group_P1 <gen> (ignoring conditions)
    Wait 5.00 seconds
    Trigger - Run Attack_group_P2 <gen> (ignoring conditions)
    Trigger - Run Attack_group_P3 <gen> (ignoring conditions)
    Trigger - Run Attack_group_P4 <gen> (ignoring conditions)
Flush
  Events
    Time - Every 21.00 seconds of game time
  Conditions
  Actions
    For each (Integer A) from 1 to 4, do (Actions)
      Loop - Actions
        If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          If - Conditions
            ((Player((Integer A))) controller) Equal to Computer
          Then - Actions
            Unit Group - Pick every unit in AI_Defenders[(Integer A)] and do (Actions)
              Loop - Actions
                Set VariableSet Temppoint = (Position of (Picked unit))
                Set VariableSet Temppoint01 = (Temppoint offset by 100.00 towards (Random angle) degrees.)
                If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                  If - Conditions
                    (Distance between AI_TownHall[(Integer A)] and Temppoint) Less than 1000.00
                    (Distance between AI_TownHall[(Integer A)] and Temppoint01) Less than 1000.00
                  Then - Actions
                    Unit - Order (Picked unit) to Move To.Temppoint01
                  Else - Actions
                If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                  If - Conditions
                    ((Picked unit) is A Hero) Equal to True
                    Equal to (Unit-type of (Picked unit))
                  Then - Actions
                    Unit - Order (Picked unit) to Move To.AI_TownHall[(Player number of (Owner of (Picked unit)))]
                  Else - Actions
                Custom script: call RemoveLocation( udg_Temppoint )
                Custom script: call RemoveLocation( udg_Temppoint01 )
          Else - Actions
Hero Learn Just Trained
  Events
    Unit - A unit Finishes training a unit
  Conditions
    ((Owner of (Trained unit)) controller) Equal to Computer
  Actions
    If (All Conditions are True) then do (Then Actions) else do (Else Actions)
      If - Conditions
        (Unit-type of (Trained unit)) Equal to Archon
      Then - Actions
        Hero - Learn skill for (Trained unit): Wisdom
      Else - Actions
Hero Learn
  Events
    Unit - A unit Gains a level
  Conditions
    ((Owner of (Leveling Hero)) controller) Equal to Computer
  Actions
    If (All Conditions are True) then do (Then Actions) else do (Else Actions)
      If - Conditions
        (Hero level of (Leveling Hero)) Equal to 2
      Then - Actions
        If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          If - Conditions
            (Unit-type of (Leveling Hero)) Equal to Archon
          Then - Actions
            Hero - Learn skill for (Leveling Hero): Fortitude
          Else - Actions
      Else - Actions
        If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          If - Conditions
            (Hero level of (Leveling Hero)) Equal to 3
          Then - Actions
            If (All Conditions are True) then do (Then Actions) else do (Else Actions)
              If - Conditions
                (Unit-type of (Leveling Hero)) Equal to Archon
              Then - Actions
                Hero - Learn skill for (Leveling Hero): Wisdom
              Else - Actions
          Else - Actions
            If (All Conditions are True) then do (Then Actions) else do (Else Actions)
              If - Conditions
                (Hero level of (Leveling Hero)) Equal to 4
              Then - Actions
                If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                  If - Conditions
                    (Unit-type of (Leveling Hero)) Equal to Archon
                  Then - Actions
                    Hero - Learn skill for (Leveling Hero): Agility