//===========================================================================

// 

// |CFFFFFF00Power of Corruption v2.3

// 

//   Warcraft III map script

//   Generated by the Warcraft III World Editor

//   Date: Sun Aug 05 10:31:40 2012

//   Map Author: moyack - poc.it.cx

// 

//===========================================================================



//***************************************************************************

//*

//*  Global Variables

//*

//***************************************************************************



globals

    // User-defined

    location                udg_loc                    = null

    unit                    udg_Unit                   = null



    // Generated

    trigger                 gg_trg_HCL                 = null

    trigger                 gg_trg_ARGB                = null

    trigger                 gg_trg_Board               = null

    trigger                 gg_trg_Alloc               = null

    trigger                 gg_trg_Indexor2            = null

    trigger                 gg_trg_DataPreloader       = null

    trigger                 gg_trg_MainGlobals         = null

    trigger                 gg_trg_CACHE               = null

    trigger                 gg_trg_RegisterAnyUnitEvent = null

    trigger                 gg_trg_SpellBlocker        = null

    trigger                 gg_trg_MicroTable          = null

    trigger                 gg_trg_UnitDamage          = null

    trigger                 gg_trg_DamageCredit        = null

    trigger                 gg_trg_SetUnitMaxState     = null

    trigger                 gg_trg_MovSys              = null

    trigger                 gg_trg_ProjSys             = null

    trigger                 gg_trg_DummyCast           = null

    trigger                 gg_trg_TimedEffects        = null

    trigger                 gg_trg_LastCommand         = null

    trigger                 gg_trg_IsUnitStuck_n_jump_ability = null

    trigger                 gg_trg_Melee_Initialization = null

    trigger                 gg_trg_Play_Race_Music     = null

    trigger                 gg_trg_Credits             = null

    trigger                 gg_trg_Multiboard_Control  = null

    trigger                 gg_trg_Handle_Counter      = null

    trigger                 gg_trg_Devotion_points     = null

    trigger                 gg_trg_Pray_for_Gold       = null

    trigger                 gg_trg_Pray_for_Lumber     = null

    trigger                 gg_trg_Naga_Ability        = null

    trigger                 gg_trg_Poisoning_Skin      = null

    trigger                 gg_trg_Illusion            = null

    trigger                 gg_trg_SoulControl         = null

    trigger                 gg_trg_SoulThirst          = null

    trigger                 gg_trg_Betrayal            = null

    trigger                 gg_trg_WaterBurst          = null

    trigger                 gg_trg_CrushingTide        = null

    trigger                 gg_trg_Freeze              = null

    trigger                 gg_trg_Lightning_Vortex    = null

    trigger                 gg_trg_LoyaltyandSacrifice = null

    trigger                 gg_trg_Murgulogenesis      = null

    trigger                 gg_trg_FearPoison          = null

    trigger                 gg_trg_ToxicFog            = null

    trigger                 gg_trg_WaterShield         = null

    trigger                 gg_trg_Sonic               = null

    trigger                 gg_trg_Broodlings          = null

    trigger                 gg_trg_Summon_Magic_Vault  = null

    trigger                 gg_trg_Demon_Ability       = null

    trigger                 gg_trg_Inner_Hell          = null

    trigger                 gg_trg_HellFire            = null

    trigger                 gg_trg_Sadism              = null

    trigger                 gg_trg_Fetid_Stomach       = null

    trigger                 gg_trg_Mighty_Smash        = null

    trigger                 gg_trg_Stunning_Punch      = null

    trigger                 gg_trg_Gluttony            = null

    trigger                 gg_trg_NetherVortex        = null

    trigger                 gg_trg_TributeoftheCursed  = null

    trigger                 gg_trg_AuraofDamnation     = null

    trigger                 gg_trg_SoulofDarkness      = null

    trigger                 gg_trg_LavaBombs           = null

    trigger                 gg_trg_FierceArrow         = null

    trigger                 gg_trg_FireExplosion       = null

    trigger                 gg_trg_Havoc               = null

    trigger                 gg_trg_Summon_Artifact_Pit = null

    trigger                 gg_trg_Slave_Harvest       = null

    trigger                 gg_trg_DoubleAttack        = null

    trigger                 gg_trg_TreacherousAttack   = null

    trigger                 gg_trg_RabidBite           = null

    trigger                 gg_trg_Torment             = null

    trigger                 gg_trg_Drain_Magic         = null

    trigger                 gg_trg_Vampire_Claymore    = null

    trigger                 gg_trg_Manipulation        = null

    trigger                 gg_trg_Blood_Aroma         = null

    trigger                 gg_trg_Spring_of_Azshara   = null

    trigger                 gg_trg_NerubianGuardian    = null

    trigger                 gg_trg_SpiderEggs          = null

    trigger                 gg_trg_AI_Hydra_Control    = null

    trigger                 gg_trg_Protect_weak_units  = null

    trigger                 gg_trg_Low_gold            = null

    trigger                 gg_trg_Low_lumber          = null

    trigger                 gg_trg_Random_AI_names     = null

    trigger                 gg_trg_Cheat               = null



    // Random Groups

    integer array gg_rg_000

endglobals



function InitGlobals takes nothing returns nothing

endfunction



//***************************************************************************

//*

//*  Random Groups

//*

//***************************************************************************



function InitRandomGroups takes nothing returns nothing

    local integer curset



    // Group 0 - RandomCreepItems

    call RandomDistReset(  )

    call RandomDistAddItem( 0, 10 )

    call RandomDistAddItem( 1, 20 )

    call RandomDistAddItem( 2, 10 )

    call RandomDistAddItem( 3, 20 )

    call RandomDistAddItem( 4, 20 )

    call RandomDistAddItem( 5, 20 )

    set curset = RandomDistChoose(  )



    if (curset == 0) then

        set gg_rg_000[0] = 'rdis'

    elseif (curset == 1) then

        set gg_rg_000[0] = 'rhe1'

    elseif (curset == 2) then

        set gg_rg_000[0] = 'rre1'

    elseif (curset == 3) then

        set gg_rg_000[0] = 'rman'

    elseif (curset == 4) then

        set gg_rg_000[0] = 'rspd'

    elseif (curset == 5) then

        set gg_rg_000[0] = 'rspl'

    else

        set gg_rg_000[0] = -1

    endif



endfunction



//***************************************************************************

//*

//*  Unit Item Tables

//*

//***************************************************************************



function Unit000005_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_PERMANENT, 2 ), 33 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_CHARGED, 2 ), 34 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_POWERUP, 2 ), 33 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000006_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_PERMANENT, 1 ), 50 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_POWERUP, 1 ), 50 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000010_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_PERMANENT, 1 ), 50 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_POWERUP, 1 ), 50 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000012_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_PERMANENT, 2 ), 33 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_CHARGED, 2 ), 34 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_POWERUP, 2 ), 33 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000014_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_CHARGED, 2 ), 50 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_POWERUP, 2 ), 50 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000015_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_PERMANENT, 2 ), 33 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_CHARGED, 2 ), 34 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_POWERUP, 2 ), 33 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000018_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_PERMANENT, 3 ), 50 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_CHARGED, 3 ), 50 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000020_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_PERMANENT, 2 ), 33 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_CHARGED, 2 ), 34 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_POWERUP, 2 ), 33 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000021_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_PERMANENT, 3 ), 50 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_CHARGED, 3 ), 50 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000022_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_PERMANENT, 3 ), 50 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_CHARGED, 3 ), 50 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000024_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_CHARGED, 2 ), 50 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_POWERUP, 2 ), 50 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000028_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_CHARGED, 2 ), 50 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_POWERUP, 2 ), 50 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000030_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_PERMANENT, 5 ), 50 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_CHARGED, 5 ), 50 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000034_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_PERMANENT, 3 ), 50 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_CHARGED, 3 ), 50 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000037_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_PERMANENT, 5 ), 50 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_CHARGED, 5 ), 50 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000043_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_CHARGED, 4 ), 50 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_PERMANENT, 4 ), 50 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000049_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_PERMANENT, 3 ), 50 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_CHARGED, 3 ), 50 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000051_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_CHARGED, 4 ), 50 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_PERMANENT, 4 ), 50 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000058_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_PERMANENT, 1 ), 50 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_POWERUP, 1 ), 50 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000062_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_PERMANENT, 2 ), 33 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_CHARGED, 2 ), 34 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_POWERUP, 2 ), 33 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000066_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_PERMANENT, 1 ), 50 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_POWERUP, 1 ), 50 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000067_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_CHARGED, 2 ), 50 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_POWERUP, 2 ), 50 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000071_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_PERMANENT, 1 ), 50 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_POWERUP, 1 ), 50 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000074_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_PERMANENT, 1 ), 50 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_POWERUP, 1 ), 50 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000075_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_PERMANENT, 5 ), 50 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_CHARGED, 5 ), 50 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000077_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_PERMANENT, 4 ), 50 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_CHARGED, 4 ), 50 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000078_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_PERMANENT, 1 ), 50 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_POWERUP, 1 ), 50 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000081_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_PERMANENT, 2 ), 33 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_CHARGED, 2 ), 34 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_POWERUP, 2 ), 33 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000084_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_PERMANENT, 1 ), 50 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_POWERUP, 1 ), 50 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000085_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_PERMANENT, 1 ), 50 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_POWERUP, 1 ), 50 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000093_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_PERMANENT, 1 ), 50 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_POWERUP, 1 ), 50 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000096_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_PERMANENT, 2 ), 33 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_CHARGED, 2 ), 34 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_POWERUP, 2 ), 33 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000102_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_PERMANENT, 2 ), 33 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_CHARGED, 2 ), 34 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_POWERUP, 2 ), 33 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000103_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_PERMANENT, 1 ), 50 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_POWERUP, 1 ), 50 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000109_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_PERMANENT, 1 ), 50 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_POWERUP, 1 ), 50 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000112_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_PERMANENT, 2 ), 33 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_CHARGED, 2 ), 34 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_POWERUP, 2 ), 33 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000117_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_PERMANENT, 3 ), 50 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_CHARGED, 3 ), 50 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000119_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_PERMANENT, 3 ), 50 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_CHARGED, 3 ), 50 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000120_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_PERMANENT, 1 ), 50 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_POWERUP, 1 ), 50 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000124_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_PERMANENT, 5 ), 50 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_CHARGED, 5 ), 50 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000126_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_PERMANENT, 2 ), 33 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_CHARGED, 2 ), 34 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_POWERUP, 2 ), 33 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000127_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_PERMANENT, 5 ), 50 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_CHARGED, 5 ), 50 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000131_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_PERMANENT, 3 ), 50 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_CHARGED, 3 ), 50 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000137_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_CHARGED, 4 ), 50 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_PERMANENT, 4 ), 50 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000138_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_PERMANENT, 2 ), 33 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_CHARGED, 2 ), 34 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_POWERUP, 2 ), 33 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000144_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_PERMANENT, 4 ), 50 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_CHARGED, 4 ), 50 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000146_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_PERMANENT, 1 ), 50 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_POWERUP, 1 ), 50 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000149_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_PERMANENT, 3 ), 50 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_CHARGED, 3 ), 50 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000152_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_PERMANENT, 1 ), 50 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_POWERUP, 1 ), 50 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000156_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_PERMANENT, 1 ), 50 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_POWERUP, 1 ), 50 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000159_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_PERMANENT, 4 ), 50 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_CHARGED, 4 ), 50 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000166_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_PERMANENT, 1 ), 50 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_POWERUP, 1 ), 50 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000171_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_PERMANENT, 2 ), 33 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_CHARGED, 2 ), 34 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_POWERUP, 2 ), 33 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000174_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_PERMANENT, 4 ), 50 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_CHARGED, 4 ), 50 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000176_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_CHARGED, 4 ), 50 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_PERMANENT, 4 ), 50 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000177_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_PERMANENT, 2 ), 33 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_CHARGED, 2 ), 34 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_POWERUP, 2 ), 33 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000182_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_PERMANENT, 2 ), 33 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_CHARGED, 2 ), 34 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_POWERUP, 2 ), 33 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000185_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_PERMANENT, 5 ), 50 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_CHARGED, 5 ), 50 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000188_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_PERMANENT, 1 ), 50 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_POWERUP, 1 ), 50 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction



function Unit000192_DropItems takes nothing returns nothing

    local widget  trigWidget = null

    local unit    trigUnit   = null

    local integer itemID     = 0

    local boolean canDrop    = true



    set trigWidget = bj_lastDyingWidget

    if (trigWidget == null) then

        set trigUnit = GetTriggerUnit()

    endif



    if (trigUnit != null) then

        set canDrop = not IsUnitHidden(trigUnit)

        if (canDrop and GetChangingUnit() != null) then

            set canDrop = (GetChangingUnitPrevOwner() == Player(PLAYER_NEUTRAL_AGGRESSIVE))

        endif

    endif



    if (canDrop) then

        // Item set 0

        call RandomDistReset(  )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_PERMANENT, 3 ), 50 )

        call RandomDistAddItem( ChooseRandomItemEx( ITEM_TYPE_CHARGED, 3 ), 50 )

        set itemID = RandomDistChoose(  )

        if (trigUnit != null) then

            call UnitDropItem( trigUnit, itemID )

        else

            call WidgetDropItem( trigWidget, itemID )

        endif



    endif



    set bj_lastDyingWidget = null

    call DestroyTrigger(GetTriggeringTrigger())

endfunction





//***************************************************************************

//*

//*  Unit Creation

//*

//***************************************************************************



//===========================================================================

function CreateNeutralHostile takes nothing returns nothing

    local player p = Player(PLAYER_NEUTRAL_AGGRESSIVE)

    local unit u

    local integer unitID

    local trigger t

    local real life



    set u = CreateUnit( p, 'nscb', 4031.4, -4373.5, 35.471 )

    call SetUnitAcquireRange( u, 200.0 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000166_DropItems )

    set u = CreateUnit( p, 'njgb', -27.1, -8301.3, 92.870 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000127_DropItems )

    set u = CreateUnit( p, 'nsrn', 3595.6, 7142.6, 308.740 )

    call SetUnitState( u, UNIT_STATE_MANA, 0 )

    call SetUnitAcquireRange( u, 200.0 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000176_DropItems )

    set u = CreateUnit( p, 'ntrs', 8360.2, 8258.5, 226.763 )

    set u = CreateUnit( p, 'nscb', 4119.9, -4246.9, 253.695 )

    call SetUnitAcquireRange( u, 200.0 )

    set u = CreateUnit( p, 'nscb', 3913.3, -4311.7, 11.466 )

    call SetUnitAcquireRange( u, 200.0 )

    set u = CreateUnit( p, 'nsko', 3237.7, -7247.9, 56.318 )

    call SetUnitAcquireRange( u, 200.0 )

    set u = CreateUnit( p, 'nsko', 2928.8, -7088.2, 19.501 )

    call SetUnitAcquireRange( u, 200.0 )

    set u = CreateUnit( p, 'nsko', 3123.1, -7087.7, 28.804 )

    call SetUnitAcquireRange( u, 200.0 )

    set u = CreateUnit( p, 'njga', 6806.9, -6158.4, 150.500 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000144_DropItems )

    set u = CreateUnit( p, 'nsko', 3765.1, 7153.0, 291.351 )

    call SetUnitAcquireRange( u, 200.0 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000177_DropItems )

    set u = CreateUnit( p, 'nsko', 3731.9, 7027.0, 303.428 )

    call SetUnitAcquireRange( u, 200.0 )

    set u = CreateUnit( p, 'nsko', 3492.4, 6999.9, 327.696 )

    call SetUnitAcquireRange( u, 200.0 )

    set u = CreateUnit( p, 'nsko', 3166.1, -7453.2, 61.210 )

    call SetUnitAcquireRange( u, 200.0 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000138_DropItems )

    set u = CreateUnit( p, 'nsko', 3608.5, 6945.6, 325.355 )

    call SetUnitAcquireRange( u, 200.0 )

    set u = CreateUnit( p, 'nsrv', 8422.4, -9037.4, 142.622 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000117_DropItems )

    set u = CreateUnit( p, 'nlpd', -2192.2, -3834.4, 253.880 )

    set u = CreateUnit( p, 'njg1', -236.0, -7951.8, 23.737 )

    set u = CreateUnit( p, 'nlpd', -2035.0, -3894.6, 225.619 )

    set u = CreateUnit( p, 'nscb', -4201.1, -4303.7, 11.466 )

    call SetUnitAcquireRange( u, 200.0 )

    set u = CreateUnit( p, 'nscb', -4068.0, -4405.2, 253.695 )

    call SetUnitAcquireRange( u, 200.0 )

    set u = CreateUnit( p, 'nscb', -4187.6, -4433.2, 126.550 )

    call SetUnitAcquireRange( u, 200.0 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000093_DropItems )

    set u = CreateUnit( p, 'njg1', 209.5, -7959.7, 151.241 )

    set u = CreateUnit( p, 'ntrt', -301.0, -8152.0, 51.620 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000081_DropItems )

    set u = CreateUnit( p, 'nsgb', -7397.2, -140.4, 3.930 )

    call SetUnitState( u, UNIT_STATE_MANA, 0 )

    call SetUnitAcquireRange( u, 200.0 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000049_DropItems )

    set u = CreateUnit( p, 'ntrt', -7263.1, 81.2, 328.050 )

    call SetUnitAcquireRange( u, 200.0 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000084_DropItems )

    set u = CreateUnit( p, 'ntrt', 110.4, 7917.2, 241.773 )

    set u = CreateUnit( p, 'ntrt', 271.5, -8217.9, 128.267 )

    set u = CreateUnit( p, 'nsko', -3115.3, -7137.2, 148.052 )

    call SetUnitAcquireRange( u, 200.0 )

    set u = CreateUnit( p, 'ntrt', -7242.8, -382.7, 43.231 )

    call SetUnitAcquireRange( u, 200.0 )

    set u = CreateUnit( p, 'nlkl', -1876.3, -1892.5, 64.630 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000028_DropItems )

    set u = CreateUnit( p, 'nsrv', -8350.3, 8390.2, 320.411 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000131_DropItems )

    set u = CreateUnit( p, 'nsko', -3275.6, -7086.9, 120.000 )

    call SetUnitAcquireRange( u, 200.0 )

    set u = CreateUnit( p, 'nlpd', -1881.0, -1635.2, 48.726 )

    set u = CreateUnit( p, 'nlpd', -1695.1, -1781.2, 68.040 )

    set u = CreateUnit( p, 'nsko', -3425.8, -7236.5, 99.423 )

    call SetUnitAcquireRange( u, 200.0 )

    set u = CreateUnit( p, 'nsrh', 8294.2, -9206.3, 123.529 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000109_DropItems )

    set u = CreateUnit( p, 'nsko', -3599.5, 7020.8, 202.570 )

    call SetUnitAcquireRange( u, 200.0 )

    set u = CreateUnit( p, 'njga', -6720.9, -6202.7, 51.980 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000159_DropItems )

    set u = CreateUnit( p, 'nsko', -3749.1, 7188.3, 256.701 )

    call SetUnitAcquireRange( u, 200.0 )

    set u = CreateUnit( p, 'nsrh', -6853.7, -5927.0, 35.440 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000005_DropItems )

    set u = CreateUnit( p, 'nsko', -3401.8, 7085.6, 200.451 )

    call SetUnitAcquireRange( u, 200.0 )

    set u = CreateUnit( p, 'nsko', -3667.2, 7344.5, 250.919 )

    call SetUnitAcquireRange( u, 200.0 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000062_DropItems )

    set u = CreateUnit( p, 'nsrh', -6514.7, -6279.1, 62.135 )

    set u = CreateUnit( p, 'nsrh', -8227.8, 8520.2, 299.641 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000074_DropItems )

    set u = CreateUnit( p, 'nsrh', -8522.6, 8237.4, 344.178 )

    set u = CreateUnit( p, 'ntrs', -8130.8, 8369.7, 297.883 )

    set u = CreateUnit( p, 'nlpd', 1861.8, 1496.8, 221.359 )

    set u = CreateUnit( p, 'nsc2', -6637.7, -5894.0, 41.893 )

    set u = CreateUnit( p, 'nsrv', -8495.7, -8969.7, 42.330 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000119_DropItems )

    set u = CreateUnit( p, 'nsrh', 8608.1, -8841.1, 165.389 )

    set u = CreateUnit( p, 'ntrs', 8467.3, 8130.8, 197.745 )

    set u = CreateUnit( p, 'nsrh', 6667.7, -6330.5, 135.636 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000171_DropItems )

    set u = CreateUnit( p, 'nsrh', 6911.4, -5864.0, 171.411 )

    set u = CreateUnit( p, 'nsc2', 6697.0, -5929.4, 163.072 )

    set u = CreateUnit( p, 'ntrs', -8339.5, 8187.8, 343.838 )

    set u = CreateUnit( p, 'nsc2', 6589.3, -6140.1, 142.635 )

    set u = CreateUnit( p, 'nsrh', 8384.5, 8442.2, 237.953 )

    set u = CreateUnit( p, 'nsrn', -3560.6, 7183.9, 225.176 )

    call SetUnitState( u, UNIT_STATE_MANA, 0 )

    call SetUnitAcquireRange( u, 200.0 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000043_DropItems )

    set u = CreateUnit( p, 'nsrh', -8585.2, -8741.4, 17.000 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000120_DropItems )

    set u = CreateUnit( p, 'nsrh', -8304.1, -9110.9, 66.295 )

    set u = CreateUnit( p, 'nsko', -3369.5, -7390.5, 103.098 )

    call SetUnitAcquireRange( u, 200.0 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000112_DropItems )

    set u = CreateUnit( p, 'nsrn', -3251.7, -7276.0, 119.718 )

    call SetUnitState( u, UNIT_STATE_MANA, 0 )

    call SetUnitAcquireRange( u, 200.0 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000051_DropItems )

    set u = CreateUnit( p, 'ntrs', -8398.2, -8692.2, 26.998 )

    set u = CreateUnit( p, 'ntrs', -8205.1, -8849.2, 59.669 )

    set u = CreateUnit( p, 'nsrv', -2028.3, -3696.6, 235.680 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000018_DropItems )

    set u = CreateUnit( p, 'ntrv', -2226.6, -3646.2, 250.550 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000078_DropItems )

    set u = CreateUnit( p, 'nsoc', -7460.1, -3166.1, 297.050 )

    call SetUnitState( u, UNIT_STATE_MANA, 0 )

    call SetUnitAcquireRange( u, 200.0 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000124_DropItems )

    set u = CreateUnit( p, 'ntrt', -472.3, 8020.0, 295.770 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000096_DropItems )

    set u = CreateUnit( p, 'ntrv', -1897.5, -3879.4, 207.414 )

    set u = CreateUnit( p, 'njg1', 36.5, 7635.0, 229.320 )

    set u = CreateUnit( p, 'nsc2', -6473.5, -6043.3, 57.340 )

    set u = CreateUnit( p, 'nsrn', 3044.2, -7308.0, 43.911 )

    call SetUnitState( u, UNIT_STATE_MANA, 0 )

    call SetUnitAcquireRange( u, 200.0 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000137_DropItems )

    set u = CreateUnit( p, 'nsrh', -7365.9, -3020.3, 279.833 )

    call SetUnitState( u, UNIT_STATE_MANA, 0 )

    call SetUnitAcquireRange( u, 200.0 )

    set u = CreateUnit( p, 'nsrh', -7674.6, -3126.5, 309.300 )

    call SetUnitState( u, UNIT_STATE_MANA, 0 )

    call SetUnitAcquireRange( u, 200.0 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000126_DropItems )

    set u = CreateUnit( p, 'nsko', -7252.5, -3264.1, 269.749 )

    call SetUnitAcquireRange( u, 200.0 )

    set u = CreateUnit( p, 'nsko', -7579.1, -3348.2, 336.996 )

    call SetUnitAcquireRange( u, 200.0 )

    set u = CreateUnit( p, 'ntrt', 7342.4, -476.2, 143.559 )

    call SetUnitAcquireRange( u, 200.0 )

    set u = CreateUnit( p, 'nsgb', 7482.0, -234.4, 176.277 )

    call SetUnitState( u, UNIT_STATE_MANA, 0 )

    call SetUnitAcquireRange( u, 200.0 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000034_DropItems )

    set u = CreateUnit( p, 'ntrt', 7322.1, -12.3, 208.179 )

    call SetUnitAcquireRange( u, 200.0 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000006_DropItems )

    set u = CreateUnit( p, 'njgb', -154.4, 7825.5, 267.898 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000075_DropItems )

    set u = CreateUnit( p, 'njg1', -378.0, 7677.1, 306.315 )

    set u = CreateUnit( p, 'nsko', -7519.0, 2902.2, 40.032 )

    call SetUnitAcquireRange( u, 200.0 )

    set u = CreateUnit( p, 'nsko', -7223.2, 2711.5, 88.058 )

    call SetUnitAcquireRange( u, 200.0 )

    set u = CreateUnit( p, 'nsoc', -7405.6, 2669.7, 68.185 )

    call SetUnitState( u, UNIT_STATE_MANA, 0 )

    call SetUnitAcquireRange( u, 200.0 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000037_DropItems )

    set u = CreateUnit( p, 'nsrh', -7271.5, 2502.8, 84.496 )

    call SetUnitState( u, UNIT_STATE_MANA, 0 )

    call SetUnitAcquireRange( u, 200.0 )

    set u = CreateUnit( p, 'nsrh', -7612.1, 2716.6, 47.878 )

    call SetUnitState( u, UNIT_STATE_MANA, 0 )

    call SetUnitAcquireRange( u, 200.0 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000020_DropItems )

    set u = CreateUnit( p, 'njga', -6828.1, 5629.5, 312.477 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000174_DropItems )

    set u = CreateUnit( p, 'nsrh', -6884.1, 5448.4, 333.127 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000102_DropItems )

    set u = CreateUnit( p, 'nsrh', -6734.4, 5812.7, 295.361 )

    set u = CreateUnit( p, 'nsc2', -6700.3, 5477.3, 323.462 )

    set u = CreateUnit( p, 'nsc2', -6583.5, 5687.6, 295.697 )

    set u = CreateUnit( p, 'nsrh', 8625.4, 8113.3, 190.160 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000066_DropItems )

    set u = CreateUnit( p, 'nscb', -4155.0, 4308.2, 23.206 )

    call SetUnitAcquireRange( u, 200.0 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000146_DropItems )

    set u = CreateUnit( p, 'nscb', -4034.1, 4301.8, 253.695 )

    call SetUnitAcquireRange( u, 200.0 )

    set u = CreateUnit( p, 'nscb', -4197.2, 4186.7, 140.210 )

    call SetUnitAcquireRange( u, 200.0 )

    set u = CreateUnit( p, 'nsrv', -1916.1, 3102.7, 132.880 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000149_DropItems )

    set u = CreateUnit( p, 'nlpd', -1950.5, 3335.3, 156.019 )

    set u = CreateUnit( p, 'nlpd', -2102.5, 3265.6, 127.221 )

    set u = CreateUnit( p, 'ntrv', -2084.6, 3047.4, 112.393 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000152_DropItems )

    set u = CreateUnit( p, 'ntrv', -1795.9, 3281.1, 157.536 )

    set u = CreateUnit( p, 'nsrv', 8519.4, 8285.0, 214.407 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000021_DropItems )

    set u = CreateUnit( p, 'nsrh', 7235.3, 2537.7, 115.077 )

    call SetUnitState( u, UNIT_STATE_MANA, 0 )

    call SetUnitAcquireRange( u, 200.0 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000182_DropItems )

    set u = CreateUnit( p, 'nscb', -3282.6, -1767.3, 330.885 )

    call SetUnitAcquireRange( u, 200.0 )

    set u = CreateUnit( p, 'nscb', -3229.5, -1881.1, 194.212 )

    call SetUnitAcquireRange( u, 200.0 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000156_DropItems )

    set u = CreateUnit( p, 'nscb', -3383.4, -1848.9, 342.289 )

    call SetUnitAcquireRange( u, 200.0 )

    set u = CreateUnit( p, 'nscb', -3385.4, 1739.9, 342.289 )

    call SetUnitAcquireRange( u, 200.0 )

    set u = CreateUnit( p, 'nscb', -3284.5, 1821.5, 330.885 )

    call SetUnitAcquireRange( u, 200.0 )

    set u = CreateUnit( p, 'nscb', -3231.5, 1707.7, 194.212 )

    call SetUnitAcquireRange( u, 200.0 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000085_DropItems )

    set u = CreateUnit( p, 'nlkl', -1908.1, 1687.4, 307.198 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000067_DropItems )

    set u = CreateUnit( p, 'nlpd', -1910.4, 1452.4, 327.841 )

    set u = CreateUnit( p, 'nlpd', -1662.9, 1592.4, 285.365 )

    set u = CreateUnit( p, 'njga', 6834.2, 5516.9, 201.293 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000077_DropItems )

    set u = CreateUnit( p, 'nsrh', 6652.4, 5661.4, 218.431 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000012_DropItems )

    set u = CreateUnit( p, 'nsrh', 6985.1, 5371.8, 188.775 )

    set u = CreateUnit( p, 'nsc2', 6620.0, 5488.5, 206.558 )

    set u = CreateUnit( p, 'nsc2', 6776.5, 5336.6, 188.516 )

    set u = CreateUnit( p, 'nscb', 3512.3, -1547.2, 342.289 )

    call SetUnitAcquireRange( u, 200.0 )

    set u = CreateUnit( p, 'nscb', 3639.6, -1643.6, 330.885 )

    call SetUnitAcquireRange( u, 200.0 )

    set u = CreateUnit( p, 'nscb', 3488.3, -1726.1, 194.212 )

    call SetUnitAcquireRange( u, 200.0 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000071_DropItems )

    set u = CreateUnit( p, 'nsrv', 2038.8, -3620.5, 309.412 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000022_DropItems )

    set u = CreateUnit( p, 'nlpd', 2204.1, -3677.4, 294.335 )

    set u = CreateUnit( p, 'nlpd', 2052.1, -3791.7, 325.178 )

    set u = CreateUnit( p, 'ntrv', 1911.4, -3738.2, 329.280 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000010_DropItems )

    set u = CreateUnit( p, 'ntrv', 2191.8, -3533.6, 288.728 )

    set u = CreateUnit( p, 'nsrh', 7506.6, 2808.1, 147.810 )

    call SetUnitState( u, UNIT_STATE_MANA, 0 )

    call SetUnitAcquireRange( u, 200.0 )

    set u = CreateUnit( p, 'nsoc', 7389.4, 2654.9, 131.320 )

    call SetUnitState( u, UNIT_STATE_MANA, 0 )

    call SetUnitAcquireRange( u, 200.0 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000185_DropItems )

    set u = CreateUnit( p, 'nsko', 7196.0, 2781.8, 123.606 )

    call SetUnitAcquireRange( u, 200.0 )

    set u = CreateUnit( p, 'nsko', 7253.3, -3252.9, 255.245 )

    call SetUnitAcquireRange( u, 200.0 )

    set u = CreateUnit( p, 'nsko', 7504.5, -3391.0, 226.239 )

    call SetUnitAcquireRange( u, 200.0 )

    set u = CreateUnit( p, 'nsoc', 7383.7, -3213.5, 245.010 )

    call SetUnitState( u, UNIT_STATE_MANA, 0 )

    call SetUnitAcquireRange( u, 200.0 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000030_DropItems )

    set u = CreateUnit( p, 'nsrh', 7594.5, -3154.4, 233.217 )

    call SetUnitState( u, UNIT_STATE_MANA, 0 )

    call SetUnitAcquireRange( u, 200.0 )

    set u = CreateUnit( p, 'nsrh', 7288.8, -3055.3, 256.436 )

    call SetUnitState( u, UNIT_STATE_MANA, 0 )

    call SetUnitAcquireRange( u, 200.0 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000015_DropItems )

    set u = CreateUnit( p, 'ntrs', 8174.2, -8915.7, 133.616 )

    set u = CreateUnit( p, 'ntrs', 8358.1, -8726.1, 171.890 )

    set u = CreateUnit( p, 'nlpd', 1606.7, -1587.8, 150.355 )

    set u = CreateUnit( p, 'nlpd', 1433.5, -1804.0, 123.853 )

    set u = CreateUnit( p, 'nlkl', 1701.1, -1877.8, 136.260 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000014_DropItems )

    set u = CreateUnit( p, 'nsko', 7330.2, 2872.6, 143.154 )

    call SetUnitAcquireRange( u, 200.0 )

    set u = CreateUnit( p, 'nscb', 4188.6, 4168.1, 23.206 )

    call SetUnitAcquireRange( u, 200.0 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000188_DropItems )

    set u = CreateUnit( p, 'nscb', 4267.1, 4027.6, 253.695 )

    call SetUnitAcquireRange( u, 200.0 )

    set u = CreateUnit( p, 'nscb', 4077.2, 4081.4, 140.210 )

    call SetUnitAcquireRange( u, 200.0 )

    set u = CreateUnit( p, 'nsrv', 1945.6, 3106.9, 49.158 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000192_DropItems )

    set u = CreateUnit( p, 'nlpd', 2058.5, 3214.0, 52.059 )

    set u = CreateUnit( p, 'nlpd', 1894.7, 3296.4, 24.030 )

    set u = CreateUnit( p, 'ntrv', 2044.5, 2989.6, 66.651 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000103_DropItems )

    set u = CreateUnit( p, 'ntrv', 1795.2, 3150.6, 33.899 )

    set u = CreateUnit( p, 'nscb', 3105.0, 1770.8, 194.212 )

    call SetUnitAcquireRange( u, 200.0 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000058_DropItems )

    set u = CreateUnit( p, 'nscb', 3313.7, 1622.9, 342.289 )

    call SetUnitAcquireRange( u, 200.0 )

    set u = CreateUnit( p, 'nscb', 3330.2, 1807.3, 330.885 )

    call SetUnitAcquireRange( u, 200.0 )

    set u = CreateUnit( p, 'nlpd', 1661.6, 1640.6, 244.659 )

    set u = CreateUnit( p, 'nlkl', 1909.8, 1732.6, 231.588 )

    set t = CreateTrigger(  )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DEATH )

    call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_CHANGE_OWNER )

    call TriggerAddAction( t, function Unit000024_DropItems )

endfunction



//===========================================================================

function CreateNeutralPassiveBuildings takes nothing returns nothing

    local player p = Player(PLAYER_NEUTRAL_PASSIVE)

    local unit u

    local integer unitID

    local trigger t

    local real life



    set u = CreateUnit( p, 'ngol', 7104.0, -6144.0, 270.000 )

    call SetResourceAmount( u, 12500 )

    set u = CreateUnit( p, 'ngme', 2880.0, -7424.0, 270.000 )

    set u = CreateUnit( p, 'ngad', -7616.0, -2880.0, 270.000 )

    set u = CreateUnit( p, 'ngol', 8640.0, -9152.0, 270.000 )

    call SetResourceAmount( u, 12500 )

    set u = CreateUnit( p, 'ngol', -8704.0, -9088.0, 270.000 )

    call SetResourceAmount( u, 12500 )

    set u = CreateUnit( p, 'ngol', -1856.0, -3392.0, 270.000 )

    call SetResourceAmount( u, 12500 )

    set u = CreateUnit( p, 'ngol', -8512.0, 8512.0, 270.000 )

    call SetResourceAmount( u, 12500 )

    set u = CreateUnit( p, 'nmrc', 7680.0, -192.0, 270.000 )

    call SetUnitColor( u, ConvertPlayerColor(1) )

    set u = CreateUnit( p, 'ngme', -3456.0, 7360.0, 270.000 )

    set u = CreateUnit( p, 'ngme', -3072.0, -7360.0, 270.000 )

    set u = CreateUnit( p, 'ngol', 1856.0, -3392.0, 270.000 )

    call SetResourceAmount( u, 12500 )

    set u = CreateUnit( p, 'ngol', -7040.0, 5696.0, 270.000 )

    call SetResourceAmount( u, 12500 )

    set u = CreateUnit( p, 'ntav', 0.0, 0.0, 270.000 )

    call SetUnitColor( u, ConvertPlayerColor(0) )

    set u = CreateUnit( p, 'nmrc', -7744.0, -192.0, 270.000 )

    call SetUnitColor( u, ConvertPlayerColor(1) )

    set u = CreateUnit( p, 'ngad', -7552.0, 2432.0, 270.000 )

    set u = CreateUnit( p, 'nmrk', 0.0, -8640.0, 270.000 )

    call SetUnitColor( u, ConvertPlayerColor(0) )

    set u = CreateUnit( p, 'ngol', 8704.0, 8448.0, 270.000 )

    call SetResourceAmount( u, 12500 )

    set u = CreateUnit( p, 'ngol', -1792.0, 2880.0, 270.000 )

    call SetResourceAmount( u, 12500 )

    set u = CreateUnit( p, 'ngol', 7040.0, 5696.0, 270.000 )

    call SetResourceAmount( u, 12500 )

    set u = CreateUnit( p, 'ngol', -6976.0, -6144.0, 270.000 )

    call SetResourceAmount( u, 12500 )

    set u = CreateUnit( p, 'ngme', 3456.0, 7296.0, 270.000 )

    set u = CreateUnit( p, 'nmrk', -192.0, 8384.0, 270.000 )

    call SetUnitColor( u, ConvertPlayerColor(0) )

    set u = CreateUnit( p, 'ngad', 7552.0, 2496.0, 270.000 )

    set u = CreateUnit( p, 'ngad', 7488.0, -2944.0, 270.000 )

    set u = CreateUnit( p, 'ngol', 1856.0, 2880.0, 270.000 )

    call SetResourceAmount( u, 12500 )

endfunction



//===========================================================================

function CreateNeutralPassive takes nothing returns nothing

    local player p = Player(PLAYER_NEUTRAL_PASSIVE)

    local unit u

    local integer unitID

    local trigger t

    local real life



    set u = CreateUnit( p, 'nalb', -126.1, -777.5, 78.995 )

    set u = CreateUnit( p, 'nalb', 176.2, -757.9, 105.487 )

    set u = CreateUnit( p, 'nalb', 504.1, -373.3, 153.737 )

    set u = CreateUnit( p, 'nalb', 548.3, 146.0, 206.333 )

    set u = CreateUnit( p, 'nalb', 243.8, 452.7, 247.185 )

    set u = CreateUnit( p, 'nalb', -236.8, 449.6, 292.467 )

    set u = CreateUnit( p, 'nalb', -533.4, 41.8, 342.665 )

    set u = CreateUnit( p, 'nalb', -518.7, -350.8, 23.488 )

    set u = CreateUnit( p, 'ncrb', 3069.4, -2039.2, 210.439 )

    set u = CreateUnit( p, 'ncrb', -722.1, -4365.1, 40.585 )

    set u = CreateUnit( p, 'ncrb', -2972.3, 1903.9, 342.202 )

    set u = CreateUnit( p, 'nhmc', -3569.6, 1494.4, 260.988 )

    set u = CreateUnit( p, 'nhmc', 2894.2, 3146.5, 288.642 )

    set u = CreateUnit( p, 'nhmc', 2666.1, -2534.0, 271.063 )

    set u = CreateUnit( p, 'nhmc', -2994.9, -2658.5, 131.818 )

endfunction



//===========================================================================

function CreatePlayerBuildings takes nothing returns nothing

endfunction



//===========================================================================

function CreatePlayerUnits takes nothing returns nothing

endfunction



//===========================================================================

function CreateAllUnits takes nothing returns nothing

    call CreateNeutralPassiveBuildings(  )

    call CreatePlayerBuildings(  )

    call CreateNeutralHostile(  )

    call CreateNeutralPassive(  )

    call CreatePlayerUnits(  )

endfunction



//***************************************************************************

//*

//*  Custom Script Code

//*

//***************************************************************************

//TESH.scrollpos=0

//TESH.alwaysfold=0



//***************************************************************************

//*

//*  Triggers

//*

//***************************************************************************



//===========================================================================

// Trigger: HCL

//===========================================================================

//TESH.scrollpos=0

//TESH.alwaysfold=0

///////////////////////////////////////////

/// HostBot Command Library

/// Last Modified: September 14, 2009

/// Authors: Strilanc, 

/// v1.01

///////////////////////////////////////////

/// Reads a command string transparently encoded into player handicaps by hostbots.

/// Allows at most one character from "abcdefghijklmnopqrstuvwxyz0123456789 -=,." per player.

/// Empty slots don't count towards the player count, but computers do.

///////////////////////////////////////////

library HCL initializer init

    globals

        private string command = ""

    endglobals

    

    public function GetCommandString takes nothing returns string

        return command

    endfunction

    

    private function init takes nothing returns nothing

        local integer i

        local integer j

        local integer h

        local integer v

        local string chars = "abcdefghijklmnopqrstuvwxyz0123456789 -=,."

        local integer array map

        local boolean array blocked



        //precompute mapping [have to avoid invalid and normal handicaps]

        set blocked[0] = true

        set blocked[50] = true

        set blocked[60] = true

        set blocked[70] = true

        set blocked[80] = true

        set blocked[90] = true

        set blocked[100] = true

        set i = 0

        set j = 0

        loop

            if blocked[j] then

                set j = j + 1

            endif

            exitwhen j >= 256

            set map[j] = i

            set i = i + 1

            set j = j + 1

        endloop

        

        //Extract command string from player handicaps

        set i = 0

        loop

            exitwhen i >= 12

            set h = R2I(100*GetPlayerHandicap(Player(i)) + 0.5)

            if not blocked[h] then

                set h = map[h]

                set v = h/6

                set h = h-v*6

                call SetPlayerHandicap(Player(i), 0.5 + h/10.0)

                set command = command + SubString(chars, v, v+1)

            endif

            set i = i + 1

        endloop

    endfunction

endlibrary//===========================================================================

// Trigger: ARGB

//===========================================================================

//TESH.scrollpos=0

//TESH.alwaysfold=0

library ARGB initializer init

//******************************************************************************

//*

//* ARGB 1.2

//* ====

//*  For your color needs.

//*  

//*  An ARGB object is a by-value struct, this means that assigning copies the

//* contents of the struct and that you don't have to use .destroy(), the

//* downside is that you cannot assign its members (can't do set c.r= 123 )

//*

//*  This library should have plenty of uses, for example, if your spell involves

//* some unit recoloring you can allow users to input the color in the config

//* section as 0xAARRGGBB and you can then use this to decode that stuff.

//*

//* You can also easily merge two colors and make fading effects using ARGB.mix

//*

//* There's ARGB.fromPlayer which gets an ARGB object containing the player's

//* color. Then you can use the previous utilities on it.

//*

//* The .str() instance method can recolor a string, and the recolorUnit method

//* will apply the ARGB on a unit

//*

//* For other uses, you can use the .red, .green, .blue and .alpha members to get

//* an ARGB object's color value (from 0 to 255).

//*

//* structs that have a recolor method that takes red,green,blue and alpha as 0.255

//* integers can implement the ARGBrecolor module to gain an ability to quickly

//* recolor using an ARGB object.

//*

//********************************************************************************



//=================================================================================

globals

    private string array i2cc

endglobals



//this double naming stuff is beginning to make me insane, if only TriggerEvaluate() wasn't so slow...

struct ARGB extends array

    static method create takes integer a, integer r, integer g, integer b returns ARGB

        return ARGB(b + g*0x100 + r*0x10000 + a*0x1000000)

    endmethod

    

    // not really part of the exported stuff, I may remove it in the future, so please don't call this textmacro

    //! textmacro ARGB_PLAYER_COLOR_2_ARGB

        if(pc==PLAYER_COLOR_RED) then

            return 0xFFFF0303

        elseif(pc==PLAYER_COLOR_BLUE) then

            return 0xFF0042FF

        elseif(pc==PLAYER_COLOR_CYAN) then

            return 0xFF1CE6B9

        elseif(pc==PLAYER_COLOR_PURPLE) then

            return 0xFF540081

        elseif(pc==PLAYER_COLOR_YELLOW) then

            return 0xFFFFFC01

        elseif(pc==PLAYER_COLOR_ORANGE) then

            return 0xFFFE8A0E

        elseif(pc==PLAYER_COLOR_GREEN) then

            return 0xFF20C000

        elseif(pc==PLAYER_COLOR_PINK) then

            return 0xFFE55BB0

        elseif(pc==PLAYER_COLOR_LIGHT_GRAY) then

            return 0xFF959697

        elseif(pc==PLAYER_COLOR_LIGHT_BLUE) then

            return 0xFF7EBFF1

        elseif(pc==PLAYER_COLOR_AQUA) then

            return 0xFF106246

        elseif(pc==PLAYER_COLOR_BROWN) then

            return 0xFF4E2A04

        endif

        

      return 0xFF111111

    //! endtextmacro

    static method fromPlayerColor takes playercolor pc returns ARGB

        //! runtextmacro ARGB_PLAYER_COLOR_2_ARGB()

    endmethod



    static method fromPlayer takes player p returns ARGB

     local playercolor pc=GetPlayerColor(p)

        //! runtextmacro ARGB_PLAYER_COLOR_2_ARGB()

    endmethod



    method operator alpha takes nothing returns integer

        if( integer(this) <0) then

            return 0x80+(-(-integer(this)+0x80000000))/0x1000000

        else

            return (integer(this))/0x1000000

        endif

    endmethod

    method operator alpha= takes integer na returns ARGB

     local integer a

     local integer r

     local integer g

     local integer b

     local integer col=integer(this)



       if (col<0) then

           set col=-(-col+0x80000000)

           set a=0x80+col/0x1000000

           set col=col-(a-0x80)*0x1000000

       else

           set a=col/0x1000000

           set col=col-a*0x1000000

       endif

       set r=col/0x10000

       set col=col-r*0x10000

       set g=col/0x100

       set b=col-g*0x100

       return ARGB(b + g*0x100 + r*0x10000 + na*0x1000000) 

    endmethod









    method operator red takes nothing returns integer

     local integer c=integer(this)*0x100

        if(c<0) then

            return 0x80+(-(-c+0x80000000))/0x1000000

        else

            return c/0x1000000

        endif

    endmethod

    method operator red= takes integer nr returns ARGB

     local integer a

     local integer r

     local integer g

     local integer b

     local integer col=integer(this)



       if (col<0) then

           set col=-(-col+0x80000000)

           set a=0x80+col/0x1000000

           set col=col-(a-0x80)*0x1000000

       else

           set a=col/0x1000000

           set col=col-a*0x1000000

       endif

       set r=col/0x10000

       set col=col-r*0x10000

       set g=col/0x100

       set b=col-g*0x100

       return ARGB(b + g*0x100 + nr*0x10000 + a*0x1000000) 

    endmethod



    method operator green takes nothing returns integer

     local integer c=integer(this)*0x10000

        if(c<0) then

            return 0x80+(-(-c+0x80000000))/0x1000000

        else

            return c/0x1000000

        endif

    endmethod

    method operator green= takes integer ng returns ARGB

     local integer a

     local integer r

     local integer g

     local integer b

     local integer col=integer(this)



       if (col<0) then

           set col=-(-col+0x80000000)

           set a=0x80+col/0x1000000

           set col=col-(a-0x80)*0x1000000

       else

           set a=col/0x1000000

           set col=col-a*0x1000000

       endif

       set r=col/0x10000

       set col=col-r*0x10000

       set g=col/0x100

       set b=col-g*0x100

       return ARGB(b + ng*0x100 + r*0x10000 + a*0x1000000) 

    endmethod



    //=======================================================

    //

    //

    method operator blue takes nothing returns integer

     local integer c=integer(this)*0x1000000

        if(c<0) then

            return 0x80+(-(-c+0x80000000))/0x1000000

        else

            return c/0x1000000

        endif

    endmethod

    method operator blue= takes integer nb returns ARGB

     local integer a

     local integer r

     local integer g

     local integer b

     local integer col=integer(this)



       if (col<0) then

           set col=-(-col+0x80000000)

           set a=0x80+col/0x1000000

           set col=col-(a-0x80)*0x1000000

       else

           set a=col/0x1000000

           set col=col-a*0x1000000

       endif

       set r=col/0x10000

       set col=col-r*0x10000

       set g=col/0x100

       set b=col-g*0x100

       return ARGB(nb + g*0x100 + r*0x10000 + a*0x1000000) 

    endmethod



    //====================================================================

    // Mixes two colors, s would be a number 0<=s<=1 that determines

    // the weight given to color c2.

    //

    //  mix(c1,c2,0)   = c1

    //  mix(c1,c2,1)   = c2

    //  mix(c1,c2,0.5) = Mixing the colors c1 and c2 in equal proportions.

    //

    static method mix takes ARGB c1, ARGB c2, real s returns ARGB

      //widest function ever

      return ARGB( R2I(c2.blue*s+c1.blue*(1-s)+0.5) + R2I(c2.green*s+c1.green*(1-s)+0.5)*0x100 + R2I(c2.red*s+c1.red*(1-s)+0.5)*0x10000 + R2I(c2.alpha*s+c1.alpha*(1-s)+0.5)*0x1000000)

    endmethod



    method str takes string s returns string

       return "|c"+i2cc[.alpha]+i2cc[.red]+i2cc[.green]+i2cc[.blue]+s+"|r"

    endmethod



    method recolorUnit takes unit u returns nothing

     local integer a

     local integer r

     local integer g

     local integer b

     local integer col=integer(this)



       if (col<0) then

           set col=-(-col+0x80000000)

           set a=0x80+col/0x1000000

           set col=col-(a-0x80)*0x1000000

       else

           set a=col/0x1000000

           set col=col-a*0x1000000

       endif

       set r=col/0x10000

       set col=col-r*0x10000

       set g=col/0x100

       set b=col-g*0x100

       call SetUnitVertexColor(u,r,g,b,a)

    endmethod



endstruct



module ARGBrecolor

    method ARGBrecolor takes ARGB color returns nothing

     local integer a

     local integer r

     local integer g

     local integer b

     local integer col=integer(this)



       if (col<0) then

           set col=-(-col+0x80000000)

           set a=0x80+col/0x1000000

           set col=col-(a-0x80)*0x1000000

       else

           set a=col/0x1000000

           set col=col-a*0x1000000

       endif

       set r=col/0x10000

       set col=col-r*0x10000

       set g=col/0x100

       set b=col-g*0x100

       

       call this.recolor(r, g , b, a)

    endmethod



endmodule



private function init takes nothing returns nothing

 local integer i=0



    // Don't run textmacros you don't own!

    //! textmacro ARGB_CHAR takes int, chr

        set i=0

        loop

            exitwhen i==16

            set i2cc[$int$*16+i]="$chr$"+i2cc[$int$*16+i]

            set i2cc[i*16+$int$]=i2cc[i*16+$int$]+"$chr$"

            set i=i+1

        endloop

    //! endtextmacro

    //! runtextmacro ARGB_CHAR( "0","0")

    //! runtextmacro ARGB_CHAR( "1","1")

    //! runtextmacro ARGB_CHAR( "2","2")

    //! runtextmacro ARGB_CHAR( "3","3")

    //! runtextmacro ARGB_CHAR( "4","4")

    //! runtextmacro ARGB_CHAR( "5","5")

    //! runtextmacro ARGB_CHAR( "6","6")

    //! runtextmacro ARGB_CHAR( "7","7")

    //! runtextmacro ARGB_CHAR( "8","8")

    //! runtextmacro ARGB_CHAR( "9","9")

    //! runtextmacro ARGB_CHAR("10","A")

    //! runtextmacro ARGB_CHAR("11","B")

    //! runtextmacro ARGB_CHAR("12","C")

    //! runtextmacro ARGB_CHAR("13","D")

    //! runtextmacro ARGB_CHAR("14","E")

    //! runtextmacro ARGB_CHAR("15","F")

endfunction



endlibrary//===========================================================================

// Trigger: Board

//===========================================================================

//TESH.scrollpos=0

//TESH.alwaysfold=0

library Board requires ARGB

//==============================================================================

// Board v0.2.01

//==============================================================================

// Credits:

//------------------------------------------------------------------------------

// Written By:

//     Earth-Fury

//------------------------------------------------------------------------------

// I don't care if you credit me or not if you use this. However, you must not

// misrepresent the source of this library in any way. This includes, but is not

// limited to claiming yourself to be the sole contributor to a map which uses

// this library.

// 

//==============================================================================

// Introduction:

//------------------------------------------------------------------------------

// Board is a library which provides decorators for multiboards. Basically, the

// Board library gives you multiboards with a more manageable API. You can not

// mix usage of the Board class and usage of the multiboard natives. You can

// have multiboards which in no way use the Board library, as well as ones that

// do.

// 

// Board does not impose limits on the number of boards, columns, rows, or

// items within boards. You can create an arbitrary number of boards with an

// arbitrary number of rows and columns, without running in to problems with

// the array size limit.

// 

//==============================================================================

// API Guide

//------------------------------------------------------------------------------

// The API for this library is very big. However, most of the methods do the

// exact same thing as their native counterparts. As well, methods which share

// the same name do the same thing, with some minor differences.

// 

//------------------------------------------------------------------------------

// An Important Note:

// 

// All of the array access methods (That is, the [] methods) which return a

// BoardRow, BoardColumn, or BoardItem, will accept values greater than the size

// of the Board. They will resize the board so that it contains the requested

// item.

// 

// Note that if you have a BoardItem, BoardRow, or BoardColumn object, and

// destroy the board they point to, weird things can happen if you use them. So

// please try to make sure you don't use BoardItem/Row/Column objects if the

// Board they belong to has been destroyed.

//

// The values of BoardRow, BoardColumn, and BoardItem instances can and will go

// above 8190. They are not suitable for use as array indexes. Instances of the

// Board struct itself are suitable for that use.

// 

//------------------------------------------------------------------------------

// The Board struct:

// 

// local Board board = Board.create()

//     When created, a Board object will have 0 columns and 0 rows. It will have

//     no title. The default settings for items are set such that new items will

//     display only text, not icons, and will have a width of 0.

// 

// set board.title = "string"

//     Sets the title of the multiboard. Identical to the native.

// 

// set board.titleColor = 0xFFFF00

//     Sets the color of the title of the multiboard to the given ARGB color.

// 

// 

// set board.visible = true

//     Makes the board visible for all players if set to true, and hidden for all

//     players if set to false.

// 

// set board.visible[Player(0)] = false

//     Makes the board visible/hidden for the given player

// 

// local boolean b = board.visible[Player(0)]

//     Returns true if the board is visible for the given player; false otherwise.

// 

// 

// set board.minimized = true

//     Minimizes/restores the board for all players.

//

// set board.minimized[Player(0)] = false

//     Minimizes/restores the board for the given player only.

// 

// 

// call board.clear()

//     Removes all items from the board. The same as the native.

// 

// 

// local BoardItem it = board[x][y]

//     Returns the BoardItem located in column x, row y.

// 

// 

// local BoardColumn col = board.col[x]

//     Returns the BoardColumn object for the given column of the board.

// 

// set board.col.count = 10

//     Resizes the board such that it has the given number of columns.

// 

// local integer i = board.col.count

//     Returns the number of columns a board currently has.

// 

// 

// local BoardRow row = board.row[y]

//     Returns the BoardRow object for the given row of the board.

// 

// set board.row.count = 10

//     Resizes the board such that it has the given number of rows.

// 

// local integer i = board.row.count

//     Returns the number of rows a board currently has.

// 

// board.all

//     Using board.all, you can modify the item properties of all items at once,

//     as well as change the default properties for items in new rows and

//     columns. Example:

//     

//     set board.all.width = 0.03

//     

//     See the "Item Manipulation" section for information on the methods that

//     board.all has.

//------------------------------------------------------------------------------

// Item Manipulation:

// 

// This section details the methods which all structs this library provides has.

// Namely, the methods that modify the properties of board items.

// 

// When these methods are called from a row, they modify all of the items in

// that row of the board.

// 

// The same for columns.

// 

// When called on BoardItems, they only modify the given item.

// 

// When called from board.all, they modify all the items on the board, and

// change the default properties for newly added items. (Items are added by the

// board gaining rows and columns.)

// 

// Explanation of the methods follows:

// 

// local BoardItem it = board[0][0]

// 

// set it.text = "string"

//      Changes the displayed text for the given item/row/etc.

// 

// set it.color = 0xFFFFFF

//      Changes the colour of the displayed text.

// 

// set it.icon = "ReplaceableTextures\\..."

//      Changes the icon of the item/row/etc.

// 

// set it.width = 0.04

//      Changes the width of the item/row/etc. These width values are the same

//      as those used by native multiboards.

// 

// call it.setDisplay(shouldDisplayText, shouldDisplayIcon)

//      The same as the MultiboardSetItemStyle() native. The first parameter

//      determines if the text for the item/row/etc. will be displayed.

//      The second parameter determines if the icon will be displayed.

//

//------------------------------------------------------------------------------

// The BoardRow and BoardColumn structs:

// 

// Note that these both have the exact same methods. The difference is, of

// course, one represents a row of items in a Board, while the other represents

// a column of items. BoardRow is used below, but it is fully interchangeable.

// 

// local BoardRow row = board.row[10]

// 

// local BoardItem it = row[y]

//      Returns the BoardItem that is in the row, at column y. For a BoardColumn

//      object, it takes the row as it's parameter instead of the column.

// 

// local integer whatRow = row.position

//      Returns the row or columns position in the board. That is to say:

//      board.row[10].position is equal to 10.

// 

// The BoardRow and BoardColumn structs have all of the methods listed in the

// "Item Manipulation" section.

// 

//------------------------------------------------------------------------------

// The BoardItem struct:

// 

// local BoardItem it = board[0][1]

// 

// local integer itemsColumn = it.x

//      Returns the item's x position in the board. (The ID of the column the

//      item is in.)

// 

// local integer itemsRow = it.y

//      The same as it.x, but it returns the row.

// 

// The BoardItem struct has all of the methods listed in the "Item Manipulation"

// section of this API guide.

//

//==============================================================================

// There is nothing to configure.

//==============================================================================



// Hopefully this will be inlined one day...

private constant function Mod takes integer dividend, integer divisor returns integer

    return dividend - (dividend / divisor) * divisor

endfunction



private constant function B2S takes boolean b returns string

    if b then

        return "true"

    endif

    return "false"

endfunction



private function ErrorMsg takes string what, string error returns nothing

    call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "Board Error: " + what + ": " + error)

endfunction



// ============================================================

// Private keywords

// ============================================================



private keyword bBoard

private keyword bColCount

private keyword bRowCount

private keyword bTemp

private keyword bVisibleFor



// ============================================================

// Item Struct

// ============================================================



struct BoardItem extends array

    // =====

    // Notes:

    // -----

    // this  = board * 10000 + row * 100 + col

    // 

    // k     = Mod(integer(this), 10000)

    //

    // row   = (k - Mod(k, 100)) / 100

    // col   = Mod(k, 100)

    // board = (integer(this) - k) / 10000

    //

    // row   = (Mod(integer(this), 10000) - Mod(Mod(integer(this), 10000), 100)) / 100

    // col   = Mod(Mod(integer(this), 10000), 100)

    // board = (integer(this) - Mod(integer(this), 10000)) / 10000

    // =====

    

    public method operator x takes nothing returns integer

        return Mod(Mod(integer(this), 10000), 100)

    endmethod

    

    public method operator y takes nothing returns integer

        return (Mod(integer(this), 10000) - Mod(Mod(integer(this), 10000), 100)) / 100

    endmethod

    

    // ==============

    

    public method operator text= takes string val returns nothing

        local integer k = Mod(integer(this), 10000)

        local Board board = Board((integer(this) - k) / 10000)

        local integer row = (k - Mod(k, 100)) / 100

        local integer col = Mod(k, 100)

        local multiboarditem mbi

        

        if board.bBoard == null then

            debug call ErrorMsg("BoardItem[" + I2S(col) + "][" + I2S(row) + "].text=", "The board this item belongs to does not exist anymore")

            return

        endif

        

        if row >= board.bRowCount then

            debug call ErrorMsg("BoardItem.text=", "The board has been shrunk to no longer include this item. Will resize the board.")

            call MultiboardSetRowCount(board.bBoard, row + 1)

            set board.bRowCount = row + 1

        endif

        if col >= board.bColCount then

            debug call ErrorMsg("BoardItem.text=", "The board has been shrunk to no longer include this item. Will resize the board.")

            call MultiboardSetColumnCount(board.bBoard, col + 1)

            set board.bColCount = col + 1

        endif

        

        set mbi =  MultiboardGetItem(board.bBoard, row, col)

        

        call MultiboardSetItemValue(mbi, val)

        

        call MultiboardReleaseItem(mbi)

        

        set mbi = null

    endmethod

    

    public method operator icon= takes string val returns nothing

        local integer k = Mod(integer(this), 10000)

        local Board board = Board((integer(this) - k) / 10000)

        local integer row = (k - Mod(k, 100)) / 100

        local integer col = Mod(k, 100)

        local multiboarditem mbi

        

        if board.bBoard == null then

            debug call ErrorMsg("BoardItem[" + I2S(col) + "][" + I2S(row) + "].icon=", "The board this item belongs to does not exist anymore")

            return

        endif

        

        if row >= board.bRowCount then

            debug call ErrorMsg("BoardItem.icon=", "The board has been shrunk to no longer include this item. Will resize the board.")

            call MultiboardSetRowCount(board.bBoard, row + 1)

            set board.bRowCount = row + 1

        endif

        if col >= board.bColCount then

            debug call ErrorMsg("BoardItem.icon=", "The board has been shrunk to no longer include this item. Will resize the board.")

            call MultiboardSetColumnCount(board.bBoard, col + 1)

            set board.bColCount = col + 1

        endif

        

        set mbi =  MultiboardGetItem(board.bBoard, row, col)

        

        call MultiboardSetItemIcon(mbi, val)

        

        call MultiboardReleaseItem(mbi)

        

        set mbi = null

    endmethod

    

    public method operator color= takes ARGB c returns nothing

        local integer k = Mod(integer(this), 10000)

        local Board board = Board((integer(this) - k) / 10000)

        local integer row = (k - Mod(k, 100)) / 100

        local integer col = Mod(k, 100)

        local multiboarditem mbi

        

        if board.bBoard == null then

            debug call ErrorMsg("BoardItem[" + I2S(col) + "][" + I2S(row) + "].color=", "The board this item belongs to does not exist anymore")

            return

        endif

        

        if row >= board.bRowCount then

            debug call ErrorMsg("BoardItem.color=", "The board has been shrunk to no longer include this item. Will resize the board.")

            call MultiboardSetRowCount(board.bBoard, row + 1)

            set board.bRowCount = row + 1

        endif

        if col >= board.bColCount then

            debug call ErrorMsg("BoardItem.color=", "The board has been shrunk to no longer include this item. Will resize the board.")

            call MultiboardSetColumnCount(board.bBoard, col + 1)

            set board.bColCount = col + 1

        endif

        

        set mbi =  MultiboardGetItem(board.bBoard, row, col)

        

        call MultiboardSetItemValueColor(mbi, c.red, c.green, c.blue, c.alpha)

        

        call MultiboardReleaseItem(mbi)

        

        set mbi = null

    endmethod

    

    public method operator width= takes real r returns nothing

        local integer k = Mod(integer(this), 10000)

        local Board board = Board((integer(this) - k) / 10000)

        local integer row = (k - Mod(k, 100)) / 100

        local integer col = Mod(k, 100)

        local multiboarditem mbi

        

        if board.bBoard == null then

            debug call ErrorMsg("BoardItem[" + I2S(col) + "][" + I2S(row) + "].width=", "The board this item belongs to does not exist anymore")

            return

        endif

        

        if row >= board.bRowCount then

            debug call ErrorMsg("BoardItem.width=", "The board has been shrunk to no longer include this item. Will resize the board.")

            call MultiboardSetRowCount(board.bBoard, row + 1)

            set board.bRowCount = row + 1

        endif

        if col >= board.bColCount then

            debug call ErrorMsg("BoardItem.width=", "The board has been shrunk to no longer include this item. Will resize the board.")

            call MultiboardSetColumnCount(board.bBoard, col + 1)

            set board.bColCount = col + 1

        endif

        

        set mbi =  MultiboardGetItem(board.bBoard, row, col)

        

        call MultiboardSetItemWidth(mbi, r)

        

        call MultiboardReleaseItem(mbi)

        

        set mbi = null

    endmethod

    

    public method setDisplay takes boolean text, boolean icon returns nothing

        local integer k = Mod(integer(this), 10000)

        local Board board = Board((integer(this) - k) / 10000)

        local integer row = (k - Mod(k, 100)) / 100

        local integer col = Mod(k, 100)

        local multiboarditem mbi

        

        if board.bBoard == null then

            debug call ErrorMsg("BoardItem[" + I2S(col) + "][" + I2S(row) + "].setDisplay()", "The board this item belongs to does not exist anymore")

            return

        endif

        

        if row >= board.bRowCount then

            debug call ErrorMsg("BoardItem.setDisplay()", "The board has been shrunk to no longer include this item. Will resize the board.")

            call MultiboardSetRowCount(board.bBoard, row + 1)

            set board.bRowCount = row + 1

        endif

        if col >= board.bColCount then

            debug call ErrorMsg("BoardItem.setDisplay()", "The board has been shrunk to no longer include this item. Will resize the board.")

            call MultiboardSetColumnCount(board.bBoard, col + 1)

            set board.bColCount = col + 1

        endif

        

        set mbi =  MultiboardGetItem(board.bBoard, row, col)

        

        call MultiboardSetItemStyle(mbi, text, icon)

        

        call MultiboardReleaseItem(mbi)

        

        set mbi = null

    endmethod

endstruct



// ============================================================

// BoardRow and BoardColumn structs

// ============================================================



//! textmacro Board_DeclareRowCol takes I, K, NAME, COUNT_FUNC, OTHER, THIS

struct Board$NAME$ extends array

    // =====

    // Notes:

    // -----

    // this  = board * 100 + pos

    // pos   = Mod(integer(this), 100)

    // board = (integer(this) - Mod(integer(this), 100)) / 100

    // =====

    

    public method operator [] takes integer $K$ returns BoardItem

        local Board board = ((integer(this) - Mod(integer(this), 100)) / 100)

        local integer $I$ = Mod(integer(this), 100)

        

        if $K$ >= board.b$OTHER$Count then

            call MultiboardSet$COUNT_FUNC$Count(board.bBoard, $K$ + 1)

            set board.b$OTHER$Count = $K$ + 1

        endif

        

        return BoardItem(integer(board) * 10000 + $I$ * 100 + $K$)

    endmethod

    

    public method operator position takes nothing returns integer

        return Mod(integer(this), 100)

    endmethod

    

    // ==============

    

    public method operator text= takes string val returns nothing

        local Board board = Board((integer(this) - Mod(integer(this), 100)) / 100)

        local integer $I$ = thistype(Mod(integer(this), 100))

        

        local multiboarditem mbi

        local integer $K$ = 0

        

        if board.bBoard == null then

            debug call ErrorMsg("Board$NAME$[" + I2S(col) + "][" + I2S(row) + "].text=", "The board this $I$ belongs to does not exist anymore")

            return

        endif

        

        if $I$ >= board.b$THIS$Count then

            debug call ErrorMsg("Board$NAME$.text=", "The board has been shrunk to no longer include this $I$. Will resize the board.")

            call MultiboardSetRowCount(board.bBoard, $I$ + 1)

            set board.b$THIS$Count = $I$ + 1

        endif

        

        loop

            exitwhen $K$ == board.b$OTHER$Count

            set mbi = MultiboardGetItem(board.bBoard, row, col)

            

            call MultiboardSetItemValue(mbi, val)

            

            call MultiboardReleaseItem(mbi)

            set $K$ = $K$ + 1

        endloop

        

        set mbi = null

    endmethod

    

    public method operator icon= takes string val returns nothing

        local Board board = Board((integer(this) - Mod(integer(this), 100)) / 100)

        local integer $I$ = thistype(Mod(integer(this), 100))

        

        local multiboarditem mbi

        local integer $K$ = 0

        

        if board.bBoard == null then

            debug call ErrorMsg("Board$NAME$[" + I2S(col) + "][" + I2S(row) + "].icon=", "The board this $I$ belongs to does not exist anymore")

            return

        endif

        

        if $I$ >= board.b$THIS$Count then

            debug call ErrorMsg("Board$NAME$.icon=", "The board has been shrunk to no longer include this $I$. Will resize the board.")

            call MultiboardSetRowCount(board.bBoard, $I$ + 1)

            set board.b$THIS$Count = $I$ + 1

        endif

        

        loop

            exitwhen $K$ == board.b$OTHER$Count

            set mbi = MultiboardGetItem(board.bBoard, row, col)

            

            call MultiboardSetItemIcon(mbi, val)

            

            call MultiboardReleaseItem(mbi)

            set $K$ = $K$ + 1

        endloop

        

        set mbi = null

    endmethod

    

    public method operator color= takes ARGB c returns nothing

        local Board board = Board((integer(this) - Mod(integer(this), 100)) / 100)

        local integer $I$ = thistype(Mod(integer(this), 100))

        

        local multiboarditem mbi

        local integer $K$ = 0

        

        if board.bBoard == null then

            debug call ErrorMsg("Board$NAME$[" + I2S(col) + "][" + I2S(row) + "].color=", "The board this $I$ belongs to does not exist anymore")

            return

        endif

        

        if $I$ >= board.b$THIS$Count then

            debug call ErrorMsg("Board$NAME$.color=", "The board has been shrunk to no longer include this $I$. Will resize the board.")

            call MultiboardSetRowCount(board.bBoard, $I$ + 1)

            set board.b$THIS$Count = $I$ + 1

        endif

        

        loop

            exitwhen $K$ >= board.b$OTHER$Count

            set mbi = MultiboardGetItem(board.bBoard, row, col)

            

            call MultiboardSetItemValueColor(mbi, c.red, c.green, c.blue, c.alpha)

            

            call MultiboardReleaseItem(mbi)

            set $K$ = $K$ + 1

        endloop

        

        set mbi = null

    endmethod

    

    public method operator width= takes real r returns nothing

        local Board board = Board((integer(this) - Mod(integer(this), 100)) / 100)

        local integer $I$ = thistype(Mod(integer(this), 100))

        

        local multiboarditem mbi

        local integer $K$ = 0

        

        if board.bBoard == null then

            debug call ErrorMsg("Board$NAME$[" + I2S(col) + "][" + I2S(row) + "].width=", "The board this $I$ belongs to does not exist anymore")

            return

        endif

        

        if $I$ >= board.b$THIS$Count then

            debug call ErrorMsg("Board$NAME$.width=", "The board has been shrunk to no longer include this $I$. Will resize the board.")

            call MultiboardSetRowCount(board.bBoard, $I$ + 1)

            set board.b$THIS$Count = $I$ + 1

        endif

        

        loop

            exitwhen $K$ == board.b$OTHER$Count

            set mbi = MultiboardGetItem(board.bBoard, row, col)

            

            call MultiboardSetItemWidth(mbi, r)



            call MultiboardReleaseItem(mbi)

            set $K$ = $K$ + 1

        endloop

        

        set mbi = null

    endmethod

    

    public method setDisplay takes boolean text, boolean icon returns nothing

        local Board board = Board((integer(this) - Mod(integer(this), 100)) / 100)

        local integer $I$ = thistype(Mod(integer(this), 100))

        

        local multiboarditem mbi

        local integer $K$ = 0

        

        if board.bBoard == null then

            debug call ErrorMsg("Board$NAME$[" + I2S(col) + "][" + I2S(row) + "].setDisplay()", "The board this $I$ belongs to does not exist anymore")

            return

        endif

        

        if $I$ >= board.b$THIS$Count then

            debug call ErrorMsg("Board$NAME$.setDisplay()", "The board has been shrunk to no longer include this $I$. Will resize the board.")

            call MultiboardSetRowCount(board.bBoard, $I$ + 1)

            set board.b$THIS$Count = $I$ + 1

        endif

        

        loop

            exitwhen $K$ == board.b$OTHER$Count

            set mbi = MultiboardGetItem(board.bBoard, row, col)

            

            call MultiboardSetItemStyle(mbi, text, icon)

            

            call MultiboardReleaseItem(mbi)

            set $K$ = $K$ + 1

        endloop

        

        set mbi = null

    endmethod

endstruct

//! endtextmacro



//! runtextmacro Board_DeclareRowCol("row", "col", "Row",    "Column", "Col", "Row")

//! runtextmacro Board_DeclareRowCol("col", "row", "Column", "Row",    "Row", "Col")



// ============================================================

// Helper Structs (For [][], .col[], .row[], etc)

// ============================================================



private struct ItemHelper extends array

    public method operator[] takes integer row returns BoardItem

        local integer col = Board.bTemp

        

        if row < 0 then

            debug call ErrorMsg("Board[" + I2S(col) + "][" + I2S(row) + "]", "Given row id is less than 0")

            return 0

        elseif col < 0 then

            debug call ErrorMsg("Board[" + I2S(col) + "][" + I2S(row) + "]", "Given col id is less than 0")

            return 0

        endif

        //i = brd * 10000 + row * 100 + col

        

        if col >= Board(this).bColCount then

            call MultiboardSetColumnCount(Board(this).bBoard, col + 1)

            set Board(this).bColCount = col + 1

        endif

        

        if row >= Board(this).bRowCount then

            call MultiboardSetRowCount(Board(this).bBoard, row + 1)

            set Board(this).bRowCount = row + 1

        endif

        

        return integer(this) * 10000 + row * 100 + Board(this).bTemp

    endmethod

endstruct



private struct RowHelper extends array

    public method operator count takes nothing returns integer

        return Board(this).bRowCount

    endmethod

    public method operator count= takes integer i returns nothing

        call MultiboardSetRowCount(Board(this).bBoard, i + 1)

        set Board(this).bRowCount = i + 1

    endmethod

    

    public method operator[] takes integer row returns BoardRow

        if row < 0 then

            debug call ErrorMsg("Board.row[" + I2S(row) + "]", "Given row id is less than 0")

            return 0

        endif

        

        if row >= Board(this).bRowCount then

            call MultiboardSetRowCount(Board(this).bBoard, row + 1)

            set Board(this).bRowCount = row + 1

        endif

        

        if Board(this).bColCount < 1 then

            call MultiboardSetColumnCount(Board(this).bBoard, 1)

            set Board(this).bColCount = 1

        endif

        

        return BoardRow(row + integer(this) * 100)

    endmethod

endstruct



private struct ColumnHelper extends array

    public method operator count takes nothing returns integer

        return Board(this).bColCount

    endmethod

    public method operator count= takes integer i returns nothing

        call MultiboardSetColumnCount(Board(this).bBoard, i + 1)

        set Board(this).bColCount = i + 1

    endmethod

    

    public method operator[] takes integer col returns BoardColumn

        if col < 0 then

            debug call ErrorMsg("Board.col[" + I2S(col) + "]", "Given column id is less than 0")

            return 0

        endif

        

        if col >= Board(this).bColCount then

            call MultiboardSetColumnCount(Board(this).bBoard, col + 1)

            set Board(this).bColCount = col + 1

        endif

        

        if Board(this).bRowCount < 1 then

            call MultiboardSetRowCount(Board(this).bBoard, 1)

            set Board(this).bRowCount = 1

        endif

        

        return BoardColumn(col + integer(this) * 100)

    endmethod

endstruct



private struct VisibleHelper extends array

    public method operator []= takes player p, boolean b returns nothing

        if GetPlayerId(p) > 11 then

            debug call ErrorMsg("Board.visible[\"" + GetPlayerName(p) + "\"]=" + B2S(b), "Given player is a neutral player")

            return

        endif

        

        set Board(this).bVisibleFor[GetPlayerId(p)] = b

        

        if GetLocalPlayer() == p then

            call MultiboardDisplay(Board(this).bBoard, b)

        endif

    endmethod

    public method operator [] takes player p returns boolean

        if GetPlayerId(p) > 11 then

            debug call ErrorMsg("Board.visible[\"" + GetPlayerName(p) + "\"]", "Given player is a neutral player")

            return false

        endif

        

        return Board(this).bVisibleFor[GetPlayerId(p)]

    endmethod

endstruct



private struct MinimizedHelper extends array

    public method operator[]= takes player p, boolean b returns nothing

        if GetPlayerId(p) > 11 then

            debug call ErrorMsg("Board.minimized[\"" + GetPlayerName(p) + "\"]=" + B2S(b), "Given player is a neutral player")

            return

        endif

        

        if GetLocalPlayer() == p then

            call MultiboardMinimize(Board(this).bBoard, b)

        endif

    endmethod

endstruct



private struct AllHelper extends array

    public method operator text= takes string val returns nothing

        call MultiboardSetItemsValue(Board(this).bBoard, val)

    endmethod

    

    public method operator icon= takes string val returns nothing

        call MultiboardSetItemsIcon(Board(this).bBoard, val)

    endmethod

    

    public method operator color= takes ARGB c returns nothing

        call MultiboardSetItemsValueColor(Board(this).bBoard, c.red, c.green, c.blue, c.alpha)

    endmethod

    

    public method operator width= takes real r returns nothing

        call MultiboardSetItemsWidth(Board(this).bBoard, r)

    endmethod

    

    public method setDisplay takes boolean text, boolean icon returns nothing

        call MultiboardSetItemsStyle(Board(this).bBoard, text, icon)

    endmethod

endstruct



// ============================================================

// Board Struct

// ============================================================



struct Board

    multiboard bBoard

    

    integer bColCount = 0

    integer bRowCount = 0

    

    boolean array bVisibleFor[12]

    

    static integer bTemp

    

    public static method create takes nothing returns thistype

        local thistype this = allocate()

        

        set bBoard = CreateMultiboard()

        

        call MultiboardSetItemsWidth(bBoard, 0.01)

        call MultiboardSetItemsStyle(bBoard, true, false)

        

        return this

    endmethod

    

    private method onDestroy takes nothing returns nothing

        call DestroyMultiboard(bBoard)

        set bBoard = null

    endmethod

    

    //==================

    

    public method operator[] takes integer column returns ItemHelper

        set bTemp = column

        return ItemHelper(this)

    endmethod

    

    public method operator col takes nothing returns ColumnHelper

        return ColumnHelper(this)

    endmethod

    

    public method operator row takes nothing returns RowHelper

        return RowHelper(this)

    endmethod

    

    //==================

    

    public method operator all takes nothing returns AllHelper

        return AllHelper(this)

    endmethod

    

    public method operator title= takes string value returns nothing

        call MultiboardSetTitleText(bBoard, value)

    endmethod

    

    public method operator titleColor= takes ARGB color returns nothing

        call MultiboardSetTitleTextColor(bBoard, color.red, color.green, color.blue, color.alpha)

    endmethod

    

    public method operator visible takes nothing returns VisibleHelper

        return VisibleHelper(this)

    endmethod

    public method operator visible= takes boolean b returns nothing

        local integer i = 0

        loop

            exitwhen i == 12

            

            set bVisibleFor[i] = b

            

            set i = i + 1

        endloop

        

        call MultiboardDisplay(bBoard, b)

    endmethod

    

    public method operator minimized takes nothing returns MinimizedHelper

        return MinimizedHelper(this)

    endmethod

    public method operator minimized= takes boolean b returns nothing

        call MultiboardMinimize(bBoard, b)

    endmethod

    

    public method clear takes nothing returns nothing

        call MultiboardClear(bBoard)

    endmethod

endstruct



endlibrary//===========================================================================

// Trigger: Alloc

//===========================================================================

//TESH.scrollpos=107

//TESH.alwaysfold=0

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

//~~ AllocLoop ~~ by moyack ~~ Version 1.0 ~~ Variant version of...

//~~ Alloc ~~ By Sevion ~~ Version 1.09 ~~

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

//

//  What is Alloc?

//         - Alloc implements an intuitive allocation method for array structs

//

//    =Pros=

//         - Efficient.

//         - Simple.

//         - Less overhead than regular structs.

//

//    =Cons=

//         - Must use array structs (hardly a con).

//         - Must manually call OnDestroy.

//         - Must use Delegates for inheritance.

//         - No default values for variables (use onInit instead).

//         - No array members (use another Alloc struct as a linked list or type declaration).

//

//    Methods:

//         - struct.allocate()

//         - struct.deallocate()

//

//           These methods are used just as they should be used in regular structs.

//

//    Modules:

//         - Alloc

//           Implements the most basic form of Alloc. Includes only create and destroy

//           methods.

//

//  Details:

//         - Less overhead than regular structs

//

//         - Use array structs when using Alloc. Put the implement at the top of the struct.

//

//         - Alloc operates almost exactly the same as default structs in debug mode with the exception of onDestroy.

//

//  How to import:

//         - Create a trigger named Alloc.

//         - Convert it to custom text and replace the whole trigger text with this.

//

//  Thanks:

//         - Nestharus for the method of allocation and suggestions on further merging.

//         - Bribe for suggestions like the static if and method names.

//         - PurgeandFire111 for some suggestions like the merging of Alloc and AllocX as well as OnDestroy stuff.

//

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

library Alloc    

    //! textmacro Alloc

        private static integer instanceCount = 0

        private thistype recycle

    

        static method allocate takes nothing returns thistype

            local thistype this

    

            if (thistype(0).recycle == 0) then

                debug if (instanceCount == 8190) then

                    debug call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "Alloc ERROR: Attempted to allocate too many instances!")

                    debug return 0

                debug endif

                set instanceCount = instanceCount + 1

                set this = instanceCount

            else

                set this = thistype(0).recycle

                set thistype(0).recycle = thistype(0).recycle.recycle

            endif



            debug set this.recycle = -1

    

            return this

        endmethod

    

        method deallocate takes nothing returns nothing

            debug if (this.recycle != -1) then

                debug call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "Alloc ERROR: Attempted to deallocate an invalid instance at [" + I2S(this) + "]!")

                debug return

            debug endif



            set this.recycle = thistype(0).recycle

            set thistype(0).recycle = this

        endmethod

    //! endtextmacro

    

    //! textmacro AllocLoop

        private static integer instanceCount = 0

        private thistype recycle

        thistype next

        thistype prev

    

        static method allocate takes nothing returns thistype

            local thistype this

    

            if (thistype(0).recycle == 0) then

                debug if (instanceCount == 8190) then

                    debug call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "Alloc ERROR: Attempted to allocate too many instances!")

                    debug return 0

                debug endif

                set instanceCount = instanceCount + 1

                set this = instanceCount

            else

                set this = thistype(0).recycle

                set thistype(0).recycle = thistype(0).recycle.recycle

            endif



            debug set this.recycle = -1

            

            set thistype(0).next.prev = this // "next" of head has our new instance as "previous"

            set this.next = thistype(0).next // "next" of our node is the "next" of head

            set thistype(0).next = this // "next" of head is now our node

            set this.prev = 0 // "previous" of our node is the head [this case, thistype(0)]

            return this

        endmethod

    

        method deallocate takes nothing returns nothing

            set .next.prev = .prev // set the "prev" of the "next" node to our "prev"

            set .prev.next = .next // set the "next" of the "prev" node to our "next"

            

            debug if (this.recycle != -1) then

                debug call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "Alloc ERROR: Attempted to deallocate an invalid instance at [" + I2S(this) + "]!")

                debug return

            debug endif



            set this.recycle = thistype(0).recycle

            set thistype(0).recycle = this

        endmethod

    //! endtextmacro

    

    module Alloc

        //! runtextmacro Alloc()

    endmodule

    

    module AllocLoop

        //! runtextmacro AllocLoop()

    endmodule

    

    // - This module must be used with "AllocLoop" textmacro

    // - this module must be pacled after a local definition in the code ALWAYS

    // - always use "this" as variable name

    module loop 

        local thistype this = thistype(0).next 

        loop

            exitwhen integer(this) == 0

    endmodule



    // this will end the looping code

    module endloop 

            set this = this.next

        endloop

    endmodule

endlibrary//===========================================================================

// Trigger: Indexor2

//

// requires MicroTable, Alloc

//===========================================================================

//TESH.scrollpos=0

//TESH.alwaysfold=0

library Indexor2 initializer init requires MicroTable, Alloc

// the Alloc requirement is just to keep properly ordered the libraries, actually this library

// does not need Alloc, but the dependant libraries does.

globals

    private constant key A

    private constant integer Max = 5

endglobals



struct Indexor2 extends array

    timer t

    trigger tr

    real period

    integer count

    thistype next

    static integer counter = 1

    private static method evaluate takes nothing returns nothing

        call TriggerEvaluate(thistype(GetData(GetExpiredTimer(), A)).tr)

    endmethod

    

    static method create takes real period returns thistype

        local thistype this = thistype(thistype.counter)

        set thistype.counter = thistype.counter + 1

        set this.t = CreateTimer()

        set this.tr = CreateTrigger()

        set this.period = period

        set this.count = 0

        call StoreData(this.t, A, integer(this))

        call TimerStart(this.t, period, true, function thistype.evaluate)

        return this

    endmethod

    

    method AddCode takes code c returns nothing // this code should return a boolean to keep consistency

        if .count > Max then

            if .next == 0 then

                set .next = thistype.create(.period)

            endif

            call .next.AddCode(c)

        else

            set .count = .count + 1

            call TriggerAddCondition(.tr, Condition(c))

            debug call BJDebugMsg( "Indexor2 index: " + I2S(this) + " events added: " + I2S(.count))

        endif

    endmethod

endstruct



globals // here we'll set the indexor we'll use in the game.

    Indexor2 UnitIndexer // Manages units effects

    Indexor2 HeroIndexer // Manages Heroes effects

    Indexor2 TEIndexer   // Manages Timed Effects

endglobals



private function init takes nothing returns nothing

    set UnitIndexer = Indexor2.create(GetRandomReal(0.060, 0.069))

    set HeroIndexer = Indexor2.create(GetRandomReal(0.060, 0.069))

    set TEIndexer   = Indexor2.create(0.1)

endfunction



endlibrary//===========================================================================

// Trigger: DataPreloader

//

// requires Alloc, DummyCast, MicroTable

//===========================================================================

//TESH.scrollpos=0

//TESH.alwaysfold=0

library DataPreloader requires Alloc, DummyCast, MicroTable



globals

    private constant key A

    private boolean done = false

endglobals



private struct data extends array

    unit u

    unit v

    

    implement Alloc

    

    method destroy takes nothing returns nothing

        set .u = null 

        set .v = null

        call .deallocate()

    endmethod

    

    static method start takes unit u, unit v returns thistype

        local thistype d = thistype.allocate()

        set d.u = u

        set d.v = v

        return d

    endmethod

endstruct



private function End takes nothing returns nothing

    local data d = data(GetData(GetExpiredTimer(), A))

    call RemoveUnit(d.u)

    call RemoveUnit(d.v)

    call d.destroy()

    call DestroyTimer(GetExpiredTimer())

endfunction



private function PreloadReq takes player p returns nothing

    call SetPlayerTechResearched(p, 'Rnsi', 1)// Broodlings

    call SetPlayerTechResearched(p, 'Rnsw', 2)// Naga siren adept training

    call SetPlayerTechResearched(p, 'R002', 2)// murgul wizard adept training

    call SetPlayerTechResearched(p, 'R005', 1)// poisoned skin

    call SetPlayerTechResearched(p, 'R00F', 2)// abyss mage adept training

    call SetPlayerTechResearched(p, 'R00G', 2)// Overlord adept training

    call SetPlayerTechResearched(p, 'R00E', 1)// Land in Flames

    call SetPlayerTechResearched(p, 'R00A', 1)// Treacherous Attack

    call SetPlayerTechResearched(p, 'R009', 1)// Evil Distraction

endfunction



private function Preload2 takes string s returns nothing

    if s != null or s != "" then

        call Preload(s)

    endif

endfunction



function PreloadUnitType takes integer id returns nothing

    call RemoveUnit(CreateUnit(Player(15), id, 0., 0., 0.))

endfunction



function PreloadSimple takes integer AbilId returns boolean

    return UnitAddAbility(DummyCast_GetDummy(), AbilId) and UnitRemoveAbility(DummyCast_GetDummy(), AbilId)

endfunction



function PreloadAbility takes integer id, string order, boolean positive returns nothing

    local unit u

    local unit v

    local integer i = 0

    call UnitAddAbility(DummyCast_GetDummy(), id)

    if order != "" then

        set u = CreateUnit(Player(13), 'Hamg', 0,0,0)

        set v = CreateUnit(Player(14), 'hpea', 0,0,0)

        call SetPlayerAllianceStateAllyBJ(Player(13), Player(14), positive)

        if not done then

            call PreloadReq(Player(13))

            call PreloadReq(Player(14))

            set done = true

        endif

        call UnitAddAbility(u, id)

        call SetUnitState(u, UNIT_STATE_MANA, GetUnitState(u, UNIT_STATE_MAX_MANA))

        if not IssueImmediateOrder(u, order) or not IssueTargetOrder(u, order, v) or not IssuePointOrder(u, order, 0,0) then

            call RemoveUnit(u)

            set u = CreateUnit(Player(13), 'hmpr', 0,0,0)

            call UnitAddAbility(u, id)

            if not IssueImmediateOrder(u, order) or not IssueTargetOrder(u, order, v) or not IssuePointOrder(u, order, 0,0) then

                debug call BJDebugMsg(GetObjectName(id) + "[" + order + "] can't be preloaded...")

                loop

                    exitwhen i > 10

                    call Preload2(GetAbilityEffectById(id, EFFECT_TYPE_AREA_EFFECT, i))

                    call Preload2(GetAbilityEffectById(id, EFFECT_TYPE_CASTER, i))

                    call Preload2(GetAbilityEffectById(id, EFFECT_TYPE_EFFECT, i))

                    call Preload2(GetAbilityEffectById(id, EFFECT_TYPE_MISSILE, i))

                    call Preload2(GetAbilityEffectById(id, EFFECT_TYPE_SPECIAL, i))

                    call Preload2(GetAbilityEffectById(id, EFFECT_TYPE_TARGET, i))

                    set i = i + 1

                endloop

            endif

        endif

        set bj_lastStartedTimer = CreateTimer()

        call StoreData(bj_lastStartedTimer, A, data.start(u, v))

        call TimerStart(bj_lastStartedTimer, 0.2, false, function End)

        set bj_lastStartedTimer = null

    endif

    set u = null

    set v = null

endfunction



endlibrary//===========================================================================

// Trigger: MainGlobals

//===========================================================================

//TESH.scrollpos=0

//TESH.alwaysfold=0

library MainGlobals initializer Init



struct stats extends array

    integer index

    integer buildings

    integer kills 

    integer devpoints

endstruct



globals

	force UserPlayers = CreateForce()

    sound SimErrorSound

    boolexpr True = null

    

    // units rawcodes

    constant integer NagaHallT1 = 'nntt'

    constant integer DemonHallT1 = 'u000'

    constant integer NagaPeon = 'nmpe'

    constant integer DemonPeon = 'u001'

    constant integer NagaShop = 'n000'

	constant integer DemonShop = 'n00D'

    

    // Devotion Points

    constant integer goldPayment = 100 // sets the gold obtained when they trade their DevPoints

    constant integer lumberPayment = 100 // sets the lumber obtained when they trade their DevPoints

    

    // Dummy unit type

    constant integer Dummy = 'n018'

endglobals



private constant function BoolTrue takes nothing returns boolean

    return true

endfunction



function PlayerIsNaga takes player p returns boolean

    local race r = GetPlayerRace(p)

    return r == RACE_HUMAN or r == RACE_NIGHTELF

endfunction



function SimError takes player ForPlayer, string msg returns nothing

    if GetLocalPlayer() == ForPlayer and GetPlayerController(ForPlayer) == MAP_CONTROL_USER then

        call ClearTextMessages()

        call DisplayTimedTextToPlayer( ForPlayer, 0.52, -1.00, 2.00, "|cffffcc00"+msg+"|r" )

        call StartSound( SimErrorSound )

    endif

    set msg = null

endfunction



function GetShop takes player p returns integer

    local race r = GetPlayerRace(p)

    local integer i

    if r == RACE_HUMAN or r == RACE_NIGHTELF then

        set i = NagaShop

    else

        set i = DemonShop

    endif

    set r = null

    return i

endfunction



function IsUnitTransport takes unit u returns boolean

    return GetUnitTypeId(u) == 'n00J' or GetUnitTypeId(u) == 'n00I' or GetUnitTypeId(u) == 'nzep' or GetUnitTypeId(u) == 'nbot'

endfunction



private function Init takes nothing returns nothing

    set True = Condition(function BoolTrue) 

    set SimErrorSound = CreateSoundFromLabel( "InterfaceError",false,false,false,10,10)

endfunction



endlibrary

//===========================================================================

// Trigger: CACHE

//===========================================================================

//TESH.scrollpos=0

//TESH.alwaysfold=0

library CACHE initializer init



globals

    private hashtable GC

endglobals



private function init takes nothing returns nothing

    set GC = InitHashtable()

endfunction



constant function GetCache takes nothing returns hashtable

    return GC

endfunction



endlibrary//===========================================================================

// Trigger: RegisterAnyUnitEvent

//===========================================================================

//TESH.scrollpos=0

//TESH.alwaysfold=0

library RegisterAnyUnitEvent



globals

    private trigger array ts

endglobals



function RegisterAnyUnitEvent takes playerunitevent e, code cond, code act returns nothing

    local integer i = GetHandleId(e)

    local trigger t

    if act != null then

        set t = CreateTrigger()

        call TriggerRegisterAnyUnitEventBJ(t, e)

        if cond != null then

            call TriggerAddCondition(t, Filter(cond))

        endif

        call TriggerAddAction(t, act)

        set t = null

    else

        if ts[i] == null then

            set ts[i] = CreateTrigger()

            call TriggerRegisterAnyUnitEventBJ(ts[i], e)

        endif

        call TriggerAddCondition(ts[i], Filter(cond))

    endif

endfunction



endlibrary



//===========================================================================

// Trigger: SpellBlocker

//

// requires RegisterAnyUnitEvent, LastCommand

//===========================================================================

//TESH.scrollpos=20

//TESH.alwaysfold=0

library SpellBlocker requires RegisterAnyUnitEvent, LastCommand



globals

    private constant integer BUFF = 'AImx' // Spell Immunity item ability

endglobals

// Library to make certain buffs/abilities/conditions, block any ability cast

private struct data extends array

    

    private static integer counter = 0

    static integer Last = 0

    integer a

    static method add takes integer ab returns nothing

        local thistype D = thistype(thistype.counter + 1)

        set D.a = ab

        set thistype.counter = integer(D)

    endmethod

    

    static method hasit takes unit u returns boolean

        local integer i = 1

        loop

            exitwhen i > thistype.counter

            if GetUnitAbilityLevel(u, thistype(i).a) > 0 then

                set thistype.Last = thistype(i).a

                return true

            endif

            set i = i + 1

        endloop

        return false

    endmethod

    

    private static method cond takes nothing returns boolean

        local unit u = GetTriggerUnit()

        if thistype.hasit(u) then

            call SimError(GetOwningPlayer(u), GetUnitName(u) + " is being blocked by " + GetObjectName(thistype.Last))

            set thistype.Last = 0

            call RedoPreviousOrder(u)

        endif

        set u = null

        return false

    endmethod

    

    private static method onInit takes nothing returns nothing

        call RegisterAnyUnitEvent(EVENT_PLAYER_UNIT_SPELL_CAST, function thistype.cond, null)

    endmethod

endstruct



function AddSpellBlocker takes integer id returns nothing

    call data.add(id)

endfunction



function SetUnitSpellInvulnerable takes unit u, boolean f returns nothing

    if GetUnitAbilityLevel(u, BUFF) > 0 then

        if not f then

            call UnitRemoveAbility(u, BUFF)

        endif

    else

        if f then

            call UnitAddAbility(u, BUFF)

        endif

    endif

endfunction



endlibrary

//===========================================================================

// Trigger: MicroTable

//

// requires CACHE, RegisterAnyUnitEvent

//===========================================================================

//TESH.scrollpos=0

//TESH.alwaysfold=0

// MicroTable by moyack. 2008

// Version 1.0

library MicroTable initializer init requires CACHE, RegisterAnyUnitEvent



function StoreData takes handle h, integer index, integer value returns nothing

    call SaveInteger(GetCache(), GetHandleId(h), index, value)

endfunction



function GetData takes handle h, integer index returns integer 

    return LoadInteger(GetCache(), GetHandleId(h), index)

endfunction



function HasData takes handle h, integer index returns boolean

    return HaveSavedInteger(GetCache(), GetHandleId(h), index)

endfunction



function ClearValue takes handle h, integer index returns nothing 

    call RemoveSavedInteger(GetCache(), GetHandleId(h), index)

endfunction



function ClearData takes handle h returns nothing

    call FlushChildHashtable(GetCache(), GetHandleId(h))

endfunction



//==================================================

private function Clean takes nothing returns nothing

    if IsUnitType(GetTriggerUnit(), UNIT_TYPE_HERO) == false then

        call ClearData(GetTriggerUnit())

    endif

endfunction



private function init takes nothing returns nothing

    call RegisterAnyUnitEvent( EVENT_PLAYER_UNIT_DEATH, null, function Clean)

endfunction



endlibrary

//===========================================================================

// Trigger: UnitDamage

//

// DamageCredit

//===========================================================================

//TESH.scrollpos=16

//TESH.alwaysfold=0

library UnitDamage



private struct DD extends array // damage detection struct

    static group D // group of units that will have damage detection

    static group Dummies // group of units which will not be detected by the system

    static trigger T

    

    // Add the attacked unit to the damage detection if the unit is not in the pack

    private static method AddUnit takes unit d returns nothing

        if not IsUnitInGroup(d, thistype.D) and not IsUnitInGroup(d, thistype.Dummies) then

            debug call DisplayTimedTextFromPlayer(GetLocalPlayer(), 0,0,2,"Added " + GetUnitName(d) + " to the DD")

            call TriggerRegisterUnitEvent(thistype.T, d, EVENT_UNIT_DAMAGED)

            call GroupAddUnit(thistype.D, d)

        endif

        set d = null

    endmethod

    

    private static method Attacked takes nothing returns nothing

        call thistype.AddUnit(GetTriggerUnit())

    endmethod

    

    private static method Spelled takes nothing returns nothing

        if GetSpellTargetUnit() != null then

            call thistype.AddUnit(GetSpellTargetUnit())

        endif

    endmethod

    

    private static method onInit takes nothing returns nothing

        set thistype.T = CreateTrigger()

        set thistype.D = CreateGroup()

        set thistype.Dummies = CreateGroup()

        call TriggerRegisterAnyUnitEventBJ(thistype.T, EVENT_PLAYER_UNIT_ATTACKED)

        call TriggerAddAction(thistype.T, function thistype.Attacked)

        set thistype.T = CreateTrigger()

        call TriggerRegisterAnyUnitEventBJ(thistype.T, EVENT_PLAYER_UNIT_SPELL_EFFECT)

        call TriggerAddAction(thistype.T, function thistype.Spelled)

        set thistype.T = CreateTrigger()

    endmethod

endstruct



// Damage detection system functions...

function AddDamageCondition takes code func returns nothing

    call TriggerAddCondition(DD.T, Condition(func))

endfunction



function CreateDummy takes player p, integer id, real x, real y, real f returns unit 

    local unit u = CreateUnit(p, id, x, y, f)

    call GroupAddUnit(DD.Dummies, u)

    return u

endfunction



function DoSafeDamage takes unit u, widget t, real damage, boolean attack, boolean ranged, attacktype AT, damagetype DT, weapontype WT returns boolean

    local boolean b

    call DisableTrigger(DD.T)

    set b = UnitDamageTarget(u, t, damage, attack, ranged, AT, DT, WT)

    call EnableTrigger(DD.T)

    return b

endfunction



endlibrary//===========================================================================

// Trigger: DamageCredit

//

// requires MainGlobals

//===========================================================================

//TESH.scrollpos=0

//TESH.alwaysfold=0

library DamageCredit initializer init requires MainGlobals



globals

    private unit array D

endglobals



private function DoDummies takes nothing returns nothing

    local player p = GetEnumPlayer()

    local integer i = GetPlayerId(p)

    set D[i] = CreateUnit(p, Dummy, 0, 0, 0)

    call ShowUnit(D[i], false)

    call SetUnitInvulnerable(D[i], true)

endfunction



private function init2 takes nothing returns nothing

    call ForForce(UserPlayers, function DoDummies)

    call DestroyTimer(GetExpiredTimer())

endfunction



private function init takes nothing returns nothing

    call TimerStart(CreateTimer(), 1., false, function init2)

endfunction



function DamageCredit takes unit u, player p returns unit

    if GetUnitState(u, UNIT_STATE_LIFE) <= 0 or u == null then

        return D[GetPlayerId(p)]

    endif

    return u

endfunction



endlibrary//===========================================================================

// Trigger: SetUnitMaxState

//===========================================================================

//TESH.scrollpos=16

//TESH.alwaysfold=0

library SetUnitMaxState initializer init requires DataPreloader



private constant function MaxStateModifierId takes unitstate u returns integer

    if u == UNIT_STATE_MAX_LIFE then

        return 'A028' // Rawcode of the Max Life Modifier ability.

    elseif u == UNIT_STATE_MAX_MANA then

        return 'A02A' // Rawcode of the Max Mana Modifier ability.

    endif

    return 0

endfunction



function SetUnitMaxState takes unit whichUnit, unitstate whichUnitState, integer newVal returns boolean

    local integer c = newVal-R2I(GetUnitState(whichUnit, whichUnitState))

    local integer i = MaxStateModifierId(whichUnitState)

    if i == 0 then

        return false

    endif

    if c > 0 then

        loop

            exitwhen c == 0

            call UnitAddAbility(whichUnit, i)

            if c >= 100 then

                set c = c - 100

                call SetUnitAbilityLevel(whichUnit, i, 4)

            elseif c >= 10 then

                set c = c - 10

                call SetUnitAbilityLevel(whichUnit, i, 3)

            else

                set c = c - 1

                call SetUnitAbilityLevel(whichUnit, i, 2)

            endif

            call UnitRemoveAbility(whichUnit, i)

        endloop

    elseif c < 0 then

        set c = -c

        loop

            exitwhen c == 0

            call UnitAddAbility(whichUnit, i)

            if c >= 100 then

                set c = c - 100

                call SetUnitAbilityLevel(whichUnit, i, 7)

            elseif c >= 10 then

                set c = c - 10

                call SetUnitAbilityLevel(whichUnit, i, 6)

            else

                set c = c - 1

                call SetUnitAbilityLevel(whichUnit, i, 5)

            endif

            call UnitRemoveAbility(whichUnit, i)

        endloop

    endif

    return true

endfunction



private function init takes nothing returns nothing

    call PreloadSimple(MaxStateModifierId(UNIT_STATE_MAX_LIFE))

    call PreloadSimple(MaxStateModifierId(UNIT_STATE_MAX_MANA))

endfunction



endlibrary//===========================================================================

// Trigger: MovSys

//

// requires Indexor2

//===========================================================================

//TESH.scrollpos=0

//TESH.alwaysfold=0

//******************************************************************************************

//*

//* Smooth movement script 2.0 By Moyack. 2012.

//* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯

//*

//* If you use this script, please be nice and give me credits.

//*

//* This library has been designed to simulate movement defined by kinematic parameters.

//*

//* You only need to define the Projectile unit, the position and velocity vectors, 

//* and the time the Projectile will fly. The rest is managed, controlled and destroyed

//* automatically by the library.

//*

//* Additionally, you can define custom "events" when the Projectile starts, moves and ends, 

//* very convenient to set and control the Projectile behaviour.

//*

//* How to use:

//* ¯¯¯¯¯¯¯¯¯¯¯

//* This library has two data types, the vector and the Projectile structs.

//* 

//*  Vector Struct: This struct allows you to group data in the way (X, Y, Z). The vector

//*  type allows the following methods:

//*

//*   - create( real x, real y, real z) returns vector

//*   - setdata(real x, real y, real z) returns nothing

//*   - destroy() returns nothing

//*

//*  The first method allocates a new vector variable and sets at the same time data on it.

//*  The second method allows you to change the data of the vector. The third method destroys

//*  the vector. Example:

//*

//*  function VecStuff takes nothing returns nothing

//*      local vector v = vector.create(0., 10., 20.) // creates a vector [0, 10, 20]

//*      call v.setdata(15., 20., -10.) // changes the values in the vector v to [15, 20, -10]

//*      call v.destroy() // destroys the vector, freeing the memory used.

//*  endfunction

//*

//*  Projectile Struct: This one is the one in charge to do the nice things. This structs

//*  allows the following methods:

//*

//* Aknowledges:

//* ¯¯¯¯¯¯¯¯¯¯¯¯

//*  - Mad[Lion] because he proposed the problem that inspire me to make this library.

//*  - Pipedream because he had the same apporach, but opposite :) and for the idea of 

//*    partial factoring.

//*  - Vexorian, PitzerMike and all the people involved in the development of vJASS.

//*    without this tool, this idea would be still just that: an idea.

//*

//******************************************************************************************



library MovSys requires Alloc



globals

    private constant real dt = 1. / 40.   // 40 frames per second.

    private unit       LastProj    = null // Stores temporally the last Projectile created / destroyed

    private vector     StartPos           // Stores the start position of the Projectile.

    private vector     StartVel           // Stores the start velocity of the Projectile.

    private vector     LastPos            // Stores the last position of the Projectile.

    private vector     LastVel            // Stores the last velocity of the Projectile.

    private Projectile MovingProj         // Stores the evaluating Projectile. Only for use when 

endglobals                                // it's called on the CodeMove function



struct vector extends array // struct used to manage vectors LOL!!!

    real x

    real y 

    real z

    

    implement Alloc

    

    method destroy takes nothing returns nothing

        set .x = 0.

        set .y = 0.

        set .z = 0.

        call .deallocate()

    endmethod

    

    static method create takes real x, real y, real z returns vector

        local vector v = vector.allocate()

        set v.x = x

        set v.y = y

        set v.z = z

        return v

    endmethod

    

    method setdata takes real x, real y, real z returns nothing

        set .x = x

        set .y = y

        set .z = z

    endmethod

endstruct



private constant function GetA takes real x0, real x1, real v0, real v1, real tf returns real

    return (tf * (v1-v0) - 2 * (x1 - x0 - v0*tf)) / (tf*tf*tf)

endfunction



private constant function GetB takes real x0, real x1, real v0, real v1, real tf returns real

    return (3 * (x1 - x0 - v0*tf) - tf * (v1 - v0)) / (tf*tf)

endfunction



private constant function GetX takes real t, real A, real B, real C, real D returns real

    return D + t*(C + t*(B + t*A)) // thanks Pipedream for the idea :)

endfunction



private constant function GetV takes real t, real A, real B, real C returns real

    return (3*A*t + 2*B)*t + C // thanks Pipedream for the idea :)

endfunction



struct Projectile extends array

    private static region reg = null

    static group ProjGroup = CreateGroup()

    private static trigger F = CreateTrigger() // used to run code

    unit p       // Projectile unit

    vector pi    // initial and final position coordinates

    vector pf

    vector vi    // initial and final velocity coordinates

    vector vf

    real tf      // time that the Projectile will take to reach the final point

    vector vp    // variable position and velocity vars

    vector vv

    real t

    vector A     // Constant Values used for calculation stuff

    vector B

    // Miscelaneous data

    boolean DV // this flag indicates if the Projectile is destroyed with the input vectors

    boolean pU // this flag indicates if the unit used as projectile will be paused or not  

    boolexpr CodeMove //Stores the function name that will be evaluated every time any Projectile is moving

    boolexpr CodeEnd  //Stores the function name used when the Projectile dies.

    boolean HasMovCode

    boolean HasEndCode

    

    implement AllocLoop

    private static method Fire takes boolexpr b returns nothing

        // Do not change the order of these.

        // That would kill recursion-safety.

        call TriggerClearConditions(thistype.F)

        call TriggerAddCondition(thistype.F, b)

        call TriggerEvaluate(thistype.F)

    endmethod

    

    method SetData takes unit p, vector pi, vector pf, vector vi, vector vf, real t, boolean DV, boolean pU returns nothing

        local real Ax = GetA(pi.x, pf.x, vi.x, vf.x, t)

        local real Ay = GetA(pi.y, pf.y, vi.y, vf.y, t)

        local real Az = GetA(pi.z, pf.z, vi.z, vf.z, t)

        local real Bx = GetB(pi.x, pf.x, vi.x, vf.x, t)

        local real By = GetB(pi.y, pf.y, vi.y, vf.y, t)

        local real Bz = GetB(pi.z, pf.z, vi.z, vf.z, t)

        

        set .p = p

        call UnitAddAbility(p, 'Amrf')

        call UnitRemoveAbility(p, 'Amrf')

        call GroupAddUnit(thistype.ProjGroup, p)

        if pU then

            call PauseUnit(p, true)

        endif

        set .pi = pi

        set .pf = pf

        set .vi = vi

        set .vf = vf

        set .A = vector.create(Ax, Ay, Az)

        set .B = vector.create(Bx, By, Bz)

        set .vp = vector.create(0., 0., 0.)

        set .vv = vector.create(0., 0., 0.)

        if t <= 0. then

            set .tf = dt

        else

            set .tf = t

        endif

        set .DV = DV

        set .pU = pU

    endmethod

    

    method SetStartCode takes code start returns nothing

        if start != null then

            set LastProj = .p

            call StartPos.setdata(.pi.x, .pi.y, .pi.z)

            call StartVel.setdata(.vi.x, .vi.y, .vi.z)

            call LastPos.setdata(.pf.x, .pf.y, .pf.z)

            call LastVel.setdata(.vf.x, .vf.y, .vf.z)

            call ForForce(bj_FORCE_PLAYER[15], start)

        endif

    endmethod

    

    method SetMoveCode takes code move returns nothing

        if move != null then

            set .CodeMove = Condition(move)

            set .HasMovCode = true

        endif

    endmethod

    

    method SetEndCode takes code end returns nothing

        if end != null then

            set .CodeEnd = Condition(end)

            set .HasEndCode = true

        endif

    endmethod

    

    method GetVelocity takes nothing returns vector

        local vector v = vector.create(0,0,0)

        local real x = GetV(.t, .A.x, .B.x, .vi.x)

        local real y = GetV(.t, .A.y, .B.y, .vi.y)

        local real z = GetV(.t, .A.z, .B.z, .vi.z)

        call v.setdata(x, y, z)

        return v

    endmethod

    

    method GetPosition takes nothing returns vector

        return vector.create(GetUnitX(.p), GetUnitY(.p), GetUnitFlyHeight(.p))

    endmethod

    

    method destroy takes nothing returns nothing

        call GroupRemoveUnit(thistype.ProjGroup, .p)

        if .pU then

            call PauseUnit(.p, false)

        endif

        set LastProj = .p

        set .p = null

        call StartPos.setdata(.pi.x, .pi.y, .pi.z)

        call StartVel.setdata(.vi.x, .vi.y, .vi.z)

        call LastPos.setdata(.pf.x, .pf.y, .pf.z)

        call LastVel.setdata(.vf.x, .vf.y, .vf.z)

        if .HasEndCode then

            call thistype.Fire(.CodeEnd)

        endif

        if .DV then

            call .pi.destroy()

            call .pf.destroy()

            call .vi.destroy()

            call .vf.destroy()

        endif

        call .A.destroy()

        call .B.destroy()

        call .vp.destroy()

        call .vv.destroy()

        call .deallocate()

    endmethod    



    static method onTimedLoop takes nothing returns boolean

        local real x

        local real y

        local real z

        implement loop

        if .HasMovCode then

            set MovingProj = this

            call thistype.Fire(.CodeMove)

        endif

        set .t = .t + dt

        set x = GetX(.t, .A.x, .B.x, .vi.x, .pi.x)

        set y = GetX(.t, .A.y, .B.y, .vi.y, .pi.y)

        set z = GetX(.t, .A.z, .B.z, .vi.z, .pi.z)

        call .vp.setdata(x, y, z)

        set x = GetV(.t, .A.x, .B.x, .vi.x)

        set y = GetV(.t, .A.y, .B.y, .vi.y)

        set z = GetV(.t, .A.z, .B.z, .vi.z)

        call .vv.setdata(x, y, z)

        if .t > .tf or not IsPointInRegion(thistype.reg, .vp.x, .vp.y) then

            call .destroy()

        else

            call SetUnitX(.p, .vp.x)

            call SetUnitY(.p, .vp.y)

            call SetUnitFlyHeight(.p, .vp.z, 0.)

        endif

        implement endloop

        return false

    endmethod

    

    static method create takes unit p, vector pi, vector pf, vector vi, vector vf, real t, boolean DestroyVectors, boolean pauseUnit returns thistype

        local thistype pr = thistype.allocate()

        call pr.SetData(p, pi, pf, vi, vf, t, DestroyVectors, pauseUnit)

        set pr.t = 0.

        set pr.HasMovCode = false

        set pr.HasEndCode = false

        return pr

    endmethod

    

    static method createSpherical takes unit p, vector pi, vector pf, vector vsi, vector vsf, real t, boolean DestroyVectors, boolean pauseUnit returns thistype

    // this method allows you to define the speed vectors in spherical coordinates [r, t, f]

    // where r is the vector magnitude

    //       t is the angle in XY plane

    //       f is the angle in the plane defined by the vector R and the Z axis

    // ALL the angles are in RADIANS

    // when the thistype is created, all the entered vectors will be changed to cartesian system

        call vsi.setdata(vsi.x * Cos(vsi.z) * Cos(vsi.y), vsi.x * Cos(vsi.z) * Sin(vsi.y), vsi.x * Sin(vsi.z))

        call vsf.setdata(vsf.x * Cos(vsf.z) * Cos(vsf.y), vsf.x * Cos(vsf.z) * Sin(vsf.y), vsf.x * Sin(vsf.z))

        return thistype.create(p, pi, pf, vsi, vsf, t, DestroyVectors, pauseUnit)

    endmethod

    

    private static method onInit takes nothing returns nothing

        set thistype.reg = CreateRegion()

        call RegionAddRect(thistype.reg, bj_mapInitialPlayableArea)

        set StartPos = vector.create(0,0,0)

        set StartVel = vector.create(0,0,0)

        set LastPos = vector.create(0,0,0)

        set LastVel = vector.create(0,0,0)

        call TimerStart(CreateTimer(), dt, true, function thistype.onTimedLoop)

    endmethod

endstruct



// functions used to get the the unit Projectile and the vectors in custom triggers

// those functions are to be used when the unit starts and stops being a Projectile



function GetUnitProjectile takes nothing returns unit

    return LastProj

endfunction



function GetInitPos takes nothing returns vector

    return vector.create(StartPos.x, StartPos.y, StartPos.z)

endfunction



function GetInitVel takes nothing returns vector

    return vector.create(StartVel.x, StartVel.y, StartVel.z)

endfunction



function GetLastPos takes nothing returns vector

    return vector.create(LastPos.x, LastPos.y, LastPos.z)

endfunction



function GetLastVel takes nothing returns vector

    return vector.create(LastVel.x, LastVel.y, LastVel.z)

endfunction



function GetMovingProjectile takes nothing returns Projectile

    // only to use when you need to get the projectile data in a CodeMove function

    return MovingProj

endfunction



function IsUnitProjectile takes unit u returns boolean

    return IsUnitInGroup(u, Projectile.ProjGroup)

endfunction



endlibrary//===========================================================================

// Trigger: ProjSys

//

// requires MainGlobals, MovSys

//===========================================================================

//TESH.scrollpos=100

//TESH.alwaysfold=0

library ProjSys initializer InitMovSys requires MainGlobals, MovSys

//***************************************************************************************************************

//* Configuration globals

globals

    private constant string MovDustFX   = "Objects\\Spawnmodels\\Undead\\ImpaleTargetDust\\ImpaleTargetDust.mdl"

    private constant string MovSplashFX = "Abilities\\Spells\\Other\\CrushingWave\\CrushingWaveDamage.mdl"

endglobals

//***************************************************************************************************************

//* End configuration globals

    

globals

    private constant rect TreeReg = Rect(0,0,1,1)

endglobals



private function KillTrees takes nothing returns nothing

    local destructable d = GetEnumDestructable()

    call KillDestructable(d)

    set d = null

endfunction



private function RemoveTreesInRange takes real x, real y, real r returns nothing

    call SetRect(TreeReg, x-r, y-r, x+r, y+r)

    call EnumDestructablesInRect(TreeReg, True, function KillTrees)

endfunction



private function MoveKnockBackBasic takes nothing returns boolean

    local Projectile P = GetMovingProjectile()

    local real x = GetUnitX(P.p)

    local real y = GetUnitY(P.p)

    if GetUnitFlyHeight(P.p) <= 0. then

        if not IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY) then

            call DestroyEffect(AddSpecialEffect(MovDustFX, x, y))

        elseif not IsTerrainPathable(x, y, PATHING_TYPE_FLOATABILITY) then

            call DestroyEffect(AddSpecialEffect(MovSplashFX, x, y))

        endif

        if IsUnitType(P.p, UNIT_TYPE_GROUND) == true and IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY) then

            call SetUnitPosition(P.p, x, y)

            call P.destroy()

        endif

    endif

    return false

endfunction



private function MoveKnockBack takes nothing returns boolean

    local Projectile P = GetMovingProjectile()

    call MoveKnockBackBasic()

    call RemoveTreesInRange(GetUnitX(P.p), GetUnitY(P.p), 100.)

    return false 

endfunction



private function MoveMissile takes nothing returns nothing

    local Projectile p = GetMovingProjectile() 

    call SetUnitFacing(p.p, Atan2(p.vv.y, p.vv.x) * bj_RADTODEG)

endfunction



private function InitMovSys takes nothing returns nothing

    call Preload(MovDustFX)

    call Preload(MovSplashFX)

endfunction



private function ParabolicA takes real h, real d returns real

    // returns the coeficient A in the parabolic function

    // h, d, and x are in the same units of distance in WC3, which is more comfortable to use :)

    if d > 0. then

        return -4 * h / (d * d)

    else

        return 0.

    endif

endfunction



private function ParabolicB takes real h, real d returns real

    // returns the coeficient B in the parabolic function

    // h, d, and x are in the same units of distance in WC3, which is more comfortable to use :)

    // NOTE: THIS VALUE IS THE TAN OF THE PROJECTILE ANGLE

    if d > 0. then

        return 4 * h / d

    else

        return 0.

    endif

endfunction



public function SetOnGround takes nothing returns boolean

    // used to fix the unit height for land units

    local unit d = GetUnitProjectile()

    if GetUnitFlyHeight(d) > 0 and IsUnitType(d, UNIT_TYPE_FLYING ) == false then

        call SetUnitFlyHeight(d, 0., 0.)

    endif

    set d = null

    return false 

endfunction



//***********************************************************************************************

//* public usage functions

//***********************************************************************************************

function Atan3 takes real x1, real y1, real x2, real y2 returns real

    local real a = Atan2(y2 - y1, x2 - x1)

    if a >= 0. then

        return a

    else

        return 2 * bj_PI + a

    endif

endfunction



function Dist takes real x1, real y1, real x2, real y2 returns real

    local real dx = x2 - x1

    local real dy = y2 - y1

    return SquareRoot( dx * dx + dy * dy )

endfunction



function GetParabolicAngle takes real h, real d returns real

    return Atan(ParabolicB(h, d))

endfunction



function GetUnitsAngle takes unit a, unit b returns real

    return Atan3(GetUnitX(a), GetUnitY(a), GetUnitX(b), GetUnitY(b))

endfunction



function GetUnitsDist takes unit a, unit b returns real

    return Dist(GetUnitX(a), GetUnitY(a), GetUnitX(b), GetUnitY(b))

endfunction



function GetUnitProjPoint takes unit u, real angle, real dist returns location

    local real x = GetUnitX(u) + dist * Cos(angle)

    local real y = GetUnitY(u) + dist * Sin(angle)

    return Location(x, y)

endfunction



//******************************************************************************

//* KnockBack Function:

//*   - unit t:      the unit that will become into a projectile

//*   - real dist:   the distance that the projectile will move

//*   - real dir:    the angle in the plane XY which indicates the movemente direction

//*   - real height: the max height that the projectile will fly

//*   - real speed:  the initial projectile speed. If height = 0 then the projectile will change the speed until reach 0

//*   - Code InitCode: the name of the function that will be evaluated when the projectile starts moving

//*   - Code EndCode: the name of the function that will be evaluated when the projectile stops.

//*   - boolean DestroyDestructables: Indicates if the knockbacked units will destroy nearby trees while they move



function KnockBack takes unit t, real dist, real dir, real height, real speed, code InitCode, code EndCode, boolean DestroyDestructables returns nothing

    local real a = GetParabolicAngle(height, dist)

    local real tm = dist / (speed * Cos(a))

    local vector p1 = vector.create(GetUnitX(t), GetUnitY(t), GetUnitFlyHeight(t))

    local vector p2 = vector.create(p1.x + dist * Cos(dir), p1.y + dist * Sin(dir), p1.z)

    local vector vi 

    local vector vf

    local Projectile P

    if height > 0. then

        set vi = vector.create(speed, dir, a)

        set vf = vector.create(vi.x, vi.y, -vi.z)

    else

        set vi = vector.create(speed, dir, 0.)

        set vf = vector.create(0., 0., 0.)

    endif

    set P = Projectile.createSpherical(t, p1, p2, vi, vf, tm, true, true)

    call P.SetStartCode(InitCode)

    if DestroyDestructables then

        call P.SetMoveCode(function MoveKnockBack)

    else

        call P.SetMoveCode(function MoveKnockBackBasic)

    endif

    if EndCode == null then

        call P.SetEndCode(function SetOnGround)

    else

        call P.SetEndCode(EndCode)

    endif

endfunction



endlibrary//===========================================================================

// Trigger: DummyCast

//

// requires UnitDamage, MainGlobals

//===========================================================================

//TESH.scrollpos=0

//TESH.alwaysfold=0

library DummyCast initializer init requires UnitDamage, MainGlobals 



globals

    private constant real life  = 0.5

    private unit U 

endglobals



function DummyCastOnTarget takes unit c, unit t, integer Abil, integer lvl, string order, boolean instant returns nothing

    local unit d

    local boolean b

    if instant then

        set d = CreateDummy(GetOwningPlayer(c), Dummy, GetUnitX(t), GetUnitY(t), GetUnitFacing(t) + 180.)

    else

        set d = CreateDummy(GetOwningPlayer(c), Dummy, GetUnitX(c), GetUnitY(c), GetUnitFacing(c))

    endif

    call UnitAddAbility(d, Abil)

    call SetUnitAbilityLevel(d, Abil, lvl)

    call UnitApplyTimedLife(d, 0, life)

    call SetUnitPathing(d, false)

    call SetUnitX(d, GetUnitX(t))

    call SetUnitY(d, GetUnitY(t))

    call SetUnitState(d, UNIT_STATE_MANA, 9999.)

    if instant then

        set b = IssueImmediateOrder(d, order)

    else

        set b = IssueTargetOrder(d, order, t)

    endif

    debug if not b then

    debug    call DisplayTimedTextFromPlayer(GetOwningPlayer(c), 0,0,2, "Info: DummyCast couldn't cast '" + order + "' on " + GetUnitName(t))

    debug endif

    set d = null

endfunction



private function init takes nothing returns nothing

    set U = CreateUnit(Player(15), Dummy, 0,0,0)

    call ShowUnit(U, false)

    call UnitAddAbility(U, 'Aloc')

endfunction



public function GetDummy takes nothing returns unit 

    return U

endfunction



endlibrary

//===========================================================================

// Trigger: TimedEffects

//

// requires MainGlobals, Indexor2, MicroTable, DummyCast, DamageCredit

//===========================================================================

//TESH.scrollpos=123

//TESH.alwaysfold=0

library TimedEffects initializer onInit requires MainGlobals, Indexor2, MicroTable, DummyCast, DamageCredit



struct TEffect extends array

    effect fx

    real dur

    real tick

    

    implement AllocLoop

    

    method destroy takes nothing returns nothing

        call DestroyEffect(.fx)

        set .fx = null

        call .deallocate()

    endmethod

    

	static method Update takes nothing returns boolean

        implement loop

            set .tick = .tick + TEIndexer.period

            if .tick > .dur then

                call .destroy()

            endif

        implement endloop

        return false

	endmethod

    

	static method Start takes effect f, real dur returns nothing

		local thistype T

        if dur > 0. then

            set T = thistype.allocate()

            set T.fx = f

            set T.dur = dur

            set T.tick = 0.

        else

            call DestroyEffect(f)

            set f = null

        endif

	endmethod

endstruct



struct TEonUnit extends array

    private static group TEoWG = CreateGroup()

    unit u

    effect f

    real dur

    real tick

    

    implement AllocLoop

    

    method destroy takes nothing returns nothing

        call GroupRemoveUnit(thistype.TEoWG, .u)

        call DestroyEffect(.f)

        set .f = null

        set .u = null

        call .deallocate()

    endmethod

    

	static method Update takes nothing returns boolean

        implement loop

            set .tick = .tick + TEIndexer.period

            if .tick > .dur then

                call .destroy()

            endif

        implement endloop

        return false

	endmethod

    

	static method Start takes unit u, string fx, string attach, real dur returns nothing

		local thistype T

        if IsUnitInGroup(u, thistype.TEoWG) then

            return

        endif

        if dur > 0. then

            set T = thistype.allocate()

            set T.f = AddSpecialEffectTarget(fx, u, attach)

            set T.dur = dur

            set T.u = u

            set T.tick = 0.

            call GroupAddUnit(thistype.TEoWG, u)

        else

            call DestroyEffect(AddSpecialEffectTarget(fx, u, attach))

        endif

	endmethod



endstruct



struct TBolt extends array

    unit init

    unit dummy

    unit target

    integer spell

    real dur

    real count

    

    implement AllocLoop

    

    method destroy takes nothing returns nothing

        call RemoveUnit(.dummy)

        set .init = null

        set .dummy = null

        set .target = null

        call .deallocate()

	endmethod

	

    static method Update takes nothing returns boolean

        implement loop

            set .count = .count + TEIndexer.period

            call SetUnitX(.dummy, GetUnitX(.init))

            call SetUnitY(.dummy, GetUnitY(.init))

            if .count > .dur or GetWidgetLife(.init) < 0.405 or GetWidgetLife(.target) < 0.405 then

                call .destroy()

            endif

        implement endloop

        return false

    endmethod

    

	static method Start takes unit c, unit t, integer Abil, integer lvl, string order, real h, real dur returns nothing

        // c = unit that produces the bolt.

        // t = unit that receives the bolt

        // Abil = Ability Rawcode, you must base this ability on Finger of Death

        // order = the string order to cast Abil

        // h = the height where the dummy will be placed

        // dur = Bolt duration

		local thistype TB = thistype.allocate()

        set TB.spell = 0

        set TB.count = 0.

		set TB.dur = dur

        set TB.init = c

        set TB.dummy = CreateDummy(GetOwningPlayer(c), Dummy, GetUnitX(c), GetUnitY(c), GetUnitFacing(c))

        call UnitRemoveAbility(TB.dummy, 'Aloc')

        call SetUnitPathing(TB.dummy, false)

        call SetUnitX(TB.dummy, GetUnitX(c))

        call SetUnitY(TB.dummy, GetUnitY(c))

        set TB.target = t

        set TB.spell = Abil

        call UnitAddAbility(TB.dummy, 'Avul') // make unit invulnerable

        call UnitAddAbility(TB.dummy, 'Amrf')

        call SetUnitFlyHeight(TB.dummy, h, 0.) 

        call UnitAddAbility(TB.dummy, Abil)

        call SetUnitAbilityLevel(TB.dummy, Abil, lvl)

        if t != null then // is a target order

            if not IssueTargetOrder(TB.dummy, order, t) then

                debug call DisplayTimedTextFromPlayer(GetLocalPlayer(), 0,0,5,"TBolt couldn't cast the ability " + GetObjectName(Abil) + " with the order " + order)

            endif

        else // is an immediate order

            if not IssueImmediateOrder(TB.dummy, order) then

                debug call DisplayTimedTextFromPlayer(GetLocalPlayer(), 0,0,5,"TBolt couldn't cast the ability " + GetObjectName(Abil) + " with the order " + order)

            endif

        endif

	endmethod

endstruct



function DummyCastTarget takes unit c, unit t, integer Abil, integer lvl, string order returns nothing

    call TBolt.Start(c, t, Abil, lvl, order, 0., 0.5)

endfunction



struct DOT extends array

    unit c

    widget t

    real damrate

    boolean attack

    boolean range

    attacktype at

    damagetype damt

    weapontype wt

    player p

    private boolean safe

    private real dur 

    private real count

    

    implement AllocLoop

    

    method destroy takes nothing returns nothing

        set .c = null

        set .t = null

        call .deallocate()

    endmethod

    

    static method Update takes nothing returns boolean

        implement loop

            if not .safe then

                call UnitDamageTarget(DamageCredit(.c, .p), .t, .damrate * TEIndexer.period, .attack, .range, .at, .damt, .wt) 

            else

                call DoSafeDamage(DamageCredit(.c, .p), .t, .damrate * TEIndexer.period, .attack, .range, .at, .damt, .wt)

            endif

            set .count = .count + TEIndexer.period

            if .count > .dur then

                call .destroy()

            endif

        implement endloop

        return false 

    endmethod

    

    static method start takes real dur, unit c, widget t, real damrate, boolean attack, boolean range, attacktype at, damagetype damt, weapontype wt, boolean safe returns nothing

        local thistype D = thistype.allocate()

        set D.c = c

        set D.t = t

        set D.damrate = damrate

        set D.attack = attack

        set D.range = range

        set D.at = at

        set D.damt = damt

        set D.wt = wt

        set D.dur = dur

        set D.safe = safe

        set D.p = GetOwningPlayer(c)

        set D.count = 0.

    endmethod

    

endstruct



private function onInit takes nothing returns nothing

    call TEIndexer.AddCode(function TEffect.Update)

    call TEIndexer.AddCode(function TEonUnit.Update)

    call TEIndexer.AddCode(function TBolt.Update)

    call TEIndexer.AddCode(function DOT.Update)

endfunction



endlibrary



//===========================================================================

// Trigger: LastCommand

//

// requires MicroTable, Alloc

//===========================================================================

//TESH.scrollpos=0

//TESH.alwaysfold=0

library LastCommand initializer init requires MicroTable, Alloc



globals

    private constant real    MESSAGE_TIME_DURATION = 2.

    private constant string  POINT_EFFECT          = "Objects\\Spawnmodels\\Human\\FragmentationShards\\FragBoomSpawn.mdl"



    private constant key A

endglobals



struct Order extends array

    // current order

    eventid ET

    integer OrderID

    real x

    real y

    widget target

    unit unit

    item item 

    destructable destructable

    // previous order

    eventid pET

    integer pOrderID

    real px

    real py

    widget ptarget

    unit punit

    item pitem 

    destructable pdestructable

    

    implement Alloc

    

    method destroy takes nothing returns nothing

        set .target = null

        call .deallocate()

    endmethod

    

    method Store takes eventid E, integer oid, real x, real y, widget t, unit u, item i, destructable d returns nothing

        // Stores the previous order

        set .pET = .ET

        set .pOrderID = .OrderID

        set .px = .x

        set .py = .y

        set .ptarget = .target

        set .punit = .unit

        set .pitem = .item

        set .pdestructable = .destructable

        // Stores the current order

        set .ET = E

        set .OrderID = oid

        set .x = x

        set .y = y

        set .target = t

        set .unit = u

        set .item = i

        set .destructable = d

    endmethod

endstruct



private function Echo takes string s returns nothing

    debug call DisplayTimedTextFromPlayer(GetLocalPlayer(), 0,0, MESSAGE_TIME_DURATION, s)

endfunction



private function AddtoDB takes nothing returns boolean

    local unit u = GetTriggerUnit()

    local integer id = GetIssuedOrderId()

    local Order D

    if HasData(u, A) then

        set D = Order(GetData(u, A))

    else

        set D = Order.allocate()

    endif

    if GetTriggerEventId() == EVENT_PLAYER_UNIT_ISSUED_ORDER and id != 851972 then // it won't store a stop order

        debug call Echo("Immediate order: " + OrderId2String(id) + " [" + I2S(id) + "]")

        debug call DestroyEffect(AddSpecialEffectTarget(POINT_EFFECT, u, "overhead"))

        call D.Store(EVENT_PLAYER_UNIT_ISSUED_ORDER, id, 0,0, null, null, null, null)

    elseif GetTriggerEventId() == EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER then

        debug call Echo("Point order: " + OrderId2String(id) + " [" + I2S(id) + "]" + " (" + R2S(GetOrderPointX()) + "; " + R2S(GetOrderPointY()) + ")")

        debug call DestroyEffect(AddSpecialEffect(POINT_EFFECT, GetOrderPointX(), GetOrderPointY()))

        call D.Store(EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER, id, GetOrderPointX(), GetOrderPointY(), null, null, null, null)

    elseif GetTriggerEventId() == EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER then

        debug if GetOrderTargetUnit() != null then

        debug    call Echo("Target order (unit): " + OrderId2String(id) + " [" + I2S(id) + "]" + " - " + GetUnitName(GetOrderTargetUnit()))

        debug elseif GetOrderTargetItem() != null then

        debug    call Echo("Target order (item): " + OrderId2String(id) + " [" + I2S(id) + "]" + " - " + GetItemName(GetOrderTargetItem()))

        debug elseif GetOrderTargetDestructable() != null then

        debug    call Echo("Target order (destructable): " + OrderId2String(id) + " [" + I2S(id) + "]" + " - " + GetDestructableName(GetOrderTargetDestructable()))

        debug endif

        debug call DestroyEffect(AddSpecialEffectTarget(POINT_EFFECT, GetOrderTarget(), "overhead"))

        call D.Store(EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER, id, 0, 0, GetOrderTarget(), GetOrderTargetUnit(), GetOrderTargetItem(), GetOrderTargetDestructable())

    elseif GetTriggerEventId() == EVENT_PLAYER_UNIT_ISSUED_UNIT_ORDER then

        debug call Echo("Specific Unit Target order: " + OrderId2String(id) + " [" + I2S(id) + "]" + " - " + GetUnitName(GetOrderTargetUnit()))

        debug call DestroyEffect(AddSpecialEffectTarget(POINT_EFFECT, u, "overhead"))

        call D.Store(EVENT_PLAYER_UNIT_ISSUED_UNIT_ORDER, id, 0, 0, GetOrderTargetUnit(), GetOrderTargetUnit(), null, null)

    endif

    call StoreData(u, A, integer(D))

    set u = null

    return false

endfunction



private function Clean takes nothing returns boolean

    call Order(GetData(GetTriggerUnit(), A)).destroy()

    return false

endfunction 



private function init takes nothing returns nothing

    local trigger t = CreateTrigger()

    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_ISSUED_ORDER)

    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER)

    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER)

    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_ISSUED_UNIT_ORDER)

    call TriggerAddCondition(t, Condition(function AddtoDB))

    call RegisterAnyUnitEvent(EVENT_PLAYER_UNIT_DEATH, function Clean, null)

    set t = null

endfunction



// User functions

//! textmacro Functions takes KEYWORD, PREFIX

function Get$KEYWORD$Order takes unit u returns eventid

    return Order(GetData(u, A)).$PREFIX$ET

endfunction



function Get$KEYWORD$OrderId takes unit u returns integer

    return Order(GetData(u, A)).$PREFIX$OrderID

endfunction



function Get$KEYWORD$OrderPointTargetX takes unit u returns real

    return Order(GetData(u, A)).$PREFIX$x

endfunction



function Get$KEYWORD$OrderPointTargetY takes unit u returns real

    return Order(GetData(u, A)).$PREFIX$y

endfunction



function Get$KEYWORD$OrderTarget takes unit u returns widget

    return Order(GetData(u, A)).$PREFIX$target

endfunction



function Get$KEYWORD$OrderTargetUnit takes unit u returns unit

    return Order(GetData(u, A)).$PREFIX$unit

endfunction



function Get$KEYWORD$OrderTargetItem takes unit u returns item

    return Order(GetData(u, A)).$PREFIX$item

endfunction



function Get$KEYWORD$OrderTargetDestructable takes unit u returns destructable

    return Order(GetData(u, A)).$PREFIX$destructable

endfunction



function Redo$KEYWORD$Order takes unit u returns boolean

    if Get$KEYWORD$Order(u) == EVENT_PLAYER_UNIT_ISSUED_ORDER then

        return IssueImmediateOrderById(u, Get$KEYWORD$OrderId(u))

    elseif Get$KEYWORD$Order(u) == EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER then

        return IssuePointOrderById(u, Get$KEYWORD$OrderId(u), Get$KEYWORD$OrderPointTargetX(u), Get$KEYWORD$OrderPointTargetY(u))

    elseif Get$KEYWORD$Order(u) == EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER then

        return IssueTargetOrderById(u, Get$KEYWORD$OrderId(u), Get$KEYWORD$OrderTarget(u))

    endif

    return false

endfunction

//! endtextmacro



//! runtextmacro Functions("Previous","p")

//! runtextmacro Functions("Current","")



endlibrary//===========================================================================

// Trigger: IsUnitStuck n jump ability

//

// requires Indexor2, LastCommand, ProjSys, DataPreloader

//===========================================================================

//TESH.scrollpos=43

//TESH.alwaysfold=0

library IsUnitStuck initializer init requires Indexor2, LastCommand, ProjSys, DataPreloader



globals

    private constant key StuckCode

    private constant real Range = 130.0 // Min Jump distance

    private constant real Amplifier = 10. //Times we multiply the min range to determine the max jump distance

    private constant real Delta = 2.0

    private constant integer DUMMY_ITEM_ID = 'wolg'

    private item Item = null

    private group G = CreateGroup()

    private rect R

endglobals



// Jump ability

globals

    private constant integer SpellID   = 'A02F'

    private constant real    MinRange  = 130. // the range where the unit with the abililty will jump

    private constant real    Height    = 100. // Max Height the unit will jump

    private constant real    Dur       = 1.134 // jump time duration

    private constant real    Speed     = 1000. // movement speed

    

    private constant integer MOVE_ORDER = 851986

    private constant integer ATTACK_ORDER = 851983

    private constant integer SMART_ORDER = 851971

    private constant integer AIMOVE_ORDER = 851988

    private constant integer PATROL_ORDER = 851990

    

    private string Dust

    private string Water

endglobals



private struct Data extends array

    real x

    real y

    integer order

    boolean forcestop

    

    implement Alloc

    

    static method create takes real x, real y, integer order returns thistype

        local thistype d = thistype.allocate()

        set d.x = x

        set d.y = y

        set d.order = order

        set d.forcestop = false

        return d

    endmethod

endstruct



public function Check takes unit u returns boolean

    local real X = GetUnitX(u)

    local real Y = GetUnitY(u)

    local Data d = Data(GetData(u, StuckCode))

    return integer(d) > 0 and not d.forcestop and GetUnitCurrentOrder(u) > 0 and GetUnitCurrentOrder(u) == d.order and d.x - Delta < X and X < d.x + Delta and d.y - Delta < Y and Y < d.y + Delta 

endfunction



private function start takes nothing returns boolean

    // related to the jump ability

    call PauseUnit(GetUnitProjectile(), false)

    return false

endfunction



private function StorePos takes nothing returns boolean

    local unit u = GetFilterUnit()

    local Data d

    local real f

    local real w

    local integer order

    if GetUnitAbilityLevel(u, SpellID) > 0 then

        set d = GetData(u, StuckCode)

        set f = GetUnitFacing(u) * bj_DEGTORAD

        set w = GetUnitMoveSpeed(u)

        set order = GetUnitCurrentOrder(u)

        if Check(u) and (order == MOVE_ORDER or order == SMART_ORDER or order == PATROL_ORDER) then

            call SetItemPosition(Item, GetUnitX(u)+w*Cos(f), GetUnitY(u)+w*Sin(f))

            set w = Dist(GetUnitX(u), GetUnitY(u), GetItemX(Item), GetItemY(Item))

            set f = Atan3(GetUnitX(u), GetUnitY(u), GetItemX(Item), GetItemY(Item))

            call SetItemVisible(Item, false)

            call KnockBack(u, w, f, Height, Speed, function start, null, false)

        endif

        if integer(d) > 0 then

            set d.x = GetUnitX(u)

            set d.y = GetUnitY(u)

            set d.order = GetUnitCurrentOrder(u)

        else

            set d = Data.create(GetUnitX(u), GetUnitY(u), GetUnitCurrentOrder(u))

            call StoreData(u, StuckCode, d)

        endif

    endif

    set u = null

    return false

endfunction



private function DoMove takes nothing returns boolean 

    call GroupEnumUnitsInRect(G, R, Condition(function StorePos))

    return false

endfunction



private function IsPlayerUnit takes nothing returns boolean

    local unit u = GetTriggerUnit()

    local Data d = GetData(u, StuckCode)

    if GetUnitAbilityLevel(u, SpellID) > 0 and integer(d) > 0 then

        if GetIssuedOrderId() == SMART_ORDER and (GetPlayerController(GetOwningPlayer(u)) == MAP_CONTROL_COMPUTER or IsUnitAlly(u, GetOwningPlayer(GetOrderTargetUnit()))) then

            set d.forcestop = true

        else

            set d.forcestop = false

        endif

    endif

    set u = null

    return false

endfunction



private function init takes nothing returns nothing

    local trigger t = CreateTrigger()

    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER)

    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_ISSUED_ORDER)

    call TriggerAddCondition(t, function IsPlayerUnit)

    set t = null

    call TEIndexer.AddCode(function DoMove)

    set R = GetWorldBounds()

    set Item = CreateItem(DUMMY_ITEM_ID, 0, 0)

    call SetItemVisible(Item, false)

    call PreloadAbility(SpellID, "", true)

endfunction



endlibrary

//===========================================================================

// Trigger: Melee Initialization

//

// Default melee game initialization for all players

//===========================================================================

//TESH.scrollpos=0

//TESH.alwaysfold=0

//Initialization Code

library MapInit initializer Init requires MainGlobals, ARGB



private function MeleeResult takes player whichPlayer,boolean leftGame, playergameresult gR returns nothing

    local trigger t = CreateTrigger()

    local dialog  d = DialogCreate()

    local string formatString

    if (leftGame) then

        set formatString = GetLocalizedString( "PLAYER_LEFT_GAME" )

    else

        if gR == PLAYER_GAME_RESULT_VICTORY then

            set formatString = GetLocalizedString( "PLAYER_VICTORIOUS" )

        else

            set formatString = GetLocalizedString( "PLAYER_DEFEATED" )

        endif

    endif

    if SubString(formatString, 0, 2) == "%s" then

        set formatString = SubString(formatString, 2, StringLength(formatString))

    endif

    call DisplayTimedTextToForce(GetPlayersAll(), 60, ARGB.fromPlayer(whichPlayer).str( GetPlayerName(whichPlayer) ) + formatString)

    if gR == PLAYER_GAME_RESULT_VICTORY then

         call DialogSetMessage( d, GetLocalizedString( "GAMEOVER_VICTORY_MSG" ) )

        call DialogAddButton( d, GetLocalizedString( "GAMEOVER_CONTINUE_GAME" ), GetLocalizedHotkey("GAMEOVER_CONTINUE_GAME") )    

    else

        call DialogSetMessage( d, GetLocalizedString( "GAMEOVER_DEFEAT_MSG" ) )

        if (not bj_meleeGameOver and IsMapFlagSet(MAP_OBSERVERS_ON_DEATH)) then

            call DialogAddButton( d, GetLocalizedString( "GAMEOVER_CONTINUE_OBSERVING" ), GetLocalizedHotkey("GAMEOVER_CONTINUE_OBSERVING") )

        endif

    endif

    set t = CreateTrigger()

    call TriggerRegisterDialogButtonEvent( t, DialogAddQuitButton( d, true, GetLocalizedString( "GAMEOVER_QUIT_GAME" ), GetLocalizedHotkey("GAMEOVER_QUIT_GAME") ) )

    call DialogDisplay( whichPlayer, d, true )

    if gR == PLAYER_GAME_RESULT_VICTORY then

        call StartSoundForPlayerBJ( whichPlayer, bj_victoryDialogSound )

    else

        call StartSoundForPlayerBJ( whichPlayer, bj_defeatDialogSound )

    endif

endfunction



private function GameOverDialog takes player whichPlayer returns nothing

    local trigger t = CreateTrigger()

    local dialog  d = DialogCreate()

    local string  s = GetLocalizedString( "PLAYER_LEFT_GAME" )

    if SubString(s, 0, 2) == "%s" then

        set s = SubString(s, 2, StringLength(s))

    endif

    call DisplayTimedTextToForce(GetPlayersAll(), 60, ARGB.fromPlayer(whichPlayer).str( GetPlayerName(whichPlayer) ) + s)

    if (GetIntegerGameState(GAME_STATE_DISCONNECTED) != 0) then

        set s = GetLocalizedString( "GAMEOVER_DISCONNECTED" )

    else

        set s = GetLocalizedString( "GAMEOVER_GAME_OVER" )

    endif

    call DialogSetMessage( d, s )

    set t = CreateTrigger()

    call TriggerRegisterDialogButtonEvent( t, DialogAddQuitButton( d, true, GetLocalizedString( "GAMEOVER_OK" ), GetLocalizedHotkey("GAMEOVER_OK") ) )

    call DialogDisplay( whichPlayer, d, true )

    call StartSoundForPlayerBJ( whichPlayer, bj_defeatDialogSound )

endfunction



private function RemovePlayerPreserveUnits takes player whichPlayer,playergameresult gameResult,boolean leftGame returns nothing

    if AllowVictoryDefeat(gameResult) then

        call RemovePlayer(whichPlayer, gameResult)

        if gameResult == PLAYER_GAME_RESULT_VICTORY or gameResult == PLAYER_GAME_RESULT_DEFEAT then

            call MeleeResult(whichPlayer, leftGame, gameResult)

            return

        else

            call GameOverDialog( whichPlayer )

        endif

    endif

endfunction



private function MeleeDoDefeatEnumPoC takes nothing returns nothing

    local player thePlayer = GetEnumPlayer()

    call CachePlayerHeroData(thePlayer)

    call MakeUnitsPassiveForTeam(thePlayer)

    set bj_meleeDefeated[GetPlayerId(thePlayer)] = true

    call RemovePlayerPreserveUnits(thePlayer, PLAYER_GAME_RESULT_DEFEAT, false)

endfunction



private function MeleeDoVictoryEnumPoC takes nothing returns nothing

    local player thePlayer = GetEnumPlayer()

    local integer playerIndex = GetPlayerId(thePlayer)

    if (not bj_meleeVictoried[playerIndex]) then

        set bj_meleeVictoried[playerIndex] = true

        call CachePlayerHeroData(thePlayer)

        call RemovePlayerPreserveUnits(thePlayer, PLAYER_GAME_RESULT_VICTORY, false)

    endif

endfunction



private function MeleeRemoveObserversPoC takes nothing returns nothing

    local integer playerIndex

    local player indexPlayer

    set playerIndex = 0

    loop

        set indexPlayer = Player(playerIndex)

        if (IsPlayerObserver(indexPlayer)) then

            call RemovePlayerPreserveUnits(indexPlayer, PLAYER_GAME_RESULT_NEUTRAL, false)

        endif

        set playerIndex = playerIndex + 1

        exitwhen playerIndex == bj_MAX_PLAYERS

    endloop

endfunction



private function CheckLosersVictors takes nothing returns nothing

    local integer playerIndex

    local player indexPlayer

    local force defeatedPlayers = CreateForce()

    local force victoriousPlayers = null

    if not bj_meleeGameOver then

        if GetIntegerGameState(GAME_STATE_DISCONNECTED) == 0 then

            set playerIndex = 0

            loop

                set indexPlayer = Player(playerIndex)

                if (not bj_meleeDefeated[playerIndex] and not bj_meleeVictoried[playerIndex]) then

                    if (MeleeGetAllyStructureCount(indexPlayer) <= 0) then

                        call ForceAddPlayer(defeatedPlayers, Player(playerIndex))

                        set bj_meleeDefeated[playerIndex] = true

                    endif

                endif

                set playerIndex = playerIndex + 1

                exitwhen playerIndex == bj_MAX_PLAYERS

            endloop

            set victoriousPlayers = MeleeCheckForVictors()

            call ForForce(defeatedPlayers, function MeleeDoDefeatEnumPoC)

            call ForForce(victoriousPlayers, function MeleeDoVictoryEnumPoC)

            if (bj_meleeGameOver) then

                call MeleeRemoveObserversPoC()

            endif                

        else

            set bj_meleeGameOver = true

        endif

    endif

    call DestroyForce(defeatedPlayers)

    if victoriousPlayers != null then

        call DestroyForce(victoriousPlayers)

    endif

    set defeatedPlayers = null

    set victoriousPlayers = null

endfunction



private function MeleeDoDefeatPoC takes player whichPlayer returns nothing

    set bj_meleeDefeated[GetPlayerId(whichPlayer)] = true

    call RemovePlayerPreserveUnits(whichPlayer, PLAYER_GAME_RESULT_DEFEAT, false)

endfunction



private function MeleeDoLeavePoC takes player whichPlayer returns nothing

    if (GetIntegerGameState(GAME_STATE_DISCONNECTED) != 0) then

        call GameOverDialog( whichPlayer )

    else

        set bj_meleeDefeated[GetPlayerId(whichPlayer)] = true

        call RemovePlayerPreserveUnits(whichPlayer, PLAYER_GAME_RESULT_DEFEAT, true)

    endif

endfunction



private function TriggerActionPlayerDefeatedPoC takes nothing returns nothing

    local player thePlayer = GetTriggerPlayer()

    call CachePlayerHeroData(thePlayer)



    if (MeleeGetAllyCount(thePlayer) > 0) then

        // If at least one ally is still alive and kicking, share units with

        // them and proceed with death.

        call ShareEverythingWithTeam(thePlayer)

        if (not bj_meleeDefeated[GetPlayerId(thePlayer)]) then

            call MeleeDoDefeatPoC(thePlayer)

        endif

    else

        // If no living allies remain, swap all units and buildings over to

        // neutral_passive and proceed with death.

        call MakeUnitsPassiveForTeam(thePlayer)

        if (not bj_meleeDefeated[GetPlayerId(thePlayer)]) then

            call MeleeDoDefeatPoC(thePlayer)

        endif

    endif

    call CheckLosersVictors()

endfunction



private function TriggerActionPlayerLeftPoC takes nothing returns nothing

    local player thePlayer = GetTriggerPlayer()



    // Just show game over for observers when they leave

    if (IsPlayerObserver(thePlayer)) then

        call RemovePlayerPreserveUnits(thePlayer, PLAYER_GAME_RESULT_NEUTRAL, false)

        return

    endif



    call CachePlayerHeroData(thePlayer)



    // This is the same as defeat except the player generates the message 

    // "player left the game" as opposed to "player was defeated".



    if (MeleeGetAllyCount(thePlayer) > 0) then

        // If at least one ally is still alive and kicking, share units with

        // them and proceed with death.

        call ShareEverythingWithTeam(thePlayer)

        call MeleeDoLeavePoC(thePlayer)

    else

        // If no living allies remain, swap all units and buildings over to

        // neutral_passive and proceed with death.

        call MakeUnitsPassiveForTeam(thePlayer)

        call MeleeDoLeavePoC(thePlayer)

    endif

    call CheckLosersVictors()

endfunction



private function GetTownHall takes nothing returns boolean

    if IsUnitType(GetFilterUnit(), UNIT_TYPE_TOWNHALL) == true then

        set bj_groupCountUnits = bj_groupCountUnits + 1

    endif

    return false

endfunction



private function CountTownHall takes player p returns integer

    set bj_groupCountUnits = 0

    call GroupEnumUnitsOfPlayer(bj_lastCreatedGroup, p, Condition( function GetTownHall ))

    call GroupClear(bj_lastCreatedGroup)

    return bj_groupCountUnits

endfunction



private function MeleeGetAllyKeyStructureCountPoC takes player whichPlayer returns integer

    local integer playerIndex

    local player indexPlayer

    local integer keyStructs

    set keyStructs = 0

    set playerIndex = 0

    loop

        set indexPlayer = Player(playerIndex)

        if (PlayersAreCoAllied(whichPlayer, indexPlayer)) then

            set keyStructs = CountTownHall(indexPlayer)

        endif

        set playerIndex = playerIndex + 1

        exitwhen playerIndex == bj_MAX_PLAYERS

    endloop

    return keyStructs

endfunction



private function MeleePlayerIsCrippledPoC takes player whichPlayer returns boolean

    local integer allyStructures = MeleeGetAllyStructureCount(whichPlayer)

    local integer allyKeyStructures = MeleeGetAllyKeyStructureCountPoC(whichPlayer)

    return (allyStructures > 0) and (allyKeyStructures <= 0)

endfunction



private function GetRaceMessage takes player p returns string

    local string s = "You will be revealed to your opponents unless you build a "

    if PlayerIsNaga(p) then

        set s = s + GetObjectName(NagaHallT1)

    else

        set s = s + GetObjectName(DemonHallT1)

    endif

    return s 

endfunction



private function MeleeGetCrippledRevealedMessagePoC takes player whichPlayer returns string

    return GetLocalizedString("CRIPPLE_REVEALING_PREFIX") + ARGB.fromPlayer(whichPlayer).str( GetPlayerName(whichPlayer) ) + GetLocalizedString("CRIPPLE_REVEALING_POSTFIX")

endfunction



private function MeleeCrippledPlayerTimeoutPoC takes nothing returns nothing

    local timer expiredTimer = GetExpiredTimer()

    local integer playerIndex

    local player  exposedPlayer

    set playerIndex = 0

    loop

        if (bj_crippledTimer[playerIndex] == expiredTimer) then

            exitwhen true

        endif

        set playerIndex = playerIndex + 1

        exitwhen playerIndex == bj_MAX_PLAYERS

    endloop

    if (playerIndex == bj_MAX_PLAYERS) then

        return

    endif

    set exposedPlayer = Player(playerIndex)

    if (GetLocalPlayer() == exposedPlayer) then

        call TimerDialogDisplay(bj_crippledTimerWindows[playerIndex], false)

    endif

    call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, bj_MELEE_CRIPPLE_MSG_DURATION, MeleeGetCrippledRevealedMessagePoC(exposedPlayer))

    call MeleeExposePlayer(exposedPlayer, true)

endfunction



private function MeleeCheckForCrippledPlayersPoC takes nothing returns nothing

    local integer playerIndex

    local player indexPlayer

    local boolean isNowCrippled

    if bj_finishSoonAllExposed then

        return

    endif

    set playerIndex = 0

    loop

        set indexPlayer = Player(playerIndex)

        set isNowCrippled = MeleePlayerIsCrippledPoC(indexPlayer)

        if (not bj_playerIsCrippled[playerIndex] and isNowCrippled) then

            set bj_playerIsCrippled[playerIndex] = true

            call TimerStart(bj_crippledTimer[playerIndex], bj_MELEE_CRIPPLE_TIMEOUT, false, function MeleeCrippledPlayerTimeoutPoC)

            if (GetLocalPlayer() == indexPlayer) then

                call TimerDialogDisplay(bj_crippledTimerWindows[playerIndex], true)

                call DisplayTimedTextToPlayer(indexPlayer, 0, 0, bj_MELEE_CRIPPLE_MSG_DURATION, GetRaceMessage(indexPlayer))

            endif

        elseif (bj_playerIsCrippled[playerIndex] and not isNowCrippled) then

            set bj_playerIsCrippled[playerIndex] = false

            call PauseTimer(bj_crippledTimer[playerIndex])

            if (GetLocalPlayer() == indexPlayer) then

                call TimerDialogDisplay(bj_crippledTimerWindows[playerIndex], false)

                if (MeleeGetAllyStructureCount(indexPlayer) > 0) then

                    if (bj_playerIsExposed[playerIndex]) then

                        call DisplayTimedTextToPlayer(indexPlayer, 0, 0, bj_MELEE_CRIPPLE_MSG_DURATION, GetLocalizedString("CRIPPLE_UNREVEALED"))

                    else

                        call DisplayTimedTextToPlayer(indexPlayer, 0, 0, bj_MELEE_CRIPPLE_MSG_DURATION, GetLocalizedString("CRIPPLE_UNCRIPPLED"))

                    endif

                endif

            endif

            call MeleeExposePlayer(indexPlayer, false)

        endif

        set playerIndex = playerIndex + 1

        exitwhen playerIndex == bj_MAX_PLAYERS

    endloop

endfunction



private function MeleeCheckLostUnitPoC takes unit lostUnit returns nothing

    local player lostUnitOwner = GetOwningPlayer(lostUnit)

    if (GetPlayerStructureCount(lostUnitOwner, true) <= 0) then

        call CheckLosersVictors()

    endif

    call MeleeCheckForCrippledPlayersPoC()

endfunction



private function TriggerActionConstructCancelPoC takes nothing returns nothing

    call MeleeCheckLostUnitPoC(GetCancelledStructure())

endfunction



private function MeleeTriggerActionUnitDeathPoC takes nothing returns nothing

    if (IsUnitType(GetDyingUnit(), UNIT_TYPE_STRUCTURE)) then

        call MeleeCheckLostUnitPoC(GetDyingUnit())

    endif

endfunction



private function MeleeCheckAddedUnitPoC takes unit addedUnit returns nothing

    local player addedUnitOwner = GetOwningPlayer(addedUnit)

    if (bj_playerIsCrippled[GetPlayerId(addedUnitOwner)]) then

        call MeleeCheckForCrippledPlayersPoC()

    endif

endfunction



private function MeleeTriggerActionUnitConstructionStartPoC takes nothing returns nothing

    call MeleeCheckAddedUnitPoC(GetConstructingStructure())

endfunction



private function MeleeTriggerActionAllianceChangePoC takes nothing returns nothing

    call CheckLosersVictors()

    call MeleeCheckForCrippledPlayersPoC()

endfunction



private function MeleeVictoryDefeatPoC takes nothing returns nothing

    local trigger    trig

    local integer    index

    local player     indexPlayer

    set bj_finishSoonTimerDialog = CreateTimerDialog(null)

    set trig = CreateTrigger()

    call TriggerRegisterGameEvent(trig, EVENT_GAME_TOURNAMENT_FINISH_SOON)

    call TriggerAddAction(trig, function MeleeTriggerTournamentFinishSoon)

    set trig = CreateTrigger()

    call TriggerRegisterGameEvent(trig, EVENT_GAME_TOURNAMENT_FINISH_NOW)

    call TriggerAddAction(trig, function MeleeTriggerTournamentFinishNow)

    set index = 0 

    loop

        set indexPlayer = Player(index)

        if (GetPlayerSlotState(indexPlayer) == PLAYER_SLOT_STATE_PLAYING) then

            set bj_meleeDefeated[index] = false

            set bj_meleeVictoried[index] = false

            set bj_playerIsCrippled[index] = false

            set bj_playerIsExposed[index] = false

            set bj_crippledTimer[index] = CreateTimer()

            set bj_crippledTimerWindows[index] = CreateTimerDialog(bj_crippledTimer[index])

            call TimerDialogSetTitle(bj_crippledTimerWindows[index], MeleeGetCrippledTimerMessage(indexPlayer))

            set trig = CreateTrigger()

            call TriggerRegisterPlayerUnitEvent(trig, indexPlayer, EVENT_PLAYER_UNIT_CONSTRUCT_CANCEL, null)

            call TriggerAddAction(trig, function TriggerActionConstructCancelPoC)

            set trig = CreateTrigger()

            call TriggerRegisterPlayerUnitEvent(trig, indexPlayer, EVENT_PLAYER_UNIT_DEATH, null)

            call TriggerAddAction(trig, function MeleeTriggerActionUnitDeathPoC)

            set trig = CreateTrigger()

            call TriggerRegisterPlayerUnitEvent(trig, indexPlayer, EVENT_PLAYER_UNIT_CONSTRUCT_START, null)

            call TriggerAddAction(trig, function MeleeTriggerActionUnitConstructionStartPoC)

            set trig = CreateTrigger()

            call TriggerRegisterPlayerEvent(trig, indexPlayer, EVENT_PLAYER_DEFEAT)

            call TriggerAddAction(trig, function TriggerActionPlayerDefeatedPoC)

            set trig = CreateTrigger()

            call TriggerRegisterPlayerEvent(trig, indexPlayer, EVENT_PLAYER_LEAVE)

            call TriggerAddAction(trig, function TriggerActionPlayerLeftPoC)

            set trig = CreateTrigger()

            call TriggerRegisterPlayerAllianceChange(trig, indexPlayer, ALLIANCE_PASSIVE)

            call TriggerRegisterPlayerStateEvent(trig, indexPlayer, PLAYER_STATE_ALLIED_VICTORY, EQUAL, 1)

            call TriggerAddAction(trig, function MeleeTriggerActionAllianceChangePoC)

        else

            set bj_meleeDefeated[index] = true

            set bj_meleeVictoried[index] = false

            if (IsPlayerObserver(indexPlayer)) then

                set trig = CreateTrigger()

                call TriggerRegisterPlayerEvent(trig, indexPlayer, EVENT_PLAYER_LEAVE)

                call TriggerAddAction(trig, function TriggerActionPlayerLeftPoC)

            endif

        endif

        set index = index + 1

        exitwhen index == bj_MAX_PLAYERS

    endloop

    call TimerStart(CreateTimer(), 2.0, false, function MeleeTriggerActionAllianceChangePoC)

endfunction



private function PreloadHeroes takes nothing returns nothing

    // Preload units

    local integer array uid

    local integer i = 0

    set uid[0] = 'H001' //Naga Warqueen

    set uid[1] = 'H002' //Naga Enchantress

    set uid[2] = 'H003' //Naga Imperial Warrior

    set uid[3] = 'H005' //Venom Warrior

    set uid[4] = 'U005' //Arachnian Queen

    set uid[5] = 'H000' //Inferno Warrior

    set uid[6] = 'N013' //Brutal Lord

    set uid[7] = 'N014' //Lord of Darkness

    loop

        exitwhen i > 7

        call RemoveUnit(CreateUnit(Player(15), uid[i], 0, 0, 0))

        set i = i + 1

    endloop

endfunction



private function HeroLimit takes nothing returns nothing

    local integer index

    set index = 0

    loop

        call SetPlayerMaxHeroesAllowed(3, Player(index))

        call ReducePlayerTechMaxAllowed(Player(index), 'H001', 1)

        call ReducePlayerTechMaxAllowed(Player(index), 'H002', 1)

        call ReducePlayerTechMaxAllowed(Player(index), 'H003', 1)

        call ReducePlayerTechMaxAllowed(Player(index), 'H005', 1)

        call ReducePlayerTechMaxAllowed(Player(index), 'U005', 1)

        call ReducePlayerTechMaxAllowed(Player(index), 'H000', 1)

        call ReducePlayerTechMaxAllowed(Player(index), 'N013', 1)

        call ReducePlayerTechMaxAllowed(Player(index), 'N014', 1)

        // neutral heroes

        call ReducePlayerTechMaxAllowed(Player(index), 'Npbm', 1)

        call ReducePlayerTechMaxAllowed(Player(index), 'Nbrn', 1)

        call ReducePlayerTechMaxAllowed(Player(index), 'Nngs', 1)

        call ReducePlayerTechMaxAllowed(Player(index), 'Nplh', 1)

        call ReducePlayerTechMaxAllowed(Player(index), 'Nbst', 1)

        call ReducePlayerTechMaxAllowed(Player(index), 'Nalc', 1)

        call ReducePlayerTechMaxAllowed(Player(index), 'Ntin', 1)

        call ReducePlayerTechMaxAllowed(Player(index), 'Nfir', 1)

        set index = index + 1

        exitwhen index == 12

    endloop

endfunction



private function IsPlaying takes integer p returns boolean

    // Indicates if the player slot is playing

    return GetPlayerSlotState(Player(p)) == PLAYER_SLOT_STATE_PLAYING

endfunction



private function StartingResources takes nothing returns nothing

    // Set the starting resources for all players

    local integer i = 0

    loop

        exitwhen i == 12

        if IsPlaying(i) then

            call SetPlayerState( Player(i), PLAYER_STATE_RESOURCE_GOLD, 550 )

            call SetPlayerState( Player(i), PLAYER_STATE_RESOURCE_LUMBER, 210 )

        endif

        set i = i + 1

    endloop

endfunction



private function IsNaga takes integer p returns boolean

    // Indicates if the player race must be set as Naga

    return PlayerIsNaga(Player(p)) and IsPlaying(p)

endfunction



private function IsDemon takes integer p returns boolean

    // Indicates if the player race must be set as Demon

    return not PlayerIsNaga(Player(p)) and IsPlaying(p)

endfunction



private function SetTownHall takes integer p returns integer

    // Returns the correct town Hall ID

    if IsNaga(p) then

        return NagaHallT1

    elseif IsDemon(p) then

        return DemonHallT1

    else

        return 0

    endif 

endfunction



private function SetPeon takes integer p returns integer

    // Returns the correct worker ID

    if IsNaga(p) then

        return NagaPeon

    elseif IsDemon(p) then

        return DemonPeon

    else

        return 0

    endif 

endfunction



private function StartingUnits takes integer p returns nothing

    // Start the units for each active player

    local player Pl = Player(p)

    local location lp = GetStartLocationLoc(GetPlayerStartLocation(Pl))

    local boolean useRandomHero = IsMapFlagSet(MAP_RANDOM_HERO)

    local real unitSpacing = 64.00

    local unit nearestMine = MeleeFindNearestMine(lp, bj_MELEE_MINE_SEARCH_RADIUS)

    local location nearMineLoc

    local location heroLoc

    local real peonX

    local real peonY

    local integer TownHID = SetTownHall(p)

    local integer PeonID = SetPeon(p)

    call CreateUnitAtLoc(Pl, TownHID, lp, bj_UNIT_FACING)

    if nearestMine != null then

        set nearMineLoc = MeleeGetProjectedLoc(GetUnitLoc(nearestMine), lp, 320, 0)

        set peonX = GetLocationX(nearMineLoc)

        set peonY = GetLocationY(nearMineLoc)

        call CreateUnit(Pl, PeonID, peonX + 0.00 * unitSpacing, peonY + 1.00 * unitSpacing, bj_UNIT_FACING)

        call CreateUnit(Pl, PeonID, peonX + 1.00 * unitSpacing, peonY + 0.15 * unitSpacing, bj_UNIT_FACING)

        call CreateUnit(Pl, PeonID, peonX - 1.00 * unitSpacing, peonY + 0.15 * unitSpacing, bj_UNIT_FACING)

        call CreateUnit(Pl, PeonID, peonX + 0.60 * unitSpacing, peonY - 1.00 * unitSpacing, bj_UNIT_FACING)

        call CreateUnit(Pl, PeonID, peonX - 0.60 * unitSpacing, peonY - 1.00 * unitSpacing, bj_UNIT_FACING)

        set heroLoc = MeleeGetProjectedLoc(nearMineLoc, lp, 384, 45)

    else

        set peonX = GetLocationX(lp)

        set peonY = GetLocationY(lp) - 224.00

        call CreateUnit(Pl, PeonID, peonX + 2.00 * unitSpacing, peonY + 0.00 * unitSpacing, bj_UNIT_FACING)

        call CreateUnit(Pl, PeonID, peonX + 1.00 * unitSpacing, peonY + 0.00 * unitSpacing, bj_UNIT_FACING)

        call CreateUnit(Pl, PeonID, peonX + 0.00 * unitSpacing, peonY + 0.00 * unitSpacing, bj_UNIT_FACING)

        call CreateUnit(Pl, PeonID, peonX - 1.00 * unitSpacing, peonY + 0.00 * unitSpacing, bj_UNIT_FACING)

        call CreateUnit(Pl, PeonID, peonX - 2.00 * unitSpacing, peonY + 0.00 * unitSpacing, bj_UNIT_FACING)

        set heroLoc = Location(peonX, peonY - 2.00 * unitSpacing)

    endif

    if useRandomHero then

        if IsNaga(p) then

            call MeleeRandomHeroLoc(Pl, 'H001', 'H002', 'H003', 'H005', heroLoc)

        elseif IsDemon(p) then

            call MeleeRandomHeroLoc(Pl, 'U005', 'H000', 'N013', 'N014', heroLoc)

        endif

    else

        call SetPlayerState(Pl, PLAYER_STATE_RESOURCE_HERO_TOKENS, bj_MELEE_STARTING_HERO_TOKENS)

    endif

    call SetCameraPositionForPlayer(Pl, peonX, peonY)

    call SetCameraQuickPositionForPlayer(Pl, peonX, peonY)

    call RemoveLocation(lp)

    call RemoveLocation(nearMineLoc)

    call RemoveLocation(heroLoc)

    set Pl = null

    set lp = null

    set nearestMine = null

    set nearMineLoc = null

    set heroLoc = null

endfunction



private function Init takes nothing returns nothing

    local integer i = 0

    call PreloadHeroes()

    call SetFloatGameState(GAME_STATE_TIME_OF_DAY, bj_MELEE_STARTING_TOD)

    call MeleeGrantHeroItems()

    call MeleeClearExcessUnits()

    call HeroLimit()

    call StartingResources()

    loop

        if GetPlayerSlotState(Player(i)) == PLAYER_SLOT_STATE_PLAYING then

            call StartingUnits(i)

        endif

        if GetPlayerSlotState(Player(i)) == PLAYER_SLOT_STATE_PLAYING and GetPlayerController(Player(i)) == MAP_CONTROL_COMPUTER then

            if PlayerIsNaga(Player(i)) then

                call StartMeleeAI(Player(i), "war3mapImported\\Naga_AI_General.ai" )

            else

                call StartMeleeAI(Player(i), "war3mapImported\\Demon_Mixted.ai" )

            endif

            

        endif

        set i = i + 1

        exitwhen i == bj_MAX_PLAYERS

    endloop

    

    call MeleeVictoryDefeatPoC()

endfunction



endlibrary    



//===========================================================================

// Trigger: Play Race Music

//===========================================================================

//TESH.scrollpos=0

//TESH.alwaysfold=0

library NagaTheme initializer init



private function Play takes nothing returns nothing

    if PlayerIsNaga(GetLocalPlayer()) then

        call PlayThematicMusic( "Sound\\Music\\mp3Music\\NagaTheme.mp3" )

    else

        call PlayThematicMusic( "Sound\\Music\\mp3Music\\UndeadX1.mp3" )

    endif

    call DestroyTimer(GetExpiredTimer())

endfunction



private function init takes nothing returns nothing

    call TimerStart(CreateTimer(), 0.5, false, function Play)

endfunction



endlibrary//===========================================================================

// Trigger: Credits

//===========================================================================

//TESH.scrollpos=0

//TESH.alwaysfold=0

scope Credits initializer Init



globals

    private quest array Q

endglobals 



private function StartCredit takes integer questType, string title, string description, string iconPath returns quest

    local boolean required   = (questType == bj_QUESTTYPE_REQ_DISCOVERED) or (questType == bj_QUESTTYPE_REQ_UNDISCOVERED)

    local boolean discovered = (questType == bj_QUESTTYPE_REQ_DISCOVERED) or (questType == bj_QUESTTYPE_OPT_DISCOVERED)

    local quest q = CreateQuest()

    call QuestSetTitle(q, title)

    call QuestSetDescription(q, description)

    call QuestSetIconPath(q, iconPath)

    call QuestSetRequired(q, required)

    call QuestSetDiscovered(q, discovered)

    call QuestSetCompleted(q, false)

    return q

endfunction



private function StartSubCredit takes quest whichQuest, string description returns nothing

    local questitem q = QuestCreateItem(whichQuest)

    call QuestItemSetDescription(q, description)

    call QuestItemSetCompleted(q, false)

    set q = null

endfunction



private function Actions takes nothing returns nothing

    // Main credit

    set Q[0] = StartCredit( bj_QUESTTYPE_REQ_DISCOVERED, "Power of Corruption", "This is an altered melee map, where you can play a very improved Naga or Demon race.\n\nAny comments and suggestions can be placed in poc.it.cx. Thanks for playing.", "ReplaceableTextures\\CommandButtons\\BTNBrutalLord.blp" )

    call StartSubCredit( Q[0], "Visit poc.it.cx" )

    call StartSubCredit( Q[0], "And download the latest version" )

    // Staff credit

    set Q[1] = StartCredit( bj_QUESTTYPE_REQ_DISCOVERED, "Team", "This is the staff behind of this game", "ReplaceableTextures\\CommandButtons\\BTNNagaKing.blp" )

    call StartSubCredit( Q[1], "Moyack: Main map developer." )

    call StartSubCredit( Q[1], "Av3n: Ideas, Spells, AI and suggestions" )

    call StartSubCredit( Q[1], "Tarrasque: Modelling & suggestions" )

    call StartSubCredit( Q[1], "JetFangInferno: Suggestions & FX design" )

    call StartSubCredit( Q[1], "Archmage Owenalacaster: AI development" )

    call StartSubCredit( Q[1], "THE_END: Comments, support and Skins" )

    // Models credit

    set Q[2] = StartCredit( bj_QUESTTYPE_REQ_DISCOVERED, "Models - Skins - Spells", "Armel:\n  - Naga Enchantress\nAv3n:\n  - Demon caster spells\nCookie:\n  - Arachnian Queen\nD.O.G:\n  - Demon Birth model\n  - Chaos Razormane\nDonDustin:\n  - VolcanoShieldTarget\nFrankster:\n  - Fel hound Rider\n  - Fel Orc Rampager\n  - Chaos Altar of Terror\n  - Fel Orc Assassin\n-Grendel:\n  - Ogre Iron Fist (modified)\n  - Legionnaire (modified)\nGottfrei:\n  - CruelCloister\n  - Demonic Sanctuary\nTarrasque:\n  - WarQueen\n  - incursor (terror king)\n  - Naga Royal Guard\n  - Dragon Turtle (Transport turtle)\n  - Death Knight (Burning Knight)\n  - Rock Prison\n  - Sea Drake\n  - Lord of Darkness", "ReplaceableTextures\\CommandButtons\\BTNLordofDarkness.blp")

    call StartSubCredit( Q[2], "Armel" )

    call StartSubCredit( Q[2], "Av3n" )

    call StartSubCredit( Q[2], "Cookie" )

    call StartSubCredit( Q[2], "D.O.G" )

    call StartSubCredit( Q[2], "DonDustin" )

    call StartSubCredit( Q[2], "Frankster" )

    call StartSubCredit( Q[2], "-Grendel")

    call StartSubCredit( Q[2], "Gottfrei" )

    call StartSubCredit( Q[2], "Tarrasque" )

    call StartSubCredit( Q[2], "JetFangInferno" )

    call StartSubCredit( Q[2], "Mephestrial" )

    call StartSubCredit( Q[2], "Pheonix-IV" )

    call StartSubCredit( Q[2], "sPy")

    call StartSubCredit( Q[2], "THE_END" )

    call StartSubCredit( Q[2], "Whitehorn" )

    call StartSubCredit( Q[2], "WyrWuulfe" )

    // more art credits

    set Q[6] = StartCredit( bj_QUESTTYPE_REQ_DISCOVERED, "More art credits", "(Continuation):\nJetFagInferno\n  - Spiral Aura\n  - Fanactism Aura\n  - Greater Geiser\n  - Aura of Damnation\n  - Aura of Damnation buff\n  - BlackHole\n  - ManaThirst\n  - Treacherous Attack\n  - EnergyBreathDamage\nMephestrial:\n  - Legion Teleporter model\nPheonix-IV:\n  - Naga Town Hall\nSpy:\n  - Lava Bomb model\nTHE_END:\n  - Venom Warrior skin\n  - Demon Hall model\nWhitehorn:\n  - Diabolic skin\n  - Despoiler skin\nWyrWuulfe:\n  - Satyr Worker model", "ReplaceableTextures\\CommandButtons\\BTNNagaQueen.blp")

    call StartSubCredit( Q[6], "Armel" )

    call StartSubCredit( Q[6], "Av3n" )

    call StartSubCredit( Q[6], "Cookie" )

    call StartSubCredit( Q[6], "D.O.G" )

    call StartSubCredit( Q[2], "Frankster" )

    call StartSubCredit( Q[6], "-Grendel")

    call StartSubCredit( Q[6], "Gottfrei" )

    call StartSubCredit( Q[6], "Tarrasque" )

    call StartSubCredit( Q[6], "JetFangInferno" )

    call StartSubCredit( Q[6], "Mephestrial" )

    call StartSubCredit( Q[6], "Pheonix-IV" )

    call StartSubCredit( Q[6], "sPy")

    call StartSubCredit( Q[6], "THE_END" )

    call StartSubCredit( Q[6], "Whitehorn" )

    call StartSubCredit( Q[6], "WyrWuulfe" )

    // Suggestions and Ideas credit

    set Q[3] = StartCredit( bj_QUESTTYPE_OPT_DISCOVERED, "Script & suggestions", "- Av3n (Your valuable help with items, abilities and other stuff)\n- RedDragon (Abilities help and other stuff)\n- Tarrasque (Your models and feedback were very useful)\n- JetFangInferno (For his suggestions and FX development)\n- GaDDeN (he has been a great helper with this project)\n- Kyrbi0: Abilities and some other ideas\n- Tim. (Thanks for his comments and for directing WC3C <3\n- Veev. For his help in grammar\n- Archmage Owenalacaster. For his help with the AI improvement.\n- Vexorian. For TimedLoop script\n- Earth-Fury for Board script.\n- WC3C community (for all the feedback received)", "ReplaceableTextures\\CommandButtons\\BTNBansheeMaster.blp" )

    call StartSubCredit( Q[3], "Archmage Owenalacaster" )

    call StartSubCredit( Q[3], "Av3n" )

    call StartSubCredit( Q[3], "Earth-Fury" )

    call StartSubCredit( Q[3], "GaDDeN" )

    call StartSubCredit( Q[3], "Tarrasque" )

    call StartSubCredit( Q[3], "Jualin (Caster abilities ideas)" )

    call StartSubCredit( Q[3], "Kyrbi0" )

    call StartSubCredit( Q[3], "Tim." )

    call StartSubCredit( Q[3], "Raq_Thao" )

    call StartSubCredit( Q[3], "RedDragon" )

    call StartSubCredit( Q[3], "Sevion")

    call StartSubCredit( Q[3], "Whitehorn (Naga Imperial Warrior abilities)" )

    call StartSubCredit( Q[3], "Zantetsuken@Azeroth (Veev)" )



    set Q[4] = StartCredit( bj_QUESTTYPE_OPT_DISCOVERED, "Icons", "Some of this icons are as is, others were modified in borders and/or recolored in some cases, but they are based on the original work of the following authors:", "ReplaceableTextures\\CommandButtons\\BTNRune.blp" )

    call StartSubCredit( Q[4], "BLIZZARD" )

    call StartSubCredit( Q[4], "CrazzyRussian" )

    call StartSubCredit( Q[4], "FrIkY" )

    call StartSubCredit( Q[4], "Handclaw" )

    call StartSubCredit( Q[4], "M0rbid" )

    call StartSubCredit( Q[4], "neo1989" )

    call StartSubCredit( Q[4], "NFWar" )

    call StartSubCredit( Q[4], "TDR" )

    call StartSubCredit( Q[4], "TripleDotta" )

    // Other credits

    set Q[5] = StartCredit( bj_QUESTTYPE_OPT_DISCOVERED, "Other Credits", "- Vexorian: For your excellent WC3mapoptimizer. This map was reduced and protected with wc3optimizer 5.0\n- RedDragon: A great supporter, thanks a lot.\n- scumedit.net (R.I.P.): I have an special gratitude with this clan for its support and bugs comments.\n- PitzerMike: For keeping alive JNGP. This map has been developed in Jass New Generation Pack (5b).\n- WC3Campaigns.net: For all the great support and hosting of this project.\n- This map has been compiled using Jass Helper version 0.9.J.0. (required for 1.24 patch and the known shit...) Credits to the respective authors.", "ReplaceableTextures\\CommandButtons\\BTNInfernalFlameCannon.blp" )

    call StartSubCredit( Q[5], "Cohadar (For improving JassHelper and keep it alive)" )

    call StartSubCredit( Q[5], "Pipedream (Grimoire is too sexy)" )

    call StartSubCredit( Q[5], "PitzerMike (safety dance :P)" )

    call StartSubCredit( Q[5], "Zoxc" )

    call StartSubCredit( Q[5], "RedDragon: Ideas and suggestions" )

    call StartSubCredit( Q[5], "Red-Bones-Ghoul: Ideas and suggestions (Lord of Darkness abilities)" )

    call StartSubCredit( Q[5], "Blade.dk (his war stomp spell making tutorial opens my mind to the JASS world)" )

    call StartSubCredit( Q[5], "scumedit.net (R.I.P.)" )

    call StartSubCredit( Q[5], "www.wc3campaigns.net" )

    call StartSubCredit( Q[5], "Blizzard: For creating patch 1.24 and fuck the WC3 modding community" )

    call DestroyTimer(GetExpiredTimer())

    call CinematicFadeBJ( bj_CINEFADETYPE_FADEIN, 5.00, "ReplaceableTextures\\CameraMasks\\Black_mask.blp", 0, 0, 0, 0 )

endfunction



//===========================================================================

private function Init takes nothing returns nothing

    call TimerStart(CreateTimer(), 3., false, function Actions)

    call CinematicFadeBJ( bj_CINEFADETYPE_FADEOUT, 0., "ReplaceableTextures\\CameraMasks\\Black_mask.blp", 0, 0, 0, 0 )

    call DisplayTimedTextToForce( bj_FORCE_ALL_PLAYERS, 8., "|cffffff00Power of Corruption v2.3 patch 1.24+ compatible version|r\n|CFF00FF00By MOYACK. 2012.|r\nFeaturing models from Tarrasque and JetFangInferno\nSpells by Av3n and Moyack,\nAI scripting improvements by Archmage Owenalacaster\n|cffffff00Press F9 for basic help and credits" )

endfunction



endscope



//===========================================================================

// Trigger: Multiboard Control

//===========================================================================

//TESH.scrollpos=82

//TESH.alwaysfold=0

library Multiboard initializer init requires Board, MainGlobals, UnitDamage



globals   

	private constant real   ElapsedTime    = 6.

	

	private constant string Title          = "|CFFFFFF00Power of Corruption|R |CFF18BE00Player Stats"

    private constant string Team           = "|CFF18BE00Team "

	private constant string Player_Text    = "|CFFFFF799Player Name"

	private constant string Kills_Text     = "|CFFFFF799kills"

	private constant string Devotion_Text  = "|CFFFFF799Devotion"

	

	private constant string PlayerIcon     = "ReplaceableTextures\\WorldEditUI\\Editor-MultipleUnits.blp"

	private constant string BuildingsIcon  = "ReplaceableTextures\\WorldEditUI\\Doodad-Structures.blp"

	private constant string KillsIcon      = "ReplaceableTextures\\CommandButtons\\BTNSpellSteal.blp"

	private constant string DevotionIcon   = "ReplaceableTextures\\CommandButtons\\BTNResStone.blp"

	private constant string DemonIcon      = "ReplaceableTextures\\CommandButtons\\BTNDoomGuard.blp"

	private constant string NagaIcon       = "ReplaceableTextures\\CommandButtons\\BTNNagaMyrmidon.blp"

	private constant string DefeatedColor  = "|C88FFF799"

    private constant string Sep            = "________________________________________________________"

    private constant real   PercChar       = 0.0055// width of the characters respect the screen

    

    private Board array B

    private integer OBSROWCOUNT = 1

    private boolean HASOBSERVERS = false

    private force Observers = CreateForce()

endglobals



private function GetRaceIcon takes player p returns string

    //Returns the race icon

    local string s

    if PlayerIsNaga(p) then

        set s = NagaIcon

    else

        set s = DemonIcon

    endif

    return s

endfunction



private function DestroyUnits takes nothing returns boolean

    local unit u = GetFilterUnit()

    call RemoveUnit(u)

    set u = null

    return false

endfunction



private function FillBoard takes nothing returns nothing

    local integer i = GetPlayerId(GetEnumPlayer())

    local real w = StringLength(Player_Text)-10

    local BoardItem I

    set B[i] = Board.create()

    set B[i].title = Title

    set B[i].row.count = 1

    set B[i].col.count = 2

    set B[i][0][0].text = Player_Text

    set B[i][1][0].text = Kills_Text

    set B[i][2][0].text = Devotion_Text

    //Set the icon and player name...

    call B[i].row[0].setDisplay(true, true)

    set I = B[i][0][1]

    set I.text = GetPlayerName(Player(i))

    set B[i][0][0].icon = GetRaceIcon(Player(i))

    if w < StringLength(GetPlayerName(Player(i))) then

        set w = StringLength(GetPlayerName(Player(i))) * PercChar + 0.025

    else

        set w = (StringLength(Player_Text)-10) * PercChar + 0.025

    endif

    set B[i].col[0].width = w

    //Set the kills

    set I = B[i][1][1]

    call I.setDisplay(true, false)

    set I.text = I2S(stats(i).kills)

    set B[i].col[1].width = 0.04

    set B[i][1][0].icon = KillsIcon

    //Set the Devotion

    set I = B[i][2][1]

    call I.setDisplay(true, false)

    set I.text = I2S(stats(i).devpoints)

    set B[i].col[2].width = 0.06

    set B[i][2][0].icon = DevotionIcon

    // set board visibility for the player

    set B[i].visible[Player(i)] = true

endfunction



private function FillObservers takes nothing returns nothing

    local real w = StringLength(Player_Text)-10

    local BoardItem I

    local integer j = 0

    set B[15] = Board.create()

    set B[15].title = Title

    set B[15].row.count = OBSROWCOUNT

    set B[15].col.count = 3

    set B[15][0][0].text = Player_Text

    set B[15][1][0].text = Kills_Text

    set B[15][2][0].text = Devotion_Text

    set B[15][3][0].text = "|CFFFFF799Buildings"

    set B[15][0][0].icon = PlayerIcon

    set B[15][1][0].icon = KillsIcon

    set B[15][2][0].icon = DevotionIcon

    set B[15][3][0].icon = BuildingsIcon

    loop

        exitwhen j > 11

        if IsPlayerInForce(Player(j), UserPlayers) then

            //Set the icon and player name...

            set I = B[15][0][stats(j).index]

            set I.text = GetPlayerName(Player(j))

            set I.icon = GetRaceIcon(Player(j))

            set I.color = ARGB.fromPlayer(Player(j))

            if w < StringLength(GetPlayerName(Player(j))) then

                set w = StringLength(GetPlayerName(Player(j))) * PercChar + 0.050

            else

                set w = (StringLength(Player_Text)-10) * PercChar + 0.050

            endif

            set B[15].col[0].width = w

            //Set the kills

            set I = B[15][1][stats(j).index]

            call I.setDisplay(true, false)

            set I.text = I2S(stats(j).kills)

            //Set the Devotion

            set I = B[15][2][stats(j).index]

            call I.setDisplay(true, false)

            set I.text = I2S(stats(j).devpoints)

            //Set the Buildings

            set I = B[15][3][stats(j).index]

            call I.setDisplay(true, false)

            set I.text = I2S(stats(j).buildings)

        endif

        set j = j + 1

    endloop

    call B[15].row[0].setDisplay(true, true)

    call B[15].col[0].setDisplay(true, true)

    set B[15].col[1].width = 0.04

    set B[15].col[2].width = 0.08

    set B[15].col[3].width = 0.06

endfunction



private function ObsVis takes nothing returns nothing

    // set board visibility for the observer player

    set B[15].visible[GetEnumPlayer()] = true

endfunction



private function Create_MultiBoard_Actions takes nothing returns nothing

    call ForForce(UserPlayers, function FillBoard)

    if HASOBSERVERS then

        call FillObservers()

        call ForForce(Observers, function ObsVis)

    endif

    call DestroyTimer(GetExpiredTimer())

endfunction



private function KillLeavingPlayer takes nothing returns nothing

    call GroupEnumUnitsOfPlayer(bj_lastCreatedGroup, GetTriggerPlayer(), Condition(function DestroyUnits))

endfunction



function UpdatePlayerMB takes player p returns nothing // Public function to update stat multiboards

    local integer i = GetPlayerId(p)

    set B[i][1][1].text = I2S(stats(i).kills)

    set B[i][2][1].text = I2S(stats(i).devpoints)

    if HASOBSERVERS then

        set B[15][1][stats(i).index].text = I2S(stats(i).kills)

        set B[15][2][stats(i).index].text = I2S(stats(i).devpoints)

        set B[15][3][stats(i).index].text = I2S(stats(i).buildings)

    endif

endfunction



function UpdateStats takes nothing returns nothing

    local integer i = 0

    if HASOBSERVERS then

        loop

            exitwhen i > 11

            if IsPlayerInForce(Player(i), UserPlayers) then

                call UpdatePlayerMB(Player(i))

            endif

            set i = i + 1

        endloop

    endif

endfunction



private function Conditions takes nothing returns boolean

    local unit u = GetTriggerUnit()

    local player p = GetOwningPlayer(u)

    if IsUnitType(u, UNIT_TYPE_STRUCTURE) == true and IsPlayerInForce(p, UserPlayers) then

        set stats(GetPlayerId(p)).buildings = GetPlayerStructureCount(p, true)

        if stats(GetPlayerId(p)).buildings < 1 then

            //******************************************

            //* Checks if the player has been defeated *

            //******************************************

            call GroupEnumUnitsOfPlayer(bj_lastCreatedGroup, p, Condition(function DestroyUnits))

            call B[GetPlayerId(p)].destroy()

            if HASOBSERVERS then

                set B[15][0][stats(GetPlayerId(p)).index].text = DefeatedColor + GetPlayerName(p)

            endif

        endif

    endif

    call UpdateStats()

    set u = null

    return false

endfunction



//===========================================================================

private function init takes nothing returns nothing

    local integer index = 0

    local integer i = 0

    local trigger t = CreateTrigger()

    //***********************************************************************

    //*Multiboard Creation

    call TimerStart(CreateTimer(), ElapsedTime, false, function Create_MultiBoard_Actions )

    //***********************************************************************

    //*Multiboard Update

    call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_CONSTRUCT_START )

    call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_DEATH )

    call TriggerAddCondition( t, Condition( function Conditions ) )

    set t = null

    set t = CreateTrigger()

    loop

        // Fills the userplayers player group...

        if GetPlayerSlotState(Player(index)) == PLAYER_SLOT_STATE_PLAYING and index < 12 then

            call ForceAddPlayer(UserPlayers, Player(index))

            set i = i + 1 // index for the observers list

            set stats(index).index = i

            call TriggerRegisterPlayerEvent(t, Player(index), EVENT_PLAYER_LEAVE)

        endif

        if IsPlayerObserver(Player(index)) or index == 15 then

            call ForceAddPlayer(Observers, Player(index))

            set HASOBSERVERS = true

        endif

        // end userplayers filling

        set index = index + 1

        exitwhen index == bj_MAX_PLAYER_SLOTS

    endloop

    call TriggerAddAction(t, function KillLeavingPlayer)

    set t = null

endfunction



endlibrary

//===========================================================================

// Trigger: Handle Counter

//===========================================================================

//TESH.scrollpos=87

//TESH.alwaysfold=0

//===========================================================================

//    A simple handle counter that shows:

//          * Maximum handles reached

//          * Elapsed seconds

//

//========== FOR VERSION 1.24+ ONLY ==========

//

//    The leaderboard can be accessed with

//          HandleCounter_LEADERBOARD

//    The clock (timer) can be accessed with

//          HandleCounter_CLOCK

//

//    This could be useful only if you'd like to see

//    if your map is leaking a lot of handles.

//    Otherwise it isn't really needed.

//

//    Requires a vJASS compiler to work.

//

//    To use: 

//          Create a trigger named HandleCounter,

//          convert to custom script and paste this.

//===========================================================================

library HandleCounter initializer Init 



//===========================================================================

// Configurables

//===========================================================================

globals

// Leaderboard title/name.

    private constant string TITLE = "Handle Counter"

// Text that represents the time.

    private constant string TIME_TEXT = "Elapsed Time:"

// Should the leaderboard show time as well? True or false.

    private constant boolean SHOW_TIME = true

// How often should the handle count update (of course this is not for the clock).

    private constant real UPDATE_PERIOD = 0.25

// Number of locations created for better counting result.

    private constant integer STACK_END_TRESHOLD = 15

    

// Player(0) = Player 1 (Red); Player(1) = Player 2 (Blue); etc.

    

// Player color of the maximum handles text.

    private constant player MAX = Player(9)

// Player color of the time text.

    private constant player TIME = Player(8)

    

    private boolean array SHOW

endglobals



//===========================================================================

// Do not edit bellow this point unless you know what you're doing.

//===========================================================================



globals

    public leaderboard LEADERBOARD = null 

    public timer CLOCK = null

    private integer CURRENT_HANDLE = 0

    private integer MAX_HANDLE = 0

    private integer SECONDS = 0

endglobals



private function UpdateTime takes nothing returns nothing

    set SECONDS = SECONDS + 1

    call LeaderboardSetItemLabel(LEADERBOARD, 1, TIME_TEXT)

    call LeaderboardSetItemValue(LEADERBOARD, 1, SECONDS)

endfunction

        

private function Callback takes nothing returns nothing

    local location array loc

    local integer a = 0

    local integer index 

    local integer prevIndex = 0

    local integer next = 0

    loop

        set loc[a] = Location(0., 0.)

        set index = GetHandleId(loc[a]) - 0x100000

        set a = a + 1

        if index == prevIndex + 1 then

            set next = next + 1

        else

            set next = 0

        endif

        set prevIndex = index

        exitwhen next >= STACK_END_TRESHOLD

    endloop

    call LeaderboardSetItemValue(LEADERBOARD, 0, index - a)

    loop

        set a = a - 1

        call RemoveLocation(loc[a])

        set loc[a] = null

        exitwhen a <= 0

    endloop

endfunction



private function Actions takes nothing returns nothing

    local timer tim = GetExpiredTimer()

    set LEADERBOARD = CreateLeaderboard()

    call LeaderboardSetLabel(LEADERBOARD, TITLE)

    call PlayerSetLeaderboard(GetLocalPlayer(), LEADERBOARD)

    call LeaderboardDisplay(LEADERBOARD, false)

    call TimerStart(tim, UPDATE_PERIOD, true, function Callback)

    call LeaderboardAddItem(LEADERBOARD, "Max Handles", 0, MAX)

    call LeaderboardSetSizeByItemCount(LEADERBOARD, 1)

    if SHOW_TIME then

        set CLOCK = CreateTimer()

        call TimerStart(CLOCK, 1., true, function UpdateTime)

        call LeaderboardAddItem(LEADERBOARD, "", 1, TIME)

        // Prevent leaderboard showing "1" during the first second.

        call LeaderboardSetItemLabel(LEADERBOARD, 1, TIME_TEXT)

        call LeaderboardSetItemValue(LEADERBOARD, 1, SECONDS)

        call LeaderboardSetSizeByItemCount(LEADERBOARD, 2)

    endif

    if IsPlayerObserver(GetLocalPlayer()) then

        call LeaderboardDisplay(LEADERBOARD, true)

    endif

    set tim = null

endfunction



private function Play takes nothing returns nothing

    set SHOW[GetPlayerId(GetTriggerPlayer())] = not SHOW[GetPlayerId(GetTriggerPlayer())]

    if GetLocalPlayer() == GetTriggerPlayer() then

        call LeaderboardDisplay(LEADERBOARD, SHOW[GetPlayerId(GetTriggerPlayer())])

    endif

endfunction 



private function Init takes nothing returns nothing

    local trigger t = CreateTrigger()

    local integer i = 0

    loop

        exitwhen i > 11

        if GetPlayerController(Player(i)) == MAP_CONTROL_USER and GetPlayerSlotState(Player(i)) == PLAYER_SLOT_STATE_PLAYING then

            call TriggerRegisterPlayerChatEvent(t, Player(i), "-handlecounter", true)

        endif

        set i = i+1

    endloop

    call TriggerAddAction(t, function Play)

    call TimerStart(CreateTimer() , 0., false, function Actions)

    set t = null

endfunction



endlibrary //===========================================================================

// Trigger: Devotion points

//

// requires RegisterAnyUnitEvent, Multiboard, UnitDamage

//===========================================================================

//TESH.scrollpos=19

//TESH.alwaysfold=0

library DevPoints initializer init requires RegisterAnyUnitEvent, Multiboard, UnitDamage



globals

	private constant integer  NagaSemiHero  = 'n012'

	private constant integer  DemonSemiHero = 'n015'

	private constant integer  MaxPoints     = 1000

	private constant string   Effect        = "Abilities\\Spells\\Other\\Awaken\\Awaken.mdl"

    private constant string   SoundPath     = "Sound\\Ambient\\DoodadEffect\\SargerasLaugh.wav"

    private          sound    Sound

    private          location L

endglobals



private function GetDevotionValue takes unit d returns integer

	// change this function in order to get the right value in devotion points for the dying unit.

	local real ishero = 1.

    if IsUnitType(d, UNIT_TYPE_HERO) == true then

        set ishero = 1.3

    endif

    return GetUnitFoodUsed(d) * 6 * R2I(GetUnitLevel(d) * ishero * GetRandomReal(0.8, 1.2))

endfunction



private function Conditions takes nothing returns boolean

    return IsPlayerInForce(GetOwningPlayer(GetKillingUnit()), UserPlayers) and IsPlayerInForce(GetOwningPlayer(GetDyingUnit()), UserPlayers) and GetOwningPlayer(GetKillingUnit()) != GetOwningPlayer(GetTriggerUnit()) and IsUnitType(GetDyingUnit(), UNIT_TYPE_SUMMONED) == false

endfunction



private function Actions takes nothing returns nothing

    local unit d = GetDyingUnit()

    local unit k = GetKillingUnit()

    local player pk = GetOwningPlayer(k)

    local integer c = GetDevotionValue(d)

    local unit sh

    local real kx = GetStartLocationX(GetPlayerStartLocation(pk))

    local real ky = GetStartLocationY(GetPlayerStartLocation(pk))

    call MoveLocation(L, kx, ky)

    set stats(GetPlayerId(pk)).devpoints = stats(GetPlayerId(pk)).devpoints + c

    set stats(GetPlayerId(pk)).kills = stats(GetPlayerId(pk)).kills + 1

    // Checks if it has to give a semi hero

    if stats(GetPlayerId(pk)).devpoints >= MaxPoints then

        if PlayerIsNaga(pk) then

            set sh = CreateUnit( pk, NagaSemiHero,kx, ky, bj_UNIT_FACING)

        else

            set sh = CreateUnit( pk, DemonSemiHero,kx, ky, bj_UNIT_FACING)

        endif

        call DestroyEffect(AddSpecialEffect(Effect, GetUnitX(sh), GetUnitY(sh)))

        call PlaySoundAtPointBJ( Sound, 100, L, 0 )

        call DisplayTextToPlayer( pk, 0, 0, "|CFFFFF200Your God Sargeras has blessed you with one of their favorite guardians.\nNow this|r " + GetUnitName(sh) + "|CFFFFF200 is yours to command.|r" )

        set stats(GetPlayerId(pk)).devpoints = stats(GetPlayerId(pk)).devpoints - MaxPoints 

    endif

    call UpdatePlayerMB(pk)

    set d = null

    set k = null

    set sh = null

endfunction



//===========================================================================

private function init takes nothing returns nothing

    call RegisterAnyUnitEvent( EVENT_PLAYER_UNIT_DEATH, function Conditions, function Actions )

    set Sound = CreateSound(SoundPath, false, true, false, 10,10, "")

    set L = Location(0,0)

endfunction



endlibrary

//===========================================================================

// Trigger: Pray for Gold

//

// requires RegisterAnyUnitEvent, Multiboard

//===========================================================================

//TESH.scrollpos=0

//TESH.alwaysfold=0

// Pray for gold ability

library PrayForGold initializer init requires RegisterAnyUnitEvent, Multiboard



globals

	private constant integer SpellID = 'A00H'

endglobals



// Pray for gold actions

private function Conditions takes nothing returns boolean

    local player p = GetOwningPlayer(GetTriggerUnit())

    if GetSpellAbilityId() == SpellID then

        if stats(GetPlayerId(p)).devpoints >= goldPayment then

            set stats(GetPlayerId(p)).devpoints = stats(GetPlayerId(p)).devpoints - goldPayment

            call SetPlayerState(p, PLAYER_STATE_RESOURCE_GOLD, GetPlayerState(p, PLAYER_STATE_RESOURCE_GOLD) + goldPayment)

            call UpdatePlayerMB(p)

        endif

    endif

    return false

endfunction



//===========================================================================

private function init takes nothing returns nothing

    call RegisterAnyUnitEvent( EVENT_PLAYER_UNIT_SPELL_CAST, function Conditions, null )

endfunction



endlibrary

//===========================================================================

// Trigger: Pray for Lumber

//

// requires RegisterAnyUnitEvent, Multiboard

//===========================================================================

//TESH.scrollpos=0

//TESH.alwaysfold=0

// Pray for lumber ability

library PrayForLumber initializer init requires RegisterAnyUnitEvent, Multiboard



globals

	private constant integer SpellID = 'A00J'

endglobals



// Pray for lumber actions

private function Conditions takes nothing returns boolean

    local player p = GetOwningPlayer(GetTriggerUnit())

    if GetSpellAbilityId() == SpellID then

        if stats(GetPlayerId(p)).devpoints >= lumberPayment then

            set stats(GetPlayerId(p)).devpoints = stats(GetPlayerId(p)).devpoints - lumberPayment

            call SetPlayerState(p, PLAYER_STATE_RESOURCE_LUMBER, GetPlayerState(p, PLAYER_STATE_RESOURCE_LUMBER) + lumberPayment)

            call UpdatePlayerMB(p)

        endif

    endif

    return false

endfunction



//===========================================================================

private function init takes nothing returns nothing

    call RegisterAnyUnitEvent( EVENT_PLAYER_UNIT_SPELL_CAST, function Conditions, null )

endfunction



endlibrary

//===========================================================================

// Trigger: Naga Ability

//

// requires TimedEffects

//===========================================================================

//TESH.scrollpos=0

//TESH.alwaysfold=0

library NagaGenAbility initializer init requires TimedEffects



globals

    private constant integer  Upgrade = 'R000'       // upgrade rawcode

    private constant integer  WaterZoneBuff = 'B00Q' // Item buff

    private constant real     Regen = 4.             // Regeneration per second

    private constant real     FXDur = 1.             // Effect duration

    private          rect     R                      // Whole map rect

    private          integer  array SpellID          // Abilities realted to Naga Ability

    private          string   FX

endglobals



private function HasAbil takes unit u returns boolean

    return GetUnitAbilityLevel(u, SpellID[0]) > 0 or GetUnitAbilityLevel(u, SpellID[1]) > 0

endfunction



private function IsOrganic takes nothing returns boolean

    local unit u = GetFilterUnit()

    // Added the condition for water item....

    if GetPlayerTechCount(GetOwningPlayer(u), Upgrade, true) > 0 and GetWidgetLife(u) > 0.405 and GetWidgetLife(u) < GetUnitState(u, UNIT_STATE_MAX_LIFE) and HasAbil(u) and GetUnitAbilityLevel(u, WaterZoneBuff) > 0 or (not IsTerrainPathable(GetUnitX(u), GetUnitY(u), PATHING_TYPE_FLOATABILITY)) then

        call SetWidgetLife(u, GetWidgetLife(u) + Regen * TEIndexer.period)

        call TEonUnit.Start( u, FX, "origin", FXDur)

    endif

    set u = null

    return false

endfunction



private function Actions takes nothing returns boolean

    call GroupEnumUnitsInRect(bj_lastCreatedGroup, R, Condition(function IsOrganic))

    return false

endfunction



//===========================================================================

private function init takes nothing returns nothing

    set R = GetWorldBounds()

    set SpellID[0] = 'A016'

    set SpellID[1] = 'A01A'

    set FX = GetAbilityEffectById(SpellID[0], EFFECT_TYPE_SPECIAL, 0)

    call TEIndexer.AddCode( function Actions )

endfunction



endlibrary

//===========================================================================

// Trigger: Poisoning Skin

//

// requires UnitDamage, TimedEffects, DataPreloader

//===========================================================================

//TESH.scrollpos=0

//TESH.alwaysfold=0

library PoisonSkin initializer init requires UnitDamage, TimedEffects, DataPreloader



globals

    private constant integer SpellID  = 'A01B'

    private constant integer Upgrade  = 'R005'

    private constant real    DamRate  = 2. // set the damage per second

    private constant real    Dur      = 5. // set the poisoning duration

    private          string  PoisonFX

endglobals



// In this function I've added a condition against inner fire, where if the demon Knight uses the spell over a unit with

// Poison Skin ability, then it will receive the damage, even if it's far away from the AOE... 

private function Conditions takes nothing returns boolean

    local unit u = GetTriggerUnit()

    local unit a = GetEventDamageSource()

    if GetEventDamage() > 0 and GetUnitAbilityLevel(u, SpellID) > 0 and GetPlayerTechCount(GetOwningPlayer(u), Upgrade, true) > 0 and IsUnitType(a, UNIT_TYPE_MELEE_ATTACKER) == true and GetUnitAbilityLevel(u, 'B00A') < 1 then

        call TEonUnit.Start(a, PoisonFX, "chest", Dur)

        call DOT.start(Dur, u, a, DamRate, false, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_POISON, WEAPON_TYPE_WHOKNOWS, true)

    endif

    set u = null

    set a = null

    return false

endfunction



//===========================================================================

private function init takes nothing returns nothing

    call AddDamageCondition( function Conditions )

    set PoisonFX = GetAbilityEffectById(SpellID, EFFECT_TYPE_SPECIAL, 0)

    call PreloadAbility(SpellID, "", false)

endfunction



endlibrary

//===========================================================================

// Trigger: Illusion

//

// requires Indexor2, MicroTable, UnitDamage, DataPreloader, LastCommand

//===========================================================================

//TESH.scrollpos=0

//TESH.alwaysfold=0

library Illusion initializer Init requires Indexor2, MicroTable, UnitDamage, DataPreloader, LastCommand, ProjSys



globals

	private constant integer  SpellID = 'A009'

	private constant integer  GhostID = 'n00H'

	private constant real     Range   = 400.

	private constant real     Dur     = 0.5

    private constant real     dist    = 116.

	private constant key      LINK

    private          integer  ATTACK

    private          integer  MOVE

    private          string   FX

endglobals



private struct link extends array

    unit b

    boolean on

    

    implement Alloc

    

    method destroy takes nothing returns nothing

        set .b = null

        set .on = false

        call .deallocate()

    endmethod

    

    static method Set takes unit a, unit b returns nothing

        local link L = thistype.allocate()

        set L.b = b

        set L.on = true

        call StoreData(a, LINK, integer(L))

    endmethod

    

    static method Get takes unit a returns unit

        return thistype(GetData(a, LINK)).b

    endmethod

    

    static method Break takes unit a returns nothing

        if thistype(GetData(a, LINK)).on then

            call ClearValue(a, LINK)

            call thistype(GetData(a, LINK)).destroy()

        endif

    endmethod

endstruct



private function DoEffect takes nothing returns nothing

    local unit a = GetEnumUnit()

    local unit b = link.Get(a)

    if GetWidgetLife(a) > 0.405 then

        if GetCurrentOrderId(a) != ATTACK or GetCurrentOrderTarget(a) != b then

            call IssueTargetOrderById(a, ATTACK, b)

        endif

    else

        call SetUnitExploded(b, true)

        call KillUnit(b) 

        call link.Break(a)

    endif

    set a = null

    set b = null

endfunction



private struct IllusionData extends array

	integer Order

	integer Lvl

	group Egroup

    group Igroup

	unit caster

    effect fog

    private real tick

    

    implement AllocLoop

    

	static method create takes unit c, integer l, real x, real y returns thistype

		local thistype Ida = thistype.allocate()

		set Ida.Order = GetUnitCurrentOrder(c)

		set Ida.Lvl = l

		set Ida.caster = c

        set Ida.tick = 0.

        if Ida.Egroup == null then

            set Ida.Egroup = CreateGroup()

		endif

        if Ida.Igroup == null then

            set Ida.Igroup = CreateGroup()

		endif

        set Ida.fog = AddSpecialEffect(FX, x, y)

		return Ida

	endmethod

	

    private static method Kill takes nothing returns nothing

        local unit a = GetEnumUnit()

        call DestroyEffect(AddSpellEffectById(GhostID, EFFECT_TYPE_SPECIAL, GetUnitX(a), GetUnitY(a)))

        call RemoveUnit(a)

        set a = null

    endmethod

    

	method destroy takes nothing returns nothing

		call DestroyEffect(.fog)

        call GroupClear(.Egroup)

        call ForGroup(.Igroup, function thistype.Kill)

        call GroupClear(.Igroup)

		set .caster = null

        set .fog = null

        call .deallocate()

	endmethod

    

    static method Update takes nothing returns boolean

        implement loop

        if GetWidgetLife(.caster) < 0.405 or GetUnitCurrentOrder(.caster) != .Order then

            call .destroy()

        else

            set .tick = .tick + HeroIndexer.period

            if .tick > Dur then

                call ForGroup(.Egroup, function DoEffect)

                set .tick = 0.

            endif

        endif

        implement endloop

        return false

    endmethod

endstruct



globals

    private IllusionData U

endglobals



private function GetEnemies takes nothing returns boolean

    return IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(U.caster)) and GetWidgetLife(GetFilterUnit()) > 0.405

endfunction



private function SetIllusion takes nothing returns nothing

    local unit u = GetEnumUnit()

    local real x = GetUnitX(u) + dist * Cos(GetUnitFacing(u) * bj_DEGTORAD)

    local real y = GetUnitY(u) + dist * Sin(GetUnitFacing(u) * bj_DEGTORAD)

    local unit i = CreateDummy(GetOwningPlayer(U.caster), GhostID, x, y, GetUnitFacing(u) + 180.)

    call UnitAddAbility(i, 'Aloc')

    call UnitRemoveAbility(i, 'Aloc')

    call IssueTargetOrderById(u, ATTACK, i)

    call link.Set(u, i)

    call GroupAddUnit(U.Igroup, i)

    set u = null

    set i = null

endfunction



private function Conditions takes nothing returns boolean

    local real x = GetSpellTargetX()

    local real y = GetSpellTargetY()

    local unit u = GetTriggerUnit()

    if GetSpellAbilityId() == SpellID then

        set U = IllusionData.create(u, GetUnitAbilityLevel(u, SpellID), x, y)

        call GroupEnumUnitsInRange(U.Egroup, x, y, Range, Condition(function GetEnemies))

        call ForGroup(U.Egroup, function SetIllusion)

    endif

    set u = null

    return false

endfunction



private function Init takes nothing returns nothing

    call HeroIndexer.AddCode(function IllusionData.Update)

    call RegisterAnyUnitEvent( EVENT_PLAYER_UNIT_SPELL_EFFECT, function Conditions, null )

    set FX = GetAbilityEffectById(SpellID, EFFECT_TYPE_SPECIAL, 0)

    call PreloadAbility(SpellID, "blizzard", false)

    call Preload(GetAbilityEffectById(GhostID, EFFECT_TYPE_SPECIAL, 0))

    set ATTACK = OrderId("attack")

    set MOVE = OrderId("move")

endfunction



endlibrary



//===========================================================================

// Trigger: SoulControl

//

// requires Indexor2, LastCommand

//===========================================================================

//TESH.scrollpos=0

//TESH.alwaysfold=0

library SoulControl initializer init requires Indexor2, LastCommand



globals

	private constant integer  SpellID = 'A008' //is the ability code of the spell. This spell is based on Cripple

	private constant integer  BuffID  = 'B00E' //is the buff of the spell

	private constant real     Radius  = 500.   //AOE of the spell

	private constant real     Dur     = 0.1   //Timer period control

    

    private          integer  MOVE

    private          integer  ATTACK

endglobals



private function GetEnemy takes nothing returns boolean

    return GetFilterUnit() != bj_lastCreatedUnit and IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE) == false and not IsUnitType(GetFilterUnit(), UNIT_TYPE_DEAD) and IsUnitAlly(GetFilterUnit(), GetOwningPlayer(bj_lastCreatedUnit))

endfunction



private function SelectEnemy takes unit c returns unit

    set bj_lastCreatedUnit = c

    call GroupEnumUnitsInRange(bj_lastCreatedGroup, GetUnitX(c), GetUnitY(c), Radius, Condition(function GetEnemy))

    set bj_lastCreatedUnit = FirstOfGroup(bj_lastCreatedGroup)

    call GroupClear(bj_lastCreatedGroup)

    return bj_lastCreatedUnit

endfunction



private struct SCData extends array

	static unit T    

    unit caster

	unit target

	unit enemy

    integer order

    real tick

    

    implement AllocLoop

    

    static method Set takes unit caster, unit target returns thistype

        local thistype SC = thistype.allocate()

        set SC.caster = caster

        set SC.target = target

        set SC.enemy = SelectEnemy(SC.target)

        set SC.tick = 0.

        set caster = null

        set target = null

        return SC

    endmethod

    

    static method Update takes nothing returns boolean

        implement loop

        set .tick = .tick + HeroIndexer.period

        if .tick > Dur then

            set .tick = 0.

            if IsUnitType(.target, UNIT_TYPE_SLEEPING) == true then // wake up!!!!

                call UnitDamageTarget(.caster, .target, 0.01, false, false, null, null, null)

            endif

            if GetUnitAbilityLevel(.target, BuffID) > 0 then

                if IsUnitType(.enemy, UNIT_TYPE_DEAD) and .enemy != .caster then

                    set .enemy = SelectEnemy(.target)

                    if .enemy == null then // this condition happens when the SelectEnemy can't find anyone near

                        set .enemy = .caster

                        set .order = MOVE

                    endif

                endif

                if GetCurrentOrderId(.target) != .order or GetCurrentOrderTarget(.target) != .enemy then

                    call IssueTargetOrderById(.target, .order, .enemy)

                endif

                call SetUnitState(.caster, UNIT_STATE_MANA, GetUnitState(.caster, UNIT_STATE_MANA) - I2R(GetUnitLevel(.target)) * Dur)

            else

                call IssueImmediateOrder(.target, "stop")

                set .caster = null

                set .target = null

                set .enemy  = null

                call .deallocate()

            endif

        endif

        implement endloop

        return false 

    endmethod

endstruct



private function Conditions takes nothing returns boolean

    local SCData SC

    if GetSpellAbilityId() == SpellID then

        set SC = SCData.Set(GetTriggerUnit(), GetSpellTargetUnit())

        if SC.enemy != null then

            set SC.order = ATTACK

        else

            set SC.enemy = SC.caster

            set SC.order = MOVE

        endif

        call IssueTargetOrderById(SC.target, SC.order, SC.enemy)

    endif

    return false

endfunction



//===========================================================================

private function init takes nothing returns nothing

    call HeroIndexer.AddCode(function SCData.Update)

	call RegisterAnyUnitEvent( EVENT_PLAYER_UNIT_SPELL_EFFECT, function Conditions, null )

    set MOVE = OrderId("move")

    set ATTACK = OrderId("attack")

endfunction



endlibrary



//===========================================================================

// Trigger: SoulThirst

//

// requires TimedEffects, DataPreloader

//===========================================================================

//TESH.scrollpos=0

//TESH.alwaysfold=0

library SoulThirst initializer init requires TimedEffects, DataPreloader



globals

    private constant integer SpellID = 'A00A'

	private constant integer BuffID  = 'B00X'

    private constant integer DummyAb = 'A02Y' //Dummy missile ability based on Death Coil

    private constant string  Order   = "acidbomb"

    private constant real    AOE     = 900.

    private constant real    dt      = 1. // timerate

endglobals



private constant function ManaGained takes integer level returns real

    return 5. + 3. * (level - 1)

endfunction



private struct data extends array

    timer t

    unit c

    static integer count = 1

    

    private static method GetBuffed takes nothing returns boolean

        return GetUnitAbilityLevel(GetFilterUnit(), BuffID) > 0

    endmethod

    

    private static method PickRandomUnit takes nothing returns nothing

        set bj_groupRandomConsidered = bj_groupRandomConsidered + 1

        if GetRandomInt(1,bj_groupRandomConsidered) == 1 then

            set bj_groupRandomCurrentPick = GetEnumUnit()

        endif

    endmethod



    private static method Loop takes nothing returns nothing

        local data D = data( GetData(GetExpiredTimer(), SpellID) )

        local real mg

        local boolean a = GetWidgetLife(D.c) < GetUnitState(D.c, UNIT_STATE_MAX_LIFE)

        local boolean b = false 

        local boolean c = false

        if a or GetUnitState(D.c, UNIT_STATE_MANA) < GetUnitState(D.c, UNIT_STATE_MAX_MANA) then

            call GroupEnumUnitsInRange(bj_lastCreatedGroup, GetUnitX(D.c), GetUnitY(D.c), AOE, Condition(function data.GetBuffed))

            set bj_groupRandomConsidered = 0

            set bj_groupRandomCurrentPick = null

            call ForGroup(bj_lastCreatedGroup, function data.PickRandomUnit)

            if bj_groupRandomCurrentPick != null then

                set mg = ManaGained(GetUnitAbilityLevel(D.c, SpellID))

                if GetUnitState(bj_groupRandomCurrentPick, UNIT_STATE_MAX_MANA) > 0 and GetUnitState(bj_groupRandomCurrentPick, UNIT_STATE_MANA) > mg then

                    call SetUnitState(bj_groupRandomCurrentPick, UNIT_STATE_MANA, GetUnitState(bj_groupRandomCurrentPick, UNIT_STATE_MANA) - mg)

                    call SetUnitState(D.c, UNIT_STATE_MANA, GetUnitState(D.c, UNIT_STATE_MANA) + mg)

                    set b = true

                endif

                if a and GetWidgetLife(bj_groupRandomCurrentPick) > mg then

                    call DoSafeDamage(D.c, bj_groupRandomCurrentPick, mg, false, true, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)

                    call SetWidgetLife(D.c, GetWidgetLife(D.c) + mg)

                    set c = true

                endif

                if b or c then

                    call DummyCastTarget(bj_groupRandomCurrentPick, D.c, DummyAb, GetUnitAbilityLevel(D.c, SpellID), Order)

                endif

            endif

        endif

        call GroupClear(bj_lastCreatedGroup)

    endmethod

    

    static method Start takes unit c returns nothing

        local thistype D = thistype(thistype.count)

        set thistype.count = thistype.count + 1

        set D.t = CreateTimer()

        set D.c = c

        call StoreData(D.t, SpellID, integer(D))

        call StoreData(c, SpellID, integer(D))

        call TimerStart(D.t, dt, true, function data.Loop)

        set c = null

    endmethod

    

    static method Pause takes nothing returns boolean

        if IsUnitType(GetTriggerUnit(), UNIT_TYPE_HERO) == true and GetUnitAbilityLevel(GetTriggerUnit(), SpellID) > 0 then

            call PauseTimer(data(GetData(GetTriggerUnit(), SpellID)).t)

        endif

        return false

    endmethod

    

    static method Restart takes nothing returns boolean

        if IsUnitType(GetTriggerUnit(), UNIT_TYPE_HERO) == true and GetUnitAbilityLevel(GetTriggerUnit(), SpellID) > 0 then

            call TimerStart(data(GetData(GetTriggerUnit(), SpellID)).t, dt, true, function data.Loop)

        endif

        return false

    endmethod

endstruct



private function Conditions takes nothing returns boolean

    if GetLearnedSkill() == SpellID and GetLearnedSkillLevel() == 1 then

        call data.Start(GetTriggerUnit())

    endif

    return false

endfunction



//===========================================================================

private function init takes nothing returns nothing

    call RegisterAnyUnitEvent( EVENT_PLAYER_HERO_SKILL, function Conditions, null )

    call RegisterAnyUnitEvent( EVENT_PLAYER_UNIT_DEATH, function data.Pause, null )

    call RegisterAnyUnitEvent( EVENT_PLAYER_HERO_REVIVE_FINISH, function data.Restart, null )

    call PreloadAbility(SpellID, Order, false)

endfunction



endlibrary//===========================================================================

// Trigger: Betrayal

//

// requires RegisterAnyUnitEvent, DataPreloader

//===========================================================================

//TESH.scrollpos=12

//TESH.alwaysfold=0

library Betrayal initializer init requires RegisterAnyUnitEvent, DataPreloader



globals

	private constant integer  SpellID            = 'A00B'

	private constant real     AOE                = 400.

	private constant real     Betrayers_Duration = 120.

    private constant integer  Buff               = 0 // this buff is used in the timed life UI

    

	private          string   SpecialEffect

    private          real     LifeGained = 0.

    private          integer  counter = 0

endglobals



private constant function Betrayers takes integer level returns integer

    return 3 + level

endfunction



private function Traitor_Conditions takes nothing returns boolean

    local unit u = GetFilterUnit()

    if u != bj_lastCreatedUnit and GetWidgetLife(u) > 0.405 and IsUnitType(u, UNIT_TYPE_STRUCTURE) == false and IsUnitType(u, UNIT_TYPE_HERO) == false and GetPlayerId(GetOwningPlayer(u)) <= 12 and IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(bj_lastCreatedUnit)) and IsUnitType(u, UNIT_TYPE_FLYING) == false then

        if counter < Betrayers(GetUnitAbilityLevel(bj_lastCreatedUnit, SpellID)) then

            call SetUnitUseFood(u, false)

            call DestroyEffect(AddSpecialEffect( SpecialEffect, GetUnitX(u), GetUnitY(u) ))

            call SetUnitOwner( u, GetOwningPlayer(bj_lastCreatedUnit), true )

            call UnitApplyTimedLife( u, Buff, Betrayers_Duration)

            call UnitAddType( u, UNIT_TYPE_SUMMONED )

            call SetWidgetLife( u, GetWidgetLife(u) / 2. )

            set LifeGained = LifeGained + GetWidgetLife(u)

            set counter = counter + 1

        endif

    endif

    set u = null

    return false

endfunction



private function Conditions takes nothing returns boolean

    if GetSpellAbilityId() == SpellID then

        set bj_lastCreatedUnit = GetTriggerUnit()

        set LifeGained = 0.

        set counter = 0

        call GroupEnumUnitsInRange(bj_lastCreatedGroup, GetUnitX(bj_lastCreatedUnit), GetUnitY(bj_lastCreatedUnit), AOE, Condition(function Traitor_Conditions))

        call SetWidgetLife(bj_lastCreatedUnit, GetWidgetLife(bj_lastCreatedUnit) + LifeGained)

        set bj_lastCreatedUnit = null

    endif

    return false

endfunction



//===========================================================================

private function init takes nothing returns nothing

    call RegisterAnyUnitEvent( EVENT_PLAYER_UNIT_SPELL_EFFECT, function Conditions, null )

    set SpecialEffect = GetAbilityEffectById(SpellID, EFFECT_TYPE_SPECIAL,0)

    call PreloadAbility(SpellID, "stomp", false)

endfunction



endlibrary

//===========================================================================

// Trigger: WaterBurst

//

// requires Indexor2, TimedEffects, DummyCast, DataPreloader

//===========================================================================

//TESH.scrollpos=0

//TESH.alwaysfold=0

library WaterBurst initializer init requires Indexor2, TimedEffects, DummyCast, DataPreloader



globals

	private constant integer  SpellID       = 'A002' // Dummy Ability Rawcode. Spell based on SHOCKWAVE

    private constant integer  DummyAb       = 'A030' // Splash ability

    private constant string   DummyOr       = "stomp" // the dummy order

	private constant real     Distance      = 800.   // Distance where the spell has effect

	private constant integer  Steps         = 15     // How many water burst happens

	private constant real     Initial_width = 100.   // Initial range

	private constant real     Final_width   = 1000.  // Final range

	private constant real     MaxRange      = 350.   // Range where each burst has min effect

	private constant real     Dur            = 0.1    // returns the timer value



    private          real     wbx           = 0.

    private          real     wby           = 0.

endglobals



private constant function MaxDamage takes integer level returns real

    // Max Damage dealt to units

    return 30. + 5.5 * level * (level - 1)

endfunction



private function GetFX takes integer i returns string

    // it must be between 0 and 3

    return GetAbilityEffectById(SpellID, EFFECT_TYPE_SPECIAL, i)

endfunction



private function a1x takes real a, real alpha returns real

    return a * Cos(alpha)

endfunction



private function a1y takes real a, real alpha returns real

    return a * Sin(alpha)

endfunction



private function c1x takes real ax, real cy, real alpha returns real

    return a1x(ax,alpha) + cy * Cos(alpha + bj_PI * 0.5)

endfunction

                                                                                         

private function c1y takes real ay, real cy, real alpha returns real

    return a1y(ay,alpha) + cy * Sin(alpha + bj_PI * 0.5)

endfunction



private struct WBData extends array

    static thistype D

	unit caster

	real alpha

	real dr

	real width

	real ang

    group casted

    real tick

    player p

	

    implement AllocLoop

    

	static method create takes unit c returns WBData

		local thistype wb = thistype.allocate()

		set wb.caster = c

		set wb.alpha = GetUnitFacing(c) * bj_DEGTORAD

		set wb.p = GetOwningPlayer(c) 

        if wb.casted == null then

            set wb.casted = CreateGroup()

        endif

        set wb.dr = 0.

        set wb.width = Initial_width

        set wb.ang = 0.

        set wb.tick = 0.

        set c = null

		return wb

	endmethod

	

	method destroy takes nothing returns nothing

		set .caster = null

        call GroupClear(.casted)

        call .deallocate()

	endmethod

    

    private static method GetUnits takes nothing returns boolean

        local unit u = GetFilterUnit()

        local integer l = GetUnitAbilityLevel(thistype.D.caster, SpellID)

        local real m = - MaxDamage(l) / MaxRange

        local real dx = wbx - GetUnitX(u)

        local real dy = wby - GetUnitY(u)

        local real dist = SquareRoot(dx * dx + dy * dy)

        local real d = m * dist + MaxDamage(l)

        local unit v = null

        if GetWidgetLife( u ) > 0.405 and IsUnitEnemy(u, GetOwningPlayer(thistype.D.caster)) and IsUnitType(u, UNIT_TYPE_STRUCTURE) == false and IsUnitType(u, UNIT_TYPE_FLYING) == false then

            if GetWidgetLife(thistype.D.caster) > 0.405 then

                set v = thistype.D.caster

            else

                call SetUnitOwner(DummyCast_GetDummy(), thistype.D.p, false)

                set v = DummyCast_GetDummy()

            endif

            call UnitDamageTarget(v, u, d, true, false, ATTACK_TYPE_PIERCE, DAMAGE_TYPE_COLD, WEAPON_TYPE_WHOKNOWS)

            set v = null

            if d > 0.5 * MaxDamage(l) and not IsUnitInGroup(u, thistype.D.casted) then

                call DummyCastOnTarget(thistype.D.caster, u, DummyAb, 1, DummyOr, true)

                call GroupAddUnit(thistype.D.casted, u)

            endif

        endif

        set u = null

        return false

    endmethod

    

    static method Update takes nothing returns boolean

        local real m = (Final_width - Initial_width) / Distance

        local real Ampl 

        implement loop

        set Ampl = .width + m

        set .dr = .dr + (Distance / Steps)

        set .tick = .tick + HeroIndexer.period

        if .tick > Dur then

            set .tick = 0.

            if .dr < Distance then

                set .width = Ampl

                set .ang = .ang + (2 * bj_PI / Steps)

                set Ampl = GetRandomReal(0.5 * Ampl, 2. * Ampl)

                set wbx = GetUnitX(.caster) + c1x(.dr, Ampl * Sin(.ang), .alpha)

                set wby = GetUnitY(.caster) + c1y(.dr, Ampl * Sin(.ang), .alpha)

                call TEffect.Start( AddSpellEffectById(SpellID, EFFECT_TYPE_SPECIAL, wbx, wby), Dur )

                if IsTerrainPathable(wbx, wby, PATHING_TYPE_FLOATABILITY) then

                    call DestroyEffect(AddSpecialEffect(GetFX(2),wbx, wby))

                else

                    call DestroyEffect(AddSpecialEffect(GetFX(3),wbx, wby))

                endif

                set thistype.D = this

                call GroupEnumUnitsInRange(bj_lastCreatedGroup, wbx, wby, MaxRange, Condition(function thistype.GetUnits))

            else

                call .destroy()

            endif

        endif

        implement endloop

        return false

    endmethod

endstruct



private function Conditions takes nothing returns boolean

    if GetSpellAbilityId() == SpellID then

        call WBData.create(GetTriggerUnit())

    endif

    return false

endfunction



//===========================================================================

private function init takes nothing returns nothing

    call HeroIndexer.AddCode(function WBData.Update)

    call RegisterAnyUnitEvent( EVENT_PLAYER_UNIT_SPELL_EFFECT, function Conditions, null )

    call PreloadAbility(SpellID, "shockwave", false)

    call PreloadAbility(DummyAb, DummyOr, false)

endfunction



endlibrary//===========================================================================

// Trigger: CrushingTide

//

// requires Alloc, ProjSys, MicroTable, UnitDamage, SpellBlocker

//===========================================================================

//TESH.scrollpos=0

//TESH.alwaysfold=0

library CrushingTide initializer init requires Alloc, ProjSys, MicroTable, UnitDamage, SpellBlocker



globals

	private constant integer  SpellID    = 'A001'

	private constant real     Speed      = 1050.

	private constant real     Range      = 116.

	private constant real     TideHeight = 250. // Tide height

	private constant real     DistExp    = 500. // Distance that the enemies will be knockbacked

	private constant real     ConeAngle  = bj_PI / 2.

endglobals



private struct CTData extends array

    effect FX

    boolean on

    

    implement Alloc

    

	static method create takes unit c returns CTData

		local CTData CT = CTData.allocate()

		set CT.FX = AddSpecialEffectTarget(GetAbilityEffectById(SpellID, EFFECT_TYPE_SPECIAL, 1), c, "origin")

        set CT.on = true

		return CT

	endmethod

	

	method destroy takes nothing returns nothing

		call DestroyEffect(.FX)

        set .FX = null

        set .on = false

        call .deallocate()

	endmethod

endstruct



private constant function GetDamage takes integer level returns real

	return 60. + 40. * (level - 1)

endfunction



private function GetEnemies takes nothing returns boolean

    local unit u = GetFilterUnit()

    if not IsUnitProjectile(u) and IsUnitType(u, UNIT_TYPE_FLYING) == false and IsUnitType(u, UNIT_TYPE_STRUCTURE) == false and GetWidgetLife(u) > 0.405 and IsUnitEnemy(u, GetOwningPlayer(bj_lastCreatedUnit)) then

        call UnitDamageTarget(bj_lastCreatedUnit, u, bj_randomSubGroupChance, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)

        call KnockBack(u, DistExp, GetUnitsAngle(bj_lastCreatedUnit, u), 0., Speed, null, null, true)

    endif

    set u = null

    return false

endfunction



// functions used by the Projectile

private function Start takes nothing returns boolean

    local CTData CT = CTData.create(GetUnitProjectile())

    call StoreData(GetUnitProjectile(), SpellID, integer(CT))

    call SetUnitSpellInvulnerable(GetUnitProjectile(), true)

    return false

endfunction



private function Loop takes nothing returns boolean

	local Projectile p = GetMovingProjectile()

    set bj_randomSubGroupChance = GetDamage(GetUnitAbilityLevel(p.p, SpellID))

	set bj_lastCreatedUnit = p.p

	call GroupEnumUnitsInRange(bj_lastCreatedGroup, GetUnitX(p.p), GetUnitY(p.p), Range, Condition(function GetEnemies))

    return false

endfunction



private function EndP takes nothing returns boolean

    local CTData CT = CTData( GetData(GetUnitProjectile(), SpellID) )

    if CT.on then

        call CT.destroy()

    endif

    call SetUnitSpellInvulnerable(GetUnitProjectile(), false)

    call ClearValue(GetUnitProjectile(), SpellID)

    return false

endfunction





private function Conditions takes nothing returns boolean

    return GetSpellAbilityId() == SpellID

endfunction



private function Actions takes nothing returns nothing

	local unit c = GetTriggerUnit()

    local location P = GetSpellTargetLoc()

	local real px

	local real py

    local real tm

    local vector pi = vector.create(GetUnitX(c), GetUnitY(c), 0.)

    local vector pf

    local vector vi

    local vector vf

    local Projectile PR

	if P != null then

        set px = GetLocationX(P)

        set py = GetLocationY(P)

        call RemoveLocation(P)

        set P = null

    else

        set px = GetUnitX(c) + DistExp * Cos(GetUnitFacing(c) * bj_DEGTORAD)

        set py = GetUnitY(c) + DistExp * Sin(GetUnitFacing(c) * bj_DEGTORAD)

    endif

    set tm = Dist(GetUnitX(c), GetUnitY(c), px, py) / Speed

    set pf = vector.create(px, py, 0.)

    set vi = vector.create(Speed, GetUnitFacing(c) * bj_DEGTORAD, GetParabolicAngle(TideHeight, tm * Speed))

    set vf = vector.create(vi.x, vi.y, -vi.z)

    set PR = Projectile.createSpherical(c, pi, pf, vi, vf, tm, true, true)

    call PR.SetStartCode(function Start)

    call PR.SetMoveCode(function Loop)

    call PR.SetEndCode(function EndP)

    set c = null

endfunction



//===========================================================================

private function init takes nothing returns nothing

    call RegisterAnyUnitEvent( EVENT_PLAYER_UNIT_SPELL_EFFECT, function Conditions, function Actions )

endfunction



endlibrary//===========================================================================

// Trigger: Freeze

//

// requires Indexor2, RegisterAnyUnitEvent, SpellBlocker

//===========================================================================

//TESH.scrollpos=24

//TESH.alwaysfold=0

library Freeze initializer init requires Indexor2, RegisterAnyUnitEvent, SpellBlocker 



globals

	private constant integer SpellID         = 'A003'

	private constant integer SpellBuffAir    = 'B010'

	private constant integer SpellBuffGround = 'B011'

    private constant real    dt              = 0.1

endglobals



private function GetBuff takes unit t returns integer

    if IsUnitType(t, UNIT_TYPE_FLYING) == true then

        return SpellBuffAir

    else

        return SpellBuffGround

    endif

endfunction



private struct FreezeData extends array

	unit target

	boolean hasbuff

    real tick

    

    implement AllocLoop

    

    static method Update takes nothing returns boolean

        implement loop

        set .tick = .tick + HeroIndexer.period

        if .tick > dt then

            set .tick = 0.

            call IssueImmediateOrderById(.target, 851973) //Stunned order

            if (GetUnitAbilityLevel(.target, SpellBuffAir) > 0 or GetUnitAbilityLevel(.target, SpellBuffGround) > 0) and not .hasbuff then      

                set .hasbuff = true

                call UnitAddAbility(.target, 'Abun')

                call SetUnitTimeScale(.target, 0.)

                call SetUnitVertexColor(.target, 0, 134, 249, 255)

            elseif GetUnitAbilityLevel(.target, GetBuff(.target)) < 1 and .hasbuff then

                call SetUnitTimeScale(.target, 1.)

                call SetUnitVertexColor(.target, 255, 255, 255, 255)

                call UnitRemoveAbility(.target, 'Abun')

                set .target = null

                call .deallocate()

            endif

        endif

        implement endloop

        return false

    endmethod

    

    static method create takes unit u returns thistype

        local thistype F = thistype.allocate()

        set F.target = u

        set F.hasbuff = false

        set F.tick = 0.

        set u = null

        return F

    endmethod

endstruct



private function Conditions takes nothing returns boolean

    if GetSpellAbilityId() == SpellID then

        call FreezeData.create(GetSpellTargetUnit())

    endif

    return false

endfunction



//===========================================================================

private function init takes nothing returns nothing

    call HeroIndexer.AddCode(function FreezeData.Update)

    call RegisterAnyUnitEvent( EVENT_PLAYER_UNIT_SPELL_EFFECT, function Conditions, null )

    call AddSpellBlocker(SpellBuffAir)

    call AddSpellBlocker(SpellBuffGround)

endfunction



endlibrary//===========================================================================

// Trigger: Lightning Vortex

//

// requires TimedEffects, UnitDamage

//===========================================================================

//TESH.scrollpos=0

//TESH.alwaysfold=0

library LightningVortex initializer init requires TimedEffects, UnitDamage



globals

    private constant integer SpellID = 'A005'

    private constant integer DummyAb = 'A00P'

    private constant real    Radius  = 500.

    private constant string  Order   = "chainlightning"

endglobals



private constant function Dam takes integer level returns real

    return 65. + 30. * (level - 1)

endfunction



private function IsEnemy takes nothing returns boolean

    return GetWidgetLife(GetFilterUnit()) > 0.405 and IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(bj_groupRandomCurrentPick)) and IsUnitType(GetFilterUnit(), UNIT_TYPE_MECHANICAL) == false

endfunction



private function DoEffect takes nothing returns nothing

    call DummyCastOnTarget(bj_groupRandomCurrentPick, GetEnumUnit(), DummyAb, GetUnitAbilityLevel(bj_groupRandomCurrentPick, SpellID), Order, false)

endfunction



private function Conditions takes nothing returns boolean

    local unit d = GetSpellTargetUnit()

    if GetSpellAbilityId() == SpellID then

        set bj_groupRandomCurrentPick = GetTriggerUnit()

        call GroupEnumUnitsInRangeCounted(bj_lastCreatedGroup, GetUnitX(d), GetUnitY(d), Radius, Condition(function IsEnemy), 4)

        call ForGroup(bj_lastCreatedGroup, function DoEffect)

        call UnitDamageTarget(bj_groupRandomCurrentPick, d, Dam(GetUnitAbilityLevel(bj_groupRandomCurrentPick, SpellID)), true, true, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_UNIVERSAL, WEAPON_TYPE_WHOKNOWS)

        call GroupClear(bj_lastCreatedGroup)

    endif

    set d = null

    return false

endfunction



//===========================================================================

private function init takes nothing returns nothing

    call RegisterAnyUnitEvent( EVENT_PLAYER_UNIT_SPELL_EFFECT, function Conditions, null )

endfunction



endlibrary

//===========================================================================

// Trigger: LoyaltyandSacrifice

//

// requires Indexor2, TimedEffects

//===========================================================================

//TESH.scrollpos=0

//TESH.alwaysfold=0

library LoyAndSacr initializer init requires Indexor2, TimedEffects



globals

	private constant integer SpellID        = 'A006'

	private constant integer BuffID         = 'B009'

	private constant real    Range          = 1000.

	private constant real    HealEffectDur  = 1.

	private constant real    dt             = 0.1	

	private          string  TargetEffect

	private          string  HealEffect

	private          string  DyingEffect

endglobals



private constant function LifeGained takes integer level returns real

    return 0.2 + 0.2 * (level - 1)

endfunction



private struct LandS extends array

    unit caster

	unit target

	real tl

	effect weapon // effect for the weapon

	boolean hasbuff

    real tick

    

    implement AllocLoop

    

	static method create takes unit c, unit t returns LandS

		local LandS LS = LandS.allocate()

		set LS.caster = c

		set LS.target = t

		set LS.tl = GetUnitState(t, UNIT_STATE_MAX_LIFE) * LifeGained(GetUnitAbilityLevel(c, SpellID))

        set LS.hasbuff = false

        call StoreData(t, SpellID, integer(LS))

		return LS

	endmethod

	

	method destroy takes nothing returns nothing

        call ClearValue(.target, SpellID)

        call DestroyEffect(.weapon)

		set .caster = null

		set .target = null

		set .weapon = null

        call .deallocate()

	endmethod

	

	method addLightning takes nothing returns nothing

		set .weapon = AddSpecialEffectTarget(TargetEffect, .target, "weapon")

	endmethod

    

    static method Update takes nothing returns boolean

        implement loop

        set .tick = .tick + HeroIndexer.period

        if .tick > dt then

            set .tick = 0.

            if not .hasbuff and GetUnitAbilityLevel(.target, BuffID) > 0 then

                set .hasbuff = true

                call .addLightning()

            endif

            if (.hasbuff and not IsUnitInRange(.target, .caster, Range)) or GetWidgetLife(.caster) < 0.405 then

                call UnitRemoveAbility(.target, BuffID)

            endif

            if .hasbuff and GetUnitAbilityLevel(.target, BuffID) < 1 then

                call .destroy()

            endif

        endif

        implement endloop

        return false

    endmethod

endstruct



private function onDeath takes nothing returns boolean

    local LandS LS

    local unit u = GetTriggerUnit()

    if GetWidgetLife(u) - GetEventDamage() < 0.405 and GetUnitAbilityLevel(u, BuffID) > 0 then

        set LS = LandS(GetData(u, SpellID))

        call TEffect.Start(AddSpecialEffectTarget(DyingEffect, LS.target, "chest"), HealEffectDur)

        call SetWidgetLife(LS.caster, GetWidgetLife(LS.caster) + LS.tl)

        call TEffect.Start(AddSpecialEffectTarget(HealEffect, LS.caster, "origin"), HealEffectDur)

    endif

    set u = null

    return false

endfunction



public function Conditions takes nothing returns boolean

    local unit u = GetTriggerUnit()

    local unit t = GetSpellTargetUnit()

    if GetSpellAbilityId() == SpellID then

        if GetUnitAbilityLevel(t, BuffID) < 1 then

            call LandS.create(u, t)

        else

            set LandS(GetData(t, SpellID)).caster = u

        endif

    endif

    set u = null

    set t = null

    return false

endfunction



//===========================================================================

private function init takes nothing returns nothing

    call HeroIndexer.AddCode(function LandS.Update)

    call AddDamageCondition(function onDeath)

    call RegisterAnyUnitEvent( EVENT_PLAYER_UNIT_SPELL_EFFECT, function Conditions, null )

	set TargetEffect     = GetAbilityEffectById(SpellID, EFFECT_TYPE_SPECIAL, 0)

	set HealEffect       = GetAbilityEffectById(SpellID, EFFECT_TYPE_SPECIAL, 1)

	set DyingEffect      = GetAbilityEffectById(SpellID, EFFECT_TYPE_SPECIAL, 2)

    call Preload(TargetEffect)

    call Preload(HealEffect)

    call Preload(DyingEffect)

endfunction



endlibrary//===========================================================================

// Trigger: Murgulogenesis

//

// This spell is based on "The kraken", by me :)

// requires RegisterAnyUnitEvent, Indexor2, UnitDamage

//===========================================================================

//TESH.scrollpos=0

//TESH.alwaysfold=0

library Murgulogenesis initializer init requires RegisterAnyUnitEvent, Indexor2, UnitDamage



globals

	private constant integer     SpellID          = 'A007' // Dummy Ability Rawcode. This spell works fine with an ability based on BLIZZARD.

	private constant integer     Tentacle         = 'n004' // Tentacle Unit Rawcode

	private constant real        AOE              = 500.   // spell Area of Effect. It's recommended to use the same AOE from dummy ability

	private constant real        SpellDuration    = 1.167  // Spell animation time. Check in the caster model the spell animation time to set this value

	private constant real        MinTentacleScale = 1.     //Set the tentacles' minimun scale

	private constant real        MaxTentacleScale = 1.5    //Set the tentacles' maximun scale

	private constant real        dt               = 0.3

	private constant pathingtype PathAllowed      = PATHING_TYPE_WALKABILITY

endglobals



private function GetEnemies takes nothing returns boolean

	return IsUnitType(GetFilterUnit(), UNIT_TYPE_FLYING) == false and IsUnitEnemy(GetFilterUnit(), bj_groupEnumOwningPlayer)

endfunction



private function TentacleAbilities takes unit SummonedUnit returns nothing 

    // You can add more abilities to the summoned tentacle with this function 

    call UnitAddAbility(SummonedUnit, 'ACmi')//Makes tentacles resistant to spells.

endfunction



private struct MurgulData extends array

	private static thistype D

    unit caster

	real x

    real y

	integer order

	group tentacles

	integer tentnumber

    real tick

	

    implement AllocLoop

    

	static method create takes unit c, real x, real y returns thistype

		local thistype MD = thistype.allocate()

		set MD.caster = c

		set MD.x = x

        set MD.y = y

		set MD.order = GetUnitCurrentOrder(c)

        if MD.tentacles == null then

            set MD.tentacles = CreateGroup()

        endif

        set MD.tentnumber = 0

        set MD.tick = 0.

        set c = null

		return MD

	endmethod

    

    private static method CleanTentacles takes nothing returns nothing

        local unit u = GetEnumUnit()

        call SetUnitExploded(u, true)

        call KillUnit(u)

        set u = null

    endmethod

    

	method destroy takes nothing returns nothing

		if .tentnumber > 0 then

			call ForGroup(.tentacles, function thistype.CleanTentacles)

		endif

		call GroupClear(.tentacles)

		set .caster = null

        call .deallocate()

	endmethod

	

    private static method DoSettings takes nothing returns nothing

        local unit u = GetEnumUnit()

        local real x = GetUnitX(u) + GetRandomReal(-AOE, AOE)

        local real y = GetUnitY(u) + GetRandomReal(-AOE, AOE)

        if not IsUnitInRangeXY(u, thistype.D.x, thistype.D.y, AOE * 0.9) then

            call IssuePointOrder(u, "move", thistype.D.x, thistype.D.y)

        endif

        if GetUnitCurrentOrder(u) != OrderId("attack") then

            call IssuePointOrder(u, "attack", x, y)

        endif

        if GetWidgetLife(u) < 0.405 or not IsUnitInRangeXY(u, thistype.D.x, thistype.D.y, AOE) then

            call GroupRemoveUnit(thistype.D.tentacles, u)

            set thistype.D.tentnumber = thistype.D.tentnumber - 1

            call SetUnitExploded(u, true)

            call KillUnit(u)

        endif

        set u = null

    endmethod

    

	method SetTarget takes nothing returns nothing

		set MurgulData.D = this

		call ForGroup(.tentacles, function MurgulData.DoSettings)

	endmethod

	

	method controltentacles takes nothing returns nothing

		local unit u

		local real d = GetRandomReal(0., AOE)

		local real a = GetRandomReal(0., 2 * bj_PI)

		local real x = .x + d * Cos(a)

		local real y = .y + d * Sin(a)

		set bj_groupEnumOwningPlayer = GetOwningPlayer(.caster)

		call GroupEnumUnitsInRange(bj_lastCreatedGroup, .x, .y, AOE, Condition(function GetEnemies))

		set bj_groupCountUnits = 0

		call ForGroup(bj_lastCreatedGroup, function CountUnitsInGroupEnum)

		if bj_groupCountUnits > .tentnumber then

			call DestroyEffect(AddSpellEffectById(Tentacle, EFFECT_TYPE_SPECIAL, x, y))

			set u = CreateDummy(bj_groupEnumOwningPlayer, Tentacle, x, y, a)

			call UnitAddAbility(u, 'Aloc')

			call UnitRemoveAbility(u, 'Aloc')

			call TentacleAbilities(u)

			call GroupAddUnit(.tentacles, u)

			set .tentnumber = .tentnumber + 1

		endif

		if bj_groupCountUnits < .tentnumber then

			set u = FirstOfGroup(.tentacles)

			call GroupRemoveUnit(.tentacles, u)

			call SetUnitExploded(u, true)

            call KillUnit(u)

			set .tentnumber = .tentnumber - 1

		endif

		call GroupClear(bj_lastCreatedGroup)

	endmethod

    

    static method Update takes nothing returns boolean

        implement loop

        set .tick = .tick + HeroIndexer.period

        if .tick > dt then

            set .tick = 0.

            if .order == GetUnitCurrentOrder(.caster) then

                call .controltentacles()

                call .SetTarget()

                if GetWidgetLife(.caster) < 0.405 then

                    call .destroy()

                endif

            else

                call .destroy()

            endif

        endif

        implement endloop

        return false

    endmethod

endstruct



private function Conditions takes nothing returns boolean

    if GetSpellAbilityId() == SpellID then

        call MurgulData.create(GetTriggerUnit(), GetSpellTargetX(), GetSpellTargetY())

    endif

    return false

endfunction



private function init takes nothing returns nothing // Trigger Initialization. DO NOT MODIFY

    call HeroIndexer.AddCode( function MurgulData.Update )

    call RegisterAnyUnitEvent( EVENT_PLAYER_UNIT_SPELL_EFFECT, function Conditions, null )

endfunction



endlibrary//===========================================================================

// Trigger: FearPoison

//

// requires Indexor2, ProjSys

//===========================================================================

//TESH.scrollpos=31

//TESH.alwaysfold=0

library FearPoison initializer init requires Indexor2, ProjSys



globals

	private constant integer  SummonedID = 'o000'

	private constant integer  BuffID     = 'B00H'

	private constant real     AOE        = 500.

	private constant real     dt         = 0.5

endglobals



private struct FPData extends array

    static thistype D

	unit summon

	effect fx

    real tick

    

    implement AllocLoop

	

	static method create takes unit s returns thistype

		local thistype FP = thistype.allocate()

		set FP.summon = s

		call UnitAddAbility(s, 'Aloc')

		call UnitRemoveAbility(s, 'Aloc')

		set FP.fx = AddSpellEffectById(SummonedID, EFFECT_TYPE_SPECIAL, GetUnitX(s), GetUnitY(s))

        set FP.tick = 0.

		return FP

	endmethod

	

	method destroy takes nothing returns nothing

		set .summon = null

		call DestroyEffect(.fx)

		set .fx = null

        call .deallocate()

	endmethod

    

    private static method GetEnemies takes nothing returns boolean

        local unit u = GetFilterUnit()

        local real a = GetUnitsAngle(thistype.D.summon, u)

        local real x = GetUnitX(u) + AOE * Cos(a)

        local real y = GetUnitY(u) + AOE * Sin(a)

        if IsUnitEnemy(u, GetOwningPlayer(thistype.D.summon)) and GetUnitAbilityLevel(u, BuffID) > 0 and GetUnitCurrentOrder(u) != OrderId("move") then

            call IssuePointOrder(u, "move", x, y)

        endif

        set u = null

        return false

    endmethod

    

    static method Update takes nothing returns boolean

        implement loop

        set .tick = .tick + HeroIndexer.period

        if .tick > dt then

            set .tick = 0.

            set thistype.D = this

            call GroupEnumUnitsInRange(bj_lastCreatedGroup, GetUnitX(.summon), GetUnitY(.summon), AOE * 2, Condition(function thistype.GetEnemies))

            if GetWidgetLife(.summon) < 0.405 then

                call .destroy()

            endif

        endif

        implement endloop

        return false

    endmethod

endstruct



private function Conditions takes nothing returns boolean

    local unit u = GetSummonedUnit()

    if GetUnitTypeId(u) == SummonedID then

        call FPData.create(u)

    endif

    set u = null

    return false

endfunction



private function init takes nothing returns nothing

    call HeroIndexer.AddCode( function FPData.Update )

    call RegisterAnyUnitEvent( EVENT_PLAYER_UNIT_SUMMON, function Conditions, null )

endfunction



endlibrary//===========================================================================

// Trigger: ToxicFog

//

// requires Indexor2

//===========================================================================

//TESH.scrollpos=7

//TESH.alwaysfold=0

library ToxicFog initializer Init requires Indexor2



// this trigger is only to control better the fog effect

globals

	private constant integer SpellID = 'A00D'

	private constant integer BuffID  = 'B00R'

endglobals



private struct data extends array

    unit c

    effect f

    

    implement AllocLoop

    

    static method Start takes unit c returns thistype

        local thistype D = thistype.allocate()

        set D.c = c

        set D.f = AddSpellEffectTargetById(SpellID, EFFECT_TYPE_SPECIAL, c, "origin")

        set c = null

        return D

    endmethod

    

    method destroy takes nothing returns nothing

        call DestroyEffect(.f)

        set .c = null

        set .f = null

        call .deallocate()

    endmethod

    

    static method Update takes nothing returns boolean

        implement loop

        if GetUnitAbilityLevel(.c, BuffID) < 1 then

            call .destroy()

        endif

        implement endloop

        return false

    endmethod

endstruct



private function Conditions takes nothing returns boolean

    if GetSpellAbilityId() == SpellID then

        call data.Start(GetTriggerUnit())

    endif

    return false

endfunction



private function Init takes nothing returns nothing

    call UnitIndexer.AddCode(function data.Update)

    call RegisterAnyUnitEvent( EVENT_PLAYER_UNIT_SPELL_EFFECT, function Conditions, null )

endfunction



endlibrary//===========================================================================

// Trigger: WaterShield

//

// requires UnitDamage, TimedEffects

//===========================================================================

//TESH.scrollpos=0

//TESH.alwaysfold=0

library WaterShield initializer init requires UnitDamage, TimedEffects



globals

    private constant integer       SpellID   = 'A01F' //Spell Rawcode

    private constant integer       BuffID    = 'B00T' // Dummy buff Rawcode. Buff based on FROST ARMOR

    private constant real          Chance    = 0.5 // Returns the max chance of absorbing any damage

endglobals



private function Damage takes nothing returns boolean

    local unit c = GetTriggerUnit()

    local real dam

    if GetEventDamage() > 0 and GetUnitAbilityLevel(c, BuffID) > 0 then

        set dam = GetRandomReal(0., Chance) * GetEventDamage()

        call TEffect.Start(AddSpellEffectTargetById(SpellID, EFFECT_TYPE_SPECIAL, c, "chest"), 1.)

        call SetWidgetLife(c, GetWidgetLife(c) + dam)

    endif

    set c = null

    return false

endfunction



//===========================================================================

private function init takes nothing returns nothing

    call AddDamageCondition( function Damage )

endfunction



endlibrary

//===========================================================================

// Trigger: Sonic

//

// requires Indexor2, TimedEffects, MicroTable

//===========================================================================

//TESH.scrollpos=0

//TESH.alwaysfold=0

library Sonic initializer init requires Indexor2, TimedEffects, MicroTable



globals

    private constant integer SpellID = 'A015' // Spell ID

    private constant integer DummyAb = 'A01Y' // based on Soul Burn

    private constant integer DummyBu = 'B00K' // dummy buff ability

    private constant integer BuffID  = 'B013' // Buff ID

    private constant string  Order   = "soulburn"

    private constant string  PathSnd = "Units\\Creeps\\Harpy\\HarpyPissed2.wav"

    private constant real    radius  = 500.

    private constant real    dt      = 0.1 // timer interval

endglobals



private struct SonicData extends array

    static sound Sound

    static group HasSonic = CreateGroup()



    unit caster

    unit target

    boolean hasbuff

    real lx

    real ly

    real tick

    

    implement AllocLoop

    

    private static method SetUnitSound takes unit u returns nothing

        call SetSoundPitch(thistype.Sound,GetRandomReal(0.75,1.25))

        call SetSoundVolume(thistype.Sound, 127)

        call SetSoundDistances(thistype.Sound, 600, 10000)

        call SetSoundDistanceCutoff(thistype.Sound, 3000)

        call AttachSoundToUnit(thistype.Sound, u)

        call StartSound(thistype.Sound)

    endmethod

    

    static method start takes unit c, unit t returns nothing

        local thistype SD 

        if not IsUnitInGroup(t, thistype.HasSonic) then

            set SD = thistype.allocate()

            set SD.target = t

            call GroupAddUnit(thistype.HasSonic, t)

            set SD.lx = GetUnitX(t)

            set SD.ly = GetUnitY(t)

            set SD.tick = 0

            call UnitAddAbility(t, 'Abun')

        else

            set SD = thistype( GetData(t, SpellID) )

        endif

        set SD.hasbuff = false

        call thistype.SetUnitSound(c)

        set SD.caster = c

        set c = null

        set t = null

    endmethod

    

    method destroy takes nothing returns nothing

        call ClearValue(.target, SpellID)

        call GroupRemoveUnit(thistype.HasSonic, .target)

        call IssuePointOrder(.target, "move", .lx, ly)

        call UnitRemoveAbility(.target, 'Abun')

        set .target = null

        set .caster = null

        call .deallocate()

    endmethod

    

    static method Update takes nothing returns boolean

        local real a

        local real x

        local real y

        implement loop

        set .tick = .tick + UnitIndexer.period

        if .tick > dt then

            set .tick = 0.

            if not .hasbuff and GetUnitAbilityLevel(.target, DummyBu) > 0 then

                set .hasbuff = true

                call UnitRemoveAbility(.target, DummyBu)

                call PauseUnit(.target, true)

                call IssueImmediateOrder(.target, "stop")

                call PauseUnit(.target, false)

                call DummyCastTarget(.caster, .target, DummyAb, 1, Order)

            endif

            if .hasbuff and GetUnitAbilityLevel(.target, BuffID) > 0 and GetRandomInt(0, 10) < 6 then

                set a = GetUnitFacing(.target) * bj_DEGTORAD

                set a = GetRandomReal( a - bj_PI/2, a + bj_PI/2 )

                set x = GetUnitX(.target) + radius * Cos(a)

                set y = GetUnitY(.target) + radius * Sin(a)

                call IssuePointOrder(.target, "move", x, y)

            endif

            if .hasbuff and GetUnitAbilityLevel(.target, BuffID) < 1 then

                call .destroy()

            endif

        endif

        implement endloop

        return false

    endmethod

endstruct



private function Conditions takes nothing returns boolean

    if GetSpellAbilityId() == SpellID then

        call SonicData.start(GetTriggerUnit(), GetSpellTargetUnit())

    endif

    return false

endfunction



private function init takes nothing returns nothing

    set SonicData.Sound = CreateSound(PathSnd, false, true, false, 10, 10, "")

    call UnitIndexer.AddCode(function SonicData.Update)

    call RegisterAnyUnitEvent( EVENT_PLAYER_UNIT_SPELL_EFFECT, function Conditions, null )

endfunction



endlibrary

//===========================================================================

// Trigger: Broodlings

//

// requires MainGlobals, Indexor2, MicroTable, DummyCast, UnitDamage

//===========================================================================

//TESH.scrollpos=0

//TESH.alwaysfold=0

library Broodlings initializer init requires MainGlobals, Indexor2, MicroTable, DummyCast, UnitDamage



globals

    private constant integer SpellID  = 'A00M' // Spell rawcode

    private constant integer SpellInc = 'A00W' // Dummy spell to simulate the Coualt incubation stage

    private constant integer BuffID   = 'B014' //Buff used by both spells

    private constant integer DummyB   = 'B004' // dummy buff used to add to the timed life units

    private constant string  dumorder = "ensnare" // the string order of the dummy ability

    private constant integer Egg      = 'o002' // Couatl egg rawcode

    private constant integer Brood    = 'n009' // Couatl Whelp rawcode

    private constant real    AdultT   = 30. // the time required in seconds to convert a Couatl whelp into an adult couatl

    private constant real    EggTime  = 5.  // the time that the Coualt whelps are in a egg state

    private constant real    nidusrad = 40. // set the radius used to define the location of the eggs when they're created

    private constant real    Height   = 230. // sets the normal flying height for the Couatl Whelp

    private constant real    Hrate    = 100. // sets the flying height rate

    private constant real    dt       = 0.1

    private          string  MorphFX // stores the string path of the fx, used when the broodlings becomes into adult

endglobals



private function AddTimedLife takes nothing returns nothing

    call UnitApplyTimedLife(GetEnumUnit(), DummyB, GetRandomReal(0.7*EggTime, 1.03*EggTime))

endfunction



private struct BroodL extends array

    unit caster

    integer buffs

    group Whelps

    boolean hasbuff

    real tick

    

    implement AllocLoop

    

    static method create takes unit c, integer b returns thistype

        local thistype BL = thistype.allocate()

        set BL.caster = c

        set BL.buffs = b

        set BL.hasbuff = false

        set BL.tick = 0.

        if BL.Whelps == null then

            set BL.Whelps = CreateGroup()

        endif

        return BL

    endmethod

    

    method destroy takes nothing returns nothing

        call GroupClear(.Whelps)

        set .caster = null

        call .deallocate()

    endmethod

    

    static method Update takes nothing returns boolean

        local integer i = 1

        local real a

        local real x

        local real y

        implement loop

        set a = GetUnitFacing(.caster) * bj_DEGTORAD

        set .tick = .tick + UnitIndexer.period

        if .tick > dt then

            set .tick = 0.

            if not .hasbuff and GetUnitAbilityLevel(.caster, BuffID) > 0 then

                set .hasbuff = true

                loop

                    exitwhen i > .buffs

                    set a = a + (2 * bj_PI / .buffs)

                    set x = GetUnitX(.caster) + nidusrad * Cos(a)

                    set y = GetUnitY(.caster) + nidusrad * Sin(a)

                    call GroupAddUnit(.Whelps, CreateDummy(GetOwningPlayer(.caster), Egg, x, y, GetRandomReal(0., 360.)))

                    set i = i + 1

                endloop

                call ForGroup(.Whelps, function AddTimedLife)

            endif

            if .hasbuff and GetUnitAbilityLevel(.caster, BuffID) < 1 then

                call .destroy()

            endif

        endif

        implement endloop

        return false

    endmethod

endstruct

//===========================================================================

// trigger used to detect how many buffs the target has, if it doesn't the it stops the casting

public function CastActions takes nothing returns nothing

                                                              // REPOS  RENEG  MAG   PHYS  TIME  AURA   AUTO

    local integer cbuff = UnitCountBuffsEx(GetSpellTargetUnit(), false, false, true, false, true, false, false)

    local BroodL BL

    if cbuff > 0 then

        set BL = BroodL.create(GetTriggerUnit(), cbuff)

        call StoreData(GetTriggerUnit(), SpellID, integer(BL))

    else

        call PauseUnit(GetTriggerUnit(), true)

        call IssueImmediateOrder(GetTriggerUnit(), "stop")

        call PauseUnit(GetTriggerUnit(), false)

        call SimError(GetOwningPlayer(GetTriggerUnit()), "there is not buffs on target unit...")

    endif

endfunction

//===========================================================================

// trigger started when the whelp finishes its expiration timer and becames into an adult Coualt

public function WhelpConditions takes nothing returns boolean

    local unit c = GetTriggerUnit()

    local unit newc

    if GetUnitTypeId(c) == Brood and GetKillingUnit() == null then

        set newc = CreateUnit(GetOwningPlayer(c), 'nwgs', GetUnitX(c), GetUnitY(c), GetUnitFacing(c))

        call DestroyEffect(AddSpecialEffectTarget(MorphFX, newc, "chest"))

        if GetPlayerState(GetOwningPlayer(c), PLAYER_STATE_RESOURCE_FOOD_USED) > GetPlayerState(GetOwningPlayer(c), PLAYER_STATE_RESOURCE_FOOD_CAP) then

            call KillUnit(newc)

        endif

    elseif GetUnitTypeId(c) == Egg and GetKillingUnit() == null then

        set newc = CreateUnit(GetOwningPlayer(c), Brood, GetUnitX(c), GetUnitY(c), GetUnitFacing(c))

        call SetUnitFlyHeight(newc, 0, 0)

        call SetUnitFlyHeight(newc, Height, Hrate)

        call UnitApplyTimedLife(newc, DummyB, AdultT)

    endif

    set c = null

    set newc = null

    return false

endfunction

//===========================================================================

public function Conditions takes nothing returns boolean

    return GetSpellAbilityId() == SpellID

endfunction



public function Actions takes nothing returns nothing

    local unit c = GetTriggerUnit()

    local BroodL BL = BroodL( GetData(c, SpellID) )

    call ClearValue(c, SpellID)

    call DummyCastOnTarget(c, c, SpellInc, 1, dumorder, false)

    set c = null

endfunction

//===========================================================================

private function init takes nothing returns nothing

    call UnitIndexer.AddCode(function BroodL.Update)

    // trigger used to detect how many buffs the target has, if it doesn't the it stops the casting

    call RegisterAnyUnitEvent( EVENT_PLAYER_UNIT_SPELL_CAST, function Conditions, function CastActions )

    // trigger that will transform the whelps into adult couatls

    call RegisterAnyUnitEvent( EVENT_PLAYER_UNIT_SPELL_EFFECT, function Conditions, function Actions )

    // trigger started when the whelp finishes its expiration timer and becames into an adult Coualt

    call RegisterAnyUnitEvent( EVENT_PLAYER_UNIT_DEATH, function WhelpConditions, null )

    set MorphFX = GetAbilityEffectById(SpellID, EFFECT_TYPE_SPECIAL, 0)

    call Preload(MorphFX)

endfunction

    

endlibrary

//===========================================================================

// Trigger: Summon Magic Vault

//===========================================================================

//TESH.scrollpos=0

//TESH.alwaysfold=0

scope SummonMagicVault initializer init 



globals

    private constant integer UnitID = 'h004'

endglobals



private function Conditions takes nothing returns boolean

    local unit u = GetSummonedUnit()

    if GetUnitTypeId(u) == UnitID then

        call SetUnitAnimation(u, "stand")

    endif

    set u = null

    return false

endfunction



//===========================================================================

private function init takes nothing returns nothing

    call RegisterAnyUnitEvent( EVENT_PLAYER_UNIT_SUMMON, function Conditions, null )

    call RemoveUnit(CreateUnit(Player(15), UnitID, 0,0,0))

endfunction



endscope



//===========================================================================

// Trigger: Demon Ability

//

// requires TimedEffects, UnitDamage

//===========================================================================

//TESH.scrollpos=0

//TESH.alwaysfold=0

library DemonAbility initializer init requires TimedEffects, UnitDamage



globals

    private constant integer  Upgrade = 'R008' //upgrade rawcode

    private constant integer  SpellID = 'A019' // the ability

    private constant integer  SpellID2 = 'A02Z' // the ability (2,1 button)

    private constant real     PercLife = 0.2 // percentage of life when the ability is activated

    private constant real     PercArea = 0.1 // percentage of life when the ability is activated for nearby units

    private constant real     Area     = 200. // Blood Bath AOE

    private          string   FX

endglobals



private function HasAbility takes unit u returns boolean

    return GetPlayerTechCount(GetOwningPlayer(u), Upgrade, true) > 0 and (GetUnitAbilityLevel(u, SpellID) > 0 or GetUnitAbilityLevel(u, SpellID2) > 0)

endfunction



private function DoBath takes nothing returns boolean

    local unit u = GetFilterUnit()

    if IsUnitAlly(u, GetOwningPlayer(bj_lastCreatedUnit)) and HasAbility(u) then

        call TEffect.Start(AddSpecialEffect(FX, GetUnitX(u), GetUnitY(u)), 1.)

        if u == bj_lastCreatedUnit then

            call SetWidgetLife(u, GetWidgetLife(u) + GetUnitState(u, UNIT_STATE_MAX_LIFE)*PercLife)

        elseif u!= bj_lastCreatedUnit and GetRandomInt(0,10) <= GetUnitLevel(u) then

            call SetWidgetLife(u, GetWidgetLife(u) + GetUnitState(u, UNIT_STATE_MAX_LIFE)*PercArea)

        endif

    endif

    set u = null

    return false

endfunction



private function Conditions takes nothing returns boolean 

    local unit u = GetTriggerUnit()

    set bj_lastCreatedUnit = GetKillingUnit()

    if HasAbility(bj_lastCreatedUnit) then

        call DestroyEffect(AddSpellEffectById(GetUnitTypeId(u), EFFECT_TYPE_SPECIAL, GetUnitX(u), GetUnitY(u)))

        call GroupEnumUnitsInRange(bj_lastCreatedGroup, GetUnitX(u), GetUnitY(u), Area, Condition(function DoBath))

    endif

    set u = null

    return false

endfunction



private function init takes nothing returns nothing

    call RegisterAnyUnitEvent( EVENT_PLAYER_UNIT_DEATH, function Conditions, null )

    set FX = GetAbilityEffectById(SpellID, EFFECT_TYPE_SPECIAL, 0)

    call Preload(FX)

endfunction



endlibrary



//===========================================================================

// Trigger: Inner Hell

//

// requires Indexor2, TimedEffects, DummyCast, DamageCredit

//===========================================================================

//TESH.scrollpos=42

//TESH.alwaysfold=0

library InnerHell initializer init requires Indexor2, TimedEffects, DummyCast, DamageCredit



globals



	private constant integer SpellID       = 'A01G' // Dummy Ability rawcode. Based on LIGHTING SHIELD

	private constant integer BuffID        = 'B00A' // Dummy Buff rawcode. Based on LIGHTING SHIELD buff

    private constant integer DummyAbil     = 'A02G' // Dummy Missile Ability

    private constant string  DummyOrder    = "firebolt" // order to cast the dummyabil

	private constant real    ManaBurnBonus = 1.1 // this is used to increase the damage on units with mana

	private constant real    dt            = 0.1

endglobals



private constant function DamageRate takes integer level returns real

    // Returns the damage dealt to the target unit

    return 10.0 + 5 * (level - 1)

endfunction



private struct IHData extends array

	unit caster

	unit target

    player p

	boolean hasbuff

    real tick

	

    implement AllocLoop

    

	static method create takes unit c, unit t returns thistype

		local thistype IH = thistype.allocate()

		set IH.caster = c

		set IH.target = t

        set IH.p = GetOwningPlayer(c)

        set IH.tick = 0.

        set IH.hasbuff = false

		return IH

	endmethod

	

	method destroy takes nothing returns nothing

		set .caster = null

		set .target = null

        call .deallocate()

	endmethod

    

    static method Update takes nothing returns boolean

        local real D

        implement loop

        set .tick = .tick + HeroIndexer.period

        if .tick > dt then

            set .tick = 0.

            if not .hasbuff and GetUnitAbilityLevel(.target, BuffID) > 0 then

                set .hasbuff = true

            endif

            if .hasbuff and GetUnitAbilityLevel(.target, BuffID) > 0 then

                set D = DamageRate(GetUnitAbilityLevel(.caster, SpellID)) * dt

                if GetUnitState(.target, UNIT_STATE_MANA) > 0. then

                    call SetUnitState(.target, UNIT_STATE_MANA, GetUnitState(.target, UNIT_STATE_MANA) - D)

                    set D = D * ManaBurnBonus

                endif

                call DoSafeDamage(DamageCredit(.caster, .p), .target, D, false, false, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_MAGIC, WEAPON_TYPE_WHOKNOWS)

            endif

            if .hasbuff and GetUnitAbilityLevel(.target, BuffID) < 1 then

                call .destroy()

            endif

        endif

        implement endloop

        return false

    endmethod

endstruct



private function Conditions takes nothing returns boolean

    local unit u = GetSpellTargetUnit()

    local unit t = GetSpellAbilityUnit()

    if GetSpellAbilityId() == SpellID then

        call IHData.create(t, u)

        call DummyCastTarget(t, u, DummyAbil, 1, DummyOrder)

    endif

    set u = null

    set t = null

    return false

endfunction



private function init takes nothing returns nothing

    call HeroIndexer.AddCode(function IHData.Update)

    call RegisterAnyUnitEvent( EVENT_PLAYER_UNIT_SPELL_EFFECT, function Conditions, null )

endfunction



endlibrary//===========================================================================

// Trigger: HellFire

//

// requires Indexor2, TimedEffects, ProjSys

//===========================================================================

//TESH.scrollpos=24

//TESH.alwaysfold=0

library HellFire initializer init requires Indexor2, TimedEffects, ProjSys



globals

    private constant integer SpellID = 'A01H' // Spell ID rawcode

    private constant real    Speed   = 1050.  // Fire speed

    private constant real    PercSpd = 0.3    // Sets the % of fire speed at which the unit will be knockbacked 

    private constant real    Dur     = 5.    // Burning effect duration

    private constant real    dt      = 0.25

    private          string   FX

endglobals



private constant function Range takes integer level returns real

    return 800. + 150. * (level - 1)

endfunction



private constant function FinalArea takes integer level returns real

    return 150. + 75. * (level - 1)

endfunction



private constant function DoT takes integer level returns real

    return 5. + 5. * (level - 1)

endfunction



private struct data extends array

    unit caster

    group burned

    real radius

    real angle

    real tick

    

    implement AllocLoop

    

    static method create takes unit caster returns thistype

        local thistype D = thistype.allocate()

        set D.caster = caster

        set D.angle = GetUnitFacing(caster) * bj_DEGTORAD

        set D.radius = 0.

        set D.tick = 0.

        if D.burned == null then

            set D.burned = CreateGroup()

        endif

        set caster = null

        return D

    endmethod

    

    method destroy takes nothing returns nothing

        call GroupClear(.burned)

        set .caster = null

        call .deallocate()

    endmethod

    

    private static method GetUnits takes nothing returns boolean

        local thistype D = thistype( bj_destInRegionDiesCount )

        local unit u = GetFilterUnit()

        local real x = GetUnitX(D.caster) + bj_randomSubGroupChance * Cos(D.angle)

        local real y = GetUnitY(D.caster) + bj_randomSubGroupChance * Sin(D.angle)

        local real a

        local real r

        local vector pi

        local vector pf

        local vector vi

        local vector vf

        if GetWidgetLife(u) > 0.405 and IsUnitType(u, UNIT_TYPE_STRUCTURE) == false and IsUnitEnemy(u, GetOwningPlayer(D.caster)) and IsUnitInRangeXY(u, x, y, bj_randomSubGroupChance) and not IsUnitInGroup(u, D.burned) then

            set a = GetUnitsAngle(D.caster, u)

            set r = Range(GetUnitAbilityLevel(D.caster, SpellID)) * PercSpd

            set pi = vector.create(GetUnitX(u), GetUnitY(u), GetUnitFlyHeight(u))

            set pf = vector.create(pi.x+r*Cos(a),pi.y+r*Sin(a), pi.z)

            set vi = vector.create(Speed * PercSpd, a, 0.)

            set vf = vector.create(0., 0., 0.)

            call GroupAddUnit(D.burned, u)

            call TEffect.Start(AddSpecialEffectTarget(FX,u, "chest"), Dur)

            call DOT.start(Dur, D.caster, u, DoT(GetUnitAbilityLevel(D.caster, SpellID)), false, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_UNIVERSAL, WEAPON_TYPE_WHOKNOWS, false)

            call Projectile.createSpherical(u, pi, pf, vi, vf, r / (PercSpd * Speed), true, false)

        endif

        set u = null

        return false 

    endmethod

    

    static method Update takes nothing returns boolean

        implement loop

        set .tick = .tick + HeroIndexer.period

        if .tick > dt then

            set .tick = 0.

            set .radius = .radius + Speed * dt

            if .radius <= Range(GetUnitAbilityLevel(.caster, SpellID)) then

                set bj_destInRegionDiesCount = integer(this)

                set bj_randomSubGroupChance = FinalArea(GetUnitAbilityLevel(.caster, SpellID)) * .radius / Range(GetUnitAbilityLevel(.caster, SpellID))

                call GroupEnumUnitsInRange(bj_lastCreatedGroup, GetUnitX(.caster), GetUnitY(.caster), .radius, Condition(function thistype.GetUnits))

            else

                call .destroy()

            endif

        endif

        implement endloop

        return false

    endmethod 

endstruct



private function Conditions takes nothing returns boolean

    if GetSpellAbilityId() == SpellID then

        call data.create(GetTriggerUnit())

    endif

    return false

endfunction



//===========================================================================

private function init takes nothing returns nothing

    call HeroIndexer.AddCode(function data.Update)

    call RegisterAnyUnitEvent( EVENT_PLAYER_UNIT_SPELL_EFFECT, function Conditions, null )

    set FX = GetAbilityEffectById(SpellID, EFFECT_TYPE_TARGET, 0)

endfunction



endlibrary

//===========================================================================

// Trigger: Sadism

//

// requires UnitDamage, TimedEffects

//===========================================================================

//TESH.scrollpos=0

//TESH.alwaysfold=0

library Sadism initializer Init requires UnitDamage, TimedEffects



globals

	private constant integer  SpellID    = 'A01K' // Ability Rawcode. Spell based on BERSECK

	private constant integer  BuffID     = 'B00V' // Dummy Ability Rawcode. Spell based on BERSECK

	private constant real     AOE        = 160.   // Returns the Damage AOE

	private constant real     DamageRate = 10.    // Returns the Damage rate

	private constant real     Dur        = 5.     // Returns the Damage over time duration

	

	private          string       ImpactFX

	private          string       DamageFX

    private          string array Points

endglobals



private function GetEnemies takes nothing returns boolean

    local unit u = GetFilterUnit()

    if GetWidgetLife(u) > 0.405 and IsUnitEnemy(u, GetOwningPlayer(bj_lastCreatedUnit)) and IsUnitType(u, UNIT_TYPE_FLYING) == false and IsUnitType(u, UNIT_TYPE_STRUCTURE) == false then

        call TEffect.Start(AddSpecialEffectTarget(DamageFX, u, Points[GetRandomInt(0, 3)]), Dur)

        call DOT.start(Dur, bj_lastCreatedUnit, u, DamageRate, true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS, true)

    endif

    set u = null

    return false

endfunction



private function DoDamage takes nothing returns boolean

    local unit d = GetTriggerUnit()

    set bj_lastCreatedUnit = GetEventDamageSource()

    if GetEventDamage() > 0 and GetUnitAbilityLevel(bj_lastCreatedUnit, BuffID) > 0 then

        call GroupEnumUnitsInRange(bj_lastCreatedGroup, GetUnitX(d), GetUnitY(d), AOE, Condition(function GetEnemies))

        call DestroyEffect(AddSpecialEffectTarget(ImpactFX, d, "chest"))

    endif

    set bj_lastCreatedUnit = null

    return false

endfunction



private function Init takes nothing returns nothing

	set ImpactFX = GetAbilityEffectById(SpellID, EFFECT_TYPE_SPECIAL, 0)

	set DamageFX = GetAbilityEffectById(SpellID, EFFECT_TYPE_SPECIAL, 1)

    set Points[0] = "chest"

    set Points[1] = "left arm"

    set Points[2] = "right arm"

    set Points[3] = "head"

	call Preload(ImpactFX)

	call Preload(DamageFX)

    call AddDamageCondition( function DoDamage )

endfunction



endlibrary//===========================================================================

// Trigger: Fetid Stomach

//===========================================================================

//TESH.scrollpos=0

//TESH.alwaysfold=0

scope Fetid initializer init



globals

    private constant integer SpellID = 'A01Q'

    private constant string  PathSnd = "Units\\Orc\\KotoBeast\\KodoBeastPuke1.wav"

    private          sound   Sound

endglobals



private function Conditions takes nothing returns boolean

    if GetSpellAbilityId() == SpellID then

        call SetSoundPitch(Sound,GetRandomReal(0.75,1.25))

        call SetSoundVolume(Sound, 127)

        call SetSoundDistances(Sound, 600, 10000)

        call SetSoundDistanceCutoff(Sound, 3000)

        call AttachSoundToUnit(Sound, GetTriggerUnit())

        call StartSound(Sound)

    endif

    return false

endfunction



//===========================================================================

private function init takes nothing returns nothing

    call RegisterAnyUnitEvent( EVENT_PLAYER_UNIT_SPELL_EFFECT, function Conditions, null )

    call Preload(PathSnd)

    set Sound = CreateSound(PathSnd, false, true, false, 10, 10, "")

endfunction



endscope

//===========================================================================

// Trigger: Mighty Smash

//

// requires ProjSys, TimedEffects, MicroTable, SpellBlocker

//===========================================================================

//TESH.scrollpos=59

//TESH.alwaysfold=0

library MightySmash initializer init requires ProjSys, TimedEffects, MicroTable, SpellBlocker



globals

    private constant integer SpellID    = 'A01O' // Returns the ability rawcode

    private constant integer DummyAb    = 'A02X' //The dummy stun ability, based on ThunderClap

    private constant integer BuffID     = 'B00U' //Dizziness buff

    private constant string  DummyOrder = "thunderclap"

    private constant real    AOE        = 300.

    private constant real    MaxDist    = 600. // max distance that the units are expelled from the caster

    private constant real    MinDist    = 200. // min    "      "    "    "    "     "       "   "    "

    private constant real    MaxH       = 350.

    private constant real    MinH       = 50.

    private constant real    Speed      = 800. // speed expulsion

    private constant real    AnimDur    = 1.167 // Spell Slam Duration...

    private constant integer AnimIndex  = 7 //Set the animation index

    private          real    MovSpeed   = 0. //stores the original movement speed

endglobals



private function Distance takes real range returns real

    local real m = (MinDist - MaxDist) / AOE

    return m * range + MaxDist

endfunction



private function Height takes real range returns real

    local real m = (MinH - MaxH) / AOE

    return m * range + MaxH

endfunction



private function GetEnemies takes nothing returns boolean

    local unit u = GetFilterUnit()

    local real d

    local real h

    local real a

    if GetUnitAbilityLevel(u, BuffID) > 0 or (GetWidgetLife(u) > 0.405 and IsUnitEnemy(u, bj_groupEnumOwningPlayer) and IsUnitType(u, UNIT_TYPE_FLYING) == false) and IsUnitType(u, UNIT_TYPE_STRUCTURE) == false then

        set d = GetUnitsDist(bj_groupRandomCurrentPick, u)

        set h = Height(d)

        set a = GetUnitsAngle(bj_groupRandomCurrentPick, u)

        set d = Distance(d)

        call KnockBack(u, d, a, h, Speed, null, null, true)

    endif

    set u = null

    return false

endfunction



private function end takes nothing returns nothing

    local unit u = GetUnitProjectile()

    call SetUnitSpellInvulnerable(u, false)

    call SetUnitPosition(u, GetUnitX(u), GetUnitY(u))

    call SetUnitFlyHeight(u, 0., 0.)

    call DestroyEffect(AddSpellEffectById(SpellID, EFFECT_TYPE_SPECIAL, GetUnitX(u), GetUnitY(u)))

    call DummyCastTarget(u, null, DummyAb, GetUnitAbilityLevel(u, SpellID), DummyOrder)

    call SetUnitMoveSpeed(u, MovSpeed)

    call SetUnitAnimation(u, "stand")

    set u = null

endfunction



private function Conditions takes nothing returns boolean

    local unit c 

    local real d 

    local vector pi 

    local vector pf 

    local vector vi

    local vector vf 

    local Projectile PR 

    if GetSpellAbilityId() == SpellID then

        set c = GetTriggerUnit()

        set d = Dist(GetUnitX(c), GetUnitY(c), GetSpellTargetX(), GetSpellTargetY())

        set pi = vector.create(GetUnitX(c), GetUnitY(c), 0.)

        set pf = vector.create(GetSpellTargetX(), GetSpellTargetY(), 0.)

        set vi = vector.create(Speed, GetUnitFacing(c) * bj_DEGTORAD, GetParabolicAngle(MaxH, d))

        set vf = vector.create(vi.x, vi.y, -1.5*vi.z)

        set PR = Projectile.createSpherical(c, pi, pf, vi, vf, d/Speed, false, false)

        call SetUnitAnimationByIndex(c, AnimIndex) 

        call SetUnitMoveSpeed(c, AnimDur * Speed / d)

        call SetUnitSpellInvulnerable(c, true)

        call PR.SetEndCode(function end)

    endif

    set c = null

    return false 

endfunction



private function StunConditions takes nothing returns boolean

    if GetSpellAbilityId() == DummyAb then 

        set bj_groupRandomCurrentPick = GetTriggerUnit()

        set bj_groupEnumOwningPlayer = GetOwningPlayer(bj_groupRandomCurrentPick)

        call GroupEnumUnitsInRange(bj_lastCreatedGroup, GetUnitX(bj_groupRandomCurrentPick), GetUnitY(bj_groupRandomCurrentPick), AOE, Condition(function GetEnemies))

    endif

    return false

endfunction



//===========================================================================

private function init takes nothing returns nothing

    local unit u = CreateUnit(Player(15), 'N013', 0,0,0)

    set MovSpeed = GetUnitMoveSpeed(u)

    call RemoveUnit(u)

    set u = null

    call RegisterAnyUnitEvent( EVENT_PLAYER_UNIT_SPELL_EFFECT, function Conditions, null )

    call RegisterAnyUnitEvent( EVENT_PLAYER_UNIT_SPELL_CAST, function StunConditions, null )

endfunction



endlibrary



//===========================================================================

// Trigger: Stunning Punch

//

// requires  UnitDamage, ProjSys, TimedEffects

//===========================================================================

//TESH.scrollpos=0

//TESH.alwaysfold=0



library StunningPunch initializer init requires  UnitDamage, ProjSys, TimedEffects



globals

    private constant integer SpellID  = 'A01P' // Spell ability

    private constant real    Distance = 300. // Distance expelled

    private constant real    Speed    = 1200. // Initial Speed

    private constant real    Radius   = 250. // units in range of the smashed unit

    private constant real    Height   = 150. //Max height units will fly...

endglobals



private constant function Chance takes integer level returns real

    return 0.1 + 0.15 * (level - 1)

endfunction



private function ChooseUnits takes nothing returns boolean

    local unit u = GetFilterUnit()

    local integer l = GetUnitAbilityLevel(bj_lastCreatedUnit, SpellID)

    if GetEventDamage() > 0 and GetWidgetLife(u) > 0.405 and bj_enumDestructableRadius > 0 and IsUnitInRange(u, bj_lastCreatedUnit, Radius) and IsUnitEnemy(u, GetOwningPlayer(bj_lastCreatedUnit)) and l > 0 and GetRandomReal(0., 1.) <= Chance(l) and IsUnitType(u, UNIT_TYPE_FLYING) == false and IsUnitType(u, UNIT_TYPE_STRUCTURE) == false then

        if u != bj_groupRandomCurrentPick then

            call DoSafeDamage(bj_lastCreatedUnit, u, bj_enumDestructableRadius, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_ROCK_HEAVY_BASH)

        endif

        call KnockBack( u, Distance, GetUnitsAngle(bj_lastCreatedUnit, u), GetRandomReal(0., Height), Speed, null, null, true)

        call TEffect.Start(AddSpellEffectTargetById(SpellID, EFFECT_TYPE_SPECIAL, u, "overhead"), Distance/Speed) 

    endif

    set u = null

    return false

endfunction



private function DoEffect takes nothing returns boolean

    set bj_groupRandomCurrentPick = GetTriggerUnit()

    set bj_lastCreatedUnit = GetEventDamageSource()

    set bj_enumDestructableRadius = GetEventDamage()

    call GroupEnumUnitsInRange(bj_lastCreatedGroup, GetUnitX(bj_groupRandomCurrentPick), GetUnitY(bj_groupRandomCurrentPick), Radius, Condition(function ChooseUnits))

    return false

endfunction



private function init takes nothing returns nothing

    call AddDamageCondition( function DoEffect )

endfunction



endlibrary



//===========================================================================

// Trigger: Gluttony

//

// requires Indexor2, MainGlobals, LastCommand, UnitDamage, DataPreloader

//===========================================================================

//TESH.scrollpos=85

//TESH.alwaysfold=0

library Gluttony initializer init requires Indexor2, MainGlobals, LastCommand, UnitDamage, DataPreloader



globals

    private constant integer SpellID = 'A014'

    private constant string SpellErrorMessage = "You are already devouring a unit!"

    private constant real TimerRate = 0.2

    private constant string PathSnd = "Units\\Orc\\KotoBeast\\Devour.wav"

    private constant real PooDist = 100.

endglobals



private constant function DamageRate takes integer lvl returns real

    return 30. + 10. * (lvl - 1)

endfunction



globals

    private group isDevouring = CreateGroup()

    private group isDevoured = CreateGroup()

    private string BloodFX

    private string BloodSecFX

    private sound Sound

endglobals



private struct Devour extends array

    unit cast

    unit target

    integer uid

    real hp

    real mana

    player p

    effect f

    real tick

    

    implement AllocLoop

    

    private method destroy takes nothing returns nothing

        call GroupRemoveUnit(isDevouring, .cast)

        call DestroyEffect(.f)

        set .cast = null

        set .f = null

        call RemoveUnit(.target)

        set .target = null

        call .deallocate()

    endmethod

    

    static method Update takes nothing returns boolean

        local real R

        local real x

        local real y

        implement loop

        set R = DamageRate(GetUnitAbilityLevel(.cast, SpellID)) * TimerRate

        set .tick = .tick + HeroIndexer.period

        if .tick > TimerRate then

            set .tick = 0.

            if (.hp < 0.405 or GetWidgetLife(.cast) < 0.405) then

                if .hp < 0.405 then

                    set x = GetUnitX(.cast) + PooDist * Cos(GetUnitFacing(.cast) * bj_DEGTORAD + bj_PI)

                    set y = GetUnitY(.cast) + PooDist * Sin(GetUnitFacing(.cast) * bj_DEGTORAD + bj_PI)

                    call DoSafeDamage(.cast, CreateUnit(.p, .uid, x, y, GetUnitFacing(.cast)), 9999999., true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_UNIVERSAL, WEAPON_TYPE_WHOKNOWS)

                    call DestroyEffect(AddSpellEffectById(.uid, EFFECT_TYPE_SPECIAL, x, y))

                    call DestroyEffect(AddSpellEffectById(SpellID, EFFECT_TYPE_SPECIAL, x, y))

                endif

                call .destroy()

                return false 

            endif

            call SetWidgetLife(.cast, GetWidgetLife(.cast) + R)

            set .hp = .hp - R

            if GetRandomInt(1, 4) == 2 then

                call DestroyEffect(AddSpecialEffectTarget(BloodSecFX, .cast, "head"))

            endif

            if .mana > 0 and GetUnitState(.cast, UNIT_STATE_MANA) < GetUnitState(.cast, UNIT_STATE_MAX_MANA) and .mana > 0 then

                if .mana < R then

                    set R = .mana

                endif

                set .mana = .mana - R

                call SetUnitState(.cast, UNIT_STATE_MANA, GetUnitState(.cast, UNIT_STATE_MANA) + R)

            endif

        endif

        implement endloop

        return false

    endmethod

    

    static method Start takes nothing returns nothing

        local thistype D = thistype.allocate()

        set D.target = GetSpellTargetUnit()

        set D.cast = GetTriggerUnit()

        set D.uid = GetUnitTypeId(D.target)

        set D.hp = GetWidgetLife(D.target)

        set D.mana = GetUnitState(D.target, UNIT_STATE_MANA)

        set D.p = GetOwningPlayer(D.target)

        set D.f = AddSpecialEffectTarget(BloodFX, D.cast, "head")

        set D.tick = 0.

        call SetSoundPitch(Sound,GetRandomReal(0.75,1.25))

        call SetSoundVolume(Sound, 127)

        call SetSoundDistances(Sound, 600, 10000)

        call SetSoundDistanceCutoff(Sound, 3000)

        call AttachSoundToUnit(Sound, D.cast)

        call StartSound(Sound)

        call GroupAddUnit(isDevouring, D.cast)

        call UnitRemoveBuffs(D.target, true, true)

        call PauseUnit(D.target, true)

        call ShowUnit(D.target, false)

    endmethod

endstruct



private function Conditions takes nothing returns boolean

    return GetSpellAbilityId() == SpellID

endfunction



private function OnOrder takes nothing returns nothing

     local unit u = GetTriggerUnit()

     if IsUnitInGroup(u,isDevouring) then

        call SimError(GetOwningPlayer(u),SpellErrorMessage)

        call RedoPreviousOrder(u)

     endif

     set u = null

endfunction



private function init takes nothing returns nothing

    call HeroIndexer.AddCode(function Devour.Update)

    call RegisterAnyUnitEvent( EVENT_PLAYER_UNIT_SPELL_EFFECT, function Conditions, function Devour.Start )

    call RegisterAnyUnitEvent( EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER, function Conditions, function OnOrder )

    set Sound = CreateSound(PathSnd, false, true, false, 10, 10, "")

    set BloodFX    = GetAbilityEffectById(SpellID,EFFECT_TYPE_SPECIAL,1)

    set BloodSecFX = GetAbilityEffectById(SpellID,EFFECT_TYPE_SPECIAL,2)

    call PreloadAbility(SpellID, "cripple", false)

endfunction



endlibrary

//===========================================================================

// Trigger: NetherVortex

//

// requires Indexor2, ProjSys, DamageCredit, DataPreloader

//===========================================================================

//TESH.scrollpos=115

//TESH.alwaysfold=0

library NetherVortex initializer init requires Indexor2, ProjSys, DamageCredit, DataPreloader



globals

    private constant integer  SpellID     = 'A00E' // Spell rawcode. Based on Silence

    private constant real     MaxDamage   = 50. // maximum damage dealt (if the unit is in the middle of the vortex)

    private constant string   StealAttach = "origin"

    private constant real     Speed       = 100.

    private constant real     DamageFXDur = 1.033 // effect duration

    

    private          string   VortexFX

    private          string   StealFX

    private          string   DamageFX

endglobals



private constant function AOE takes integer level returns real

    return 200. + 75. * (level - 1)

endfunction



private constant function Dur takes integer level returns real

    return 16. + 4. * (level - 1) // values taken from Silence lol!!

endfunction



private function GetManaEnemies takes nothing returns boolean

    return IsUnitEnemy(GetFilterUnit(), bj_groupEnumOwningPlayer) and GetWidgetLife(GetFilterUnit()) > 0.405 and GetUnitState(GetFilterUnit(), UNIT_STATE_MAX_MANA) > 0.

endfunction



private function StealMana takes nothing returns nothing

    set bj_meleeNearestMineDist = bj_meleeNearestMineDist + GetUnitState(GetEnumUnit(), UNIT_STATE_MANA)

    set bj_forLoopAIndex = bj_forLoopAIndex + 1

    call SetUnitState(GetEnumUnit(), UNIT_STATE_MANA, 0.)

    call DestroyEffect(AddSpecialEffectTarget(StealFX, GetEnumUnit(), StealAttach))

endfunction



private function ReturnRemainingMana takes nothing returns nothing

    if GetWidgetLife(GetEnumUnit()) > 0.405 then

        call SetUnitState(GetEnumUnit(), UNIT_STATE_MANA, GetUnitState(GetEnumUnit(), UNIT_STATE_MANA) + bj_meleeNearestMineDist)

        call DestroyEffect(AddSpecialEffectTarget(StealFX, GetEnumUnit(), StealAttach))

    endif

endfunction



private function Damage takes integer level, unit u, location p returns real

    local real m = -MaxDamage / AOE(level)

    local real range = SquareRoot((GetUnitX(u) - GetLocationX(p))*(GetUnitX(u) - GetLocationX(p)) + (GetUnitY(u) - GetLocationY(p))*(GetUnitY(u) - GetLocationY(p)))

    return m * range + MaxDamage

endfunction



private struct NetherVortex extends array    

    unit caster

    integer level

    group Units //Stores the units affected by the vortex

    real Mana//Stores the mana stolen of all the affected units

    integer count // stores the number of units affected by the spell

    location p

    real VortexCounter

    effect vortex

    player pl

    

    implement AllocLoop

    

    static method create takes unit c, location p returns thistype

        local thistype NV = thistype.allocate()

        if NV.Units == null then

            set NV.Units = CreateGroup()

        endif

        set NV.caster = c

        set NV.pl = GetOwningPlayer(c)

        set NV.level = GetUnitAbilityLevel(c, SpellID)

        set NV.p = p

        set NV.vortex = AddSpecialEffectLoc(VortexFX, p)

        set NV.VortexCounter = 0.

        set bj_groupEnumOwningPlayer = GetOwningPlayer(c)

        call GroupEnumUnitsInRangeOfLoc(NV.Units, p, AOE(GetUnitAbilityLevel(c, SpellID)), Condition(function GetManaEnemies))

        set bj_meleeNearestMineDist = 0.

        set bj_forLoopAIndex = 0

        call ForGroup(NV.Units, function StealMana)

        set NV.Mana = bj_meleeNearestMineDist

        set NV.count = bj_forLoopAIndex

        set c = null

        return NV

    endmethod

    

    method destroy takes nothing returns nothing

        set .caster = null

        if .count != 0 then

            set bj_meleeNearestMineDist = .Mana / .count

            call ForGroup(.Units, function ReturnRemainingMana)

        endif

        call GroupClear(.Units)

        call DestroyEffect(.vortex)

        call RemoveLocation(.p)

        set .vortex = null

        set .p = null

        call .deallocate()

    endmethod

    

    private static method RemoveDeadUnits takes nothing returns nothing

        local thistype NV = thistype(bj_forLoopAIndex)

        local real a

        if GetWidgetLife(GetEnumUnit()) < 0.405 then

            call GroupRemoveUnit(NV.Units, GetEnumUnit())

            set NV.count = NV.count - 1

        else

            set a = Atan3(GetUnitX(GetEnumUnit()), GetUnitY(GetEnumUnit()), GetLocationX(NV.p), GetLocationY(NV.p))

            call SetUnitX(GetEnumUnit(), GetUnitX(GetEnumUnit()) + Speed * HeroIndexer.period * Cos(a))

            call SetUnitY(GetEnumUnit(), GetUnitY(GetEnumUnit()) + Speed * HeroIndexer.period * Sin(a))

        endif

    endmethod

    

    private static method GetEnemies takes nothing returns boolean

        local unit u = GetFilterUnit()

        local thistype D = thistype(bj_forLoopAIndex)

        local real dmg

        if IsUnitEnemy(u, GetOwningPlayer(D.caster)) and GetWidgetLife(u) > 0.405 then

            set dmg = Damage(D.level, u, D.p) * HeroIndexer.period

            set D.Mana = D.Mana - dmg * GetUnitAbilityLevel(D.caster, SpellID) / 10.

            call UnitDamageTarget(DamageCredit(D.caster, D.pl), u, dmg, false, false, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_MAGIC, WEAPON_TYPE_WHOKNOWS) 

            call TEonUnit.Start(u, DamageFX, "chest", DamageFXDur)

        endif

        set u = null

        return false

    endmethod



    static method Update takes nothing returns boolean

        implement loop

        if (.VortexCounter > Dur(.level) or .Mana <= 0. or .count <= 0) then

            call .destroy() 

        else

            set .VortexCounter = .VortexCounter + HeroIndexer.period

            set bj_forLoopAIndex = integer(this)

            call ForGroup(.Units, function thistype.RemoveDeadUnits)

            call GroupEnumUnitsInRangeOfLoc(bj_lastCreatedGroup, .p, AOE(.level), Condition(function thistype.GetEnemies))

        endif

        implement endloop

        return false

    endmethod

endstruct



private function Conditions takes nothing returns boolean

    if GetSpellAbilityId() == SpellID then

        call NetherVortex.create(GetTriggerUnit(), GetSpellTargetLoc())

    endif

    return false

endfunction



//===========================================================================

private function init takes nothing returns nothing

    call HeroIndexer.AddCode(function NetherVortex.Update)

    call RegisterAnyUnitEvent( EVENT_PLAYER_UNIT_SPELL_EFFECT, function Conditions, null )

    set VortexFX = GetAbilityEffectById(SpellID, EFFECT_TYPE_SPECIAL, 0)

    set StealFX = GetAbilityEffectById(SpellID, EFFECT_TYPE_SPECIAL, 1)

    set DamageFX = GetAbilityEffectById(SpellID, EFFECT_TYPE_SPECIAL, 2)

    call PreloadAbility(SpellID, "silence", false)

endfunction



endlibrary







//===========================================================================

// Trigger: TributeoftheCursed

//

// requires Indexor2, DummyCast, RegisterAnyUnitEvent

//===========================================================================

//TESH.scrollpos=0

//TESH.alwaysfold=0

library TributeoftheCursed initializer init requires Indexor2, DummyCast, RegisterAnyUnitEvent



globals

    private constant integer SpellID    = 'A01E' //SpellID, based on Magic shield

    private constant integer BuffID     = 'B008' //BuffID of the dummy ability

    private integer  array   DummyAbil           //The ability that increase damage in percentage

    private constant boolean KillTarget = true   //Indicates if the target unit is killed

    private constant real    Range      = 500.   // Spell Range

    private constant string  Order      = "antimagicshell"

    private constant string  DummyOrder = "innerfire"

endglobals



private function Conditions takes nothing returns boolean

    local integer level

    local unit c = GetTriggerUnit()

    local unit t = GetSpellTargetUnit()

    if GetSpellAbilityId() == SpellID then

        set level = R2I(100. * GetWidgetLife(t) / GetUnitState(t, UNIT_STATE_MAX_LIFE))

        call DummyCastOnTarget( t, c, DummyAbil[GetUnitAbilityLevel(c, SpellID)], level, DummyOrder, false)

        if KillTarget then

            call UnitDamageTarget(c, t, 9999999999999., false, true, null, null, null)

        endif

    endif

    set c = null

    set t = null

    return false

endfunction



private function GetAlliedSummoned takes nothing returns boolean

    local unit u = null

    if bj_makeUnitRescuableFlag and IsUnitAlly(u, GetOwningPlayer(bj_lastCreatedUnit)) and IsUnitType(u, UNIT_TYPE_SUMMONED) == true and GetWidgetLife(u) > 0.405 then

        call IssueTargetOrder(bj_lastCreatedUnit, Order, u)

        set bj_makeUnitRescuableFlag = false

    endif

    set u = null

    return false

endfunction



private function AIActions takes nothing returns boolean 

    set bj_lastCreatedUnit = GetTriggerUnit()

    set bj_makeUnitRescuableFlag = true 

    if GetPlayerController(GetOwningPlayer(bj_lastCreatedUnit)) == MAP_CONTROL_COMPUTER and GetUnitAbilityLevel(bj_lastCreatedUnit, SpellID) > 0 and GetUnitAbilityLevel(bj_lastCreatedUnit, BuffID) < 1 then

        call GroupEnumUnitsInRange(bj_lastCreatedGroup, GetUnitX(bj_lastCreatedUnit), GetUnitY(bj_lastCreatedUnit), Range, Condition(function GetAlliedSummoned))

    endif

    set bj_lastCreatedUnit = null

    return false

endfunction



private function init takes nothing returns nothing

    call RegisterAnyUnitEvent( EVENT_PLAYER_UNIT_SPELL_EFFECT, function Conditions, null )

    call RegisterAnyUnitEvent( EVENT_PLAYER_UNIT_ATTACKED, function AIActions, null )

    set DummyAbil[1] = 'A035'

    set DummyAbil[2] = 'A036'

    set DummyAbil[3] = 'A037'

    call PreloadAbility(DummyAbil[1], DummyOrder, false)

    call PreloadAbility(DummyAbil[2], DummyOrder, false)

    call PreloadAbility(DummyAbil[3], DummyOrder, false)

endfunction



endlibrary



//===========================================================================

// Trigger: AuraofDamnation

//

// requires DataPreloader, UnitDamage

//===========================================================================

//TESH.scrollpos=0

//TESH.alwaysfold=0

library AuraofDamnation initializer Init requires DataPreloader, UnitDamage



globals

    private constant integer SpellID = 'A01V' // spell ID, based on Brilliance Aura

    private constant integer BuffID  = 'B00Y' // buff ID

    private constant real    AOE     = 900. // Aura area of effect

    

    private          string        ManaFX

endglobals



private function ApplyMana takes nothing returns nothing

    local unit u = GetEnumUnit()

    call SetUnitState(u, UNIT_STATE_MANA, GetUnitState(u, UNIT_STATE_MANA) + bj_meleeNearestMineDist)

    call DestroyEffect(AddSpecialEffectTarget(ManaFX, u, "overhead"))

    set u = null

endfunction



private function GetAllies takes nothing returns boolean

    return GetWidgetLife(GetFilterUnit()) > 0.405 and IsUnitAlly(GetFilterUnit(), GetOwningPlayer(bj_meleeNearestMine)) and GetUnitState(GetFilterUnit(), UNIT_STATE_MAX_MANA) > 0

endfunction



private function GetAuraOwner takes nothing returns boolean

    return GetUnitAbilityLevel(GetFilterUnit(), SpellID) > 0

endfunction



private function IsDead takes nothing returns boolean

    local unit u = GetTriggerUnit()

    if GetUnitAbilityLevel(u, BuffID) > 0 and GetWidgetLife(u) - GetEventDamage() < 0.405 then

        call GroupEnumUnitsInRange(bj_lastCreatedGroup, GetUnitX(u), GetUnitY(u), AOE, Condition(function GetAuraOwner))

        set bj_meleeNearestMine = FirstOfGroup(bj_lastCreatedGroup)

        if bj_meleeNearestMine != null then

            call GroupEnumUnitsInRange(bj_lastCreatedGroup, GetUnitX(bj_meleeNearestMine), GetUnitY(bj_meleeNearestMine), AOE, Condition(function GetAllies))

            set bj_groupCountUnits = 0

            call ForGroup(bj_lastCreatedGroup, function CountUnitsInGroupEnum)

            set bj_meleeNearestMineDist = GetUnitState(u, UNIT_STATE_MANA) / RMaxBJ(bj_groupCountUnits, 1)

            call ForGroup(bj_lastCreatedGroup, function ApplyMana)

        endif

        call GroupClear(bj_lastCreatedGroup)

    endif

    set u = null

    return false

endfunction



//===========================================================================

private function Init takes nothing returns nothing

    call AddDamageCondition(function IsDead)

    set ManaFX = GetAbilityEffectById(SpellID, EFFECT_TYPE_SPECIAL, 0)

    call PreloadAbility(SpellID, "", false)

endfunction



endlibrary



//===========================================================================

// Trigger: SoulofDarkness

//

// requires TimedEffects, UnitDamage

//===========================================================================

//TESH.scrollpos=0

//TESH.alwaysfold=0

//***************************************************************************************************************

//*                                                                                                             *

//*                                           Soul of Darkness Spell.                                           *

//*                                                By Moyack.                                                   *

//*                                                  V.2.0.                                                     *

//*                                                                                                             *

//***************************************************************************************************************

library SoulofDarkness initializer init requires TimedEffects, UnitDamage



globals

    private constant integer BuffID  = 'B012' //BuffID

    private constant integer DummyFX = 'A01W' //Dummy spell ID, used to show the lightning effect, based on Finger of Death

    private constant string  BoltOrd = "fingerofdeath" // the string order that activates the dummyFX ability

    private constant real    AOE     = 800.

    private constant real    height  = 60. // returns the dummy flying height

    private constant real    BoltDur = 0.5 // returns how much the lightning bolt should be shown

endglobals



private function IsDamaged takes nothing returns boolean

    local unit c = GetTriggerUnit()

    local real dam = GetEventDamage()

    local unit t = GetEventDamageSource()

    if c != t and dam > 0 and GetUnitAbilityLevel(c, BuffID) > 0 and IsUnitInRange(t, c, AOE) then

        call TBolt.Start(c, t, DummyFX, 1, BoltOrd, height, BoltDur)

        call UnitDamageTarget(c, t, dam, true, true, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_UNIVERSAL, WEAPON_TYPE_WHOKNOWS)

    endif

    set c = null

    set t = null

    return false

endfunction



//===========================================================================

function init takes nothing returns nothing

    call AddDamageCondition( function IsDamaged )

endfunction



endlibrary







//===========================================================================

// Trigger: LavaBombs

//

// requires RegisterAnyUnitEvent, Indexor2, UnitDamage, DamageCredit, TimedEffects

//===========================================================================

//TESH.scrollpos=56

//TESH.alwaysfold=0

library LavaBombs initializer init requires RegisterAnyUnitEvent, Indexor2, UnitDamage, DamageCredit, TimedEffects, DataPreloader



globals

    private constant integer SpellID = 'A00R' // Spell RawCode

    private constant integer BuffID  = 'B01I' // Buff Rawcode

    private constant real    AOE     = 200.

    private constant real    Damage  = 10.    // damage dealt to the units which pass over the exploded land

    private constant real    FXDur   = 10.    // the fire effect duration in the area

    private constant real    dt      = FXDur / 10.

    private constant integer FireSpots = 5    // Number of fire spots generated by the spell

    private constant real    Speed   = 700.   // Missile Speed

endglobals



private constant function Dam takes integer level returns real

    return 65. + 30. * (level - 1)

endfunction



private struct data extends array

    unit caster

    real x

    real y

    real tick

    real dur

    real kaboom

    integer lvl

    boolean show

    

    implement AllocLoop

    

    static method update takes nothing returns boolean

        local unit u

        local integer i = 0

        implement loop

        set .tick = .tick + HeroIndexer.period

        if .show and .tick > dt then // Do periodic damage on AOE

            set .tick = 0.

            call GroupEnumUnitsInRange(bj_lastCreatedGroup, .x, .y, AOE, True)

            loop

                set u = FirstOfGroup(bj_lastCreatedGroup)

                exitwhen u == null

                call TEonUnit.Start(u, GetAbilityEffectById(SpellID, EFFECT_TYPE_SPECIAL, 0), "chest", dt)

                call UnitDamageTarget(DamageCredit(.caster, GetOwningPlayer(.caster)), u, Damage * dt * .lvl, false, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_FIRE, null)

                call GroupRemoveUnit(bj_lastCreatedGroup, u)

            endloop

        endif

        set .dur = .dur + HeroIndexer.period

        if not show and .dur > kaboom then // do the kaboom effect!!!!

            loop

                exitwhen i > FireSpots

                call TEffect.Start(AddSpecialEffect(GetAbilityEffectById(SpellID, EFFECT_TYPE_SPECIAL, GetRandomInt(1,2)), .x + GetRandomReal(-AOE, AOE), .y + GetRandomReal(-AOE, AOE)), FXDur)

                set i = i + 1

            endloop

            call GroupEnumUnitsInRange(bj_lastCreatedGroup, .x, .y, AOE, True)

            loop

                set u = FirstOfGroup(bj_lastCreatedGroup)

                exitwhen u == null

                if IsUnitEnemy(u, GetOwningPlayer(.caster)) and not IsUnitType(u, UNIT_TYPE_DEAD) and not IsUnitType(u, UNIT_TYPE_FLYING) then

                    call UnitDamageTarget(DamageCredit(.caster, GetOwningPlayer(.caster)), u, Dam(GetUnitAbilityLevel(.caster, SpellID)), false, false, ATTACK_TYPE_SIEGE, DAMAGE_TYPE_FIRE, null) 

                endif

                call GroupRemoveUnit(bj_lastCreatedGroup, u)

            endloop

            set .show = true

        endif

        if .dur > FXDur then

            set .caster = null

            call .deallocate()

        endif

        implement endloop

        return false

    endmethod

    

    static method create takes unit c, real x, real y returns thistype

        local thistype d = thistype.allocate()

        set d.caster = c

        set d.x = x

        set d.y = y

        set d.tick = 0.

        set d.dur = 0.

        set d.show = false

        set d.kaboom = Dist(GetUnitX(c), GetUnitY(c), x, y) / Speed

        set d.lvl = GetUnitAbilityLevel(c, SpellID)

        return d

    endmethod

endstruct



private function Effect takes nothing returns boolean

    local unit u = GetTriggerUnit()

    if GetSpellAbilityId() == SpellID then

        call data.create(u, GetSpellTargetX(), GetSpellTargetY())

    endif

    set u = null

    return false 

endfunction



private function init takes nothing returns nothing

    call HeroIndexer.AddCode( function data.update )

    call PreloadAbility(SpellID, "clusterrockets", false)

    call RegisterAnyUnitEvent(EVENT_PLAYER_UNIT_SPELL_EFFECT, function Effect, null)

endfunction



endlibrary//===========================================================================

// Trigger: FierceArrow

//

// requires Indexor2, RegisterAnyUnitEvent, ProjSys, MainGlobals, DamageCredit

//===========================================================================

//TESH.scrollpos=23

//TESH.alwaysfold=0

library FierceArrow initializer init requires Indexor2, RegisterAnyUnitEvent, ProjSys, MainGlobals, DamageCredit



globals

    private constant integer SpellID = 'A00S'

    private constant integer BuffID  = 'B01K'

    private constant real    DPS     = 10. // damage per second

    private constant real    Drag    = 500. // Distance which the target unit will drag

    private constant real    Speed   = 1500. //Movement speed

    private constant real    AOE     = 116. // Area of effect to stick allied units

    private constant real    dt      = 0.1 

    private constant real    dangle  = bj_PI / 10. // Angle range to catch units

endglobals



private struct data extends array

    unit c

    unit t

    boolean on

    real tick

    group g

    static real Sep = 116. // this value is to define the separation between units

    

    implement AllocLoop

    

    static method DoDamage takes nothing returns nothing

        call UnitDamageTarget(DamageCredit(bj_lastCreatedUnit, GetOwningPlayer(bj_lastCreatedUnit)), GetEnumUnit(), DPS * dt, true, true, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_FIRE, WEAPON_TYPE_WHOKNOWS)

    endmethod

    

    static method update takes nothing returns boolean

        local unit u

        implement loop

        if GetUnitAbilityLevel(.t, BuffID) > 0 and not .on then // checks if the unit has been reached by the arrow

            set .on = true

            if not IsUnitType(.t, UNIT_TYPE_FLYING) then

                call GroupEnumUnitsInRange(bj_lastCreatedGroup, GetUnitX(.t), GetUnitY(.t), AOE, True)

                loop

                    set u = FirstOfGroup(bj_lastCreatedGroup)

                    exitwhen u == null

                    if not IsUnitType(u, UNIT_TYPE_MECHANICAL) and not IsUnitType(u, UNIT_TYPE_FLYING) and IsUnitAlly(u, GetOwningPlayer(.t)) then

                        call GroupAddUnit(.g, u)

                        if u == .t then

                            call KnockBack(u, Drag, GetUnitFacing(.c) * bj_DEGTORAD, 0., Speed, null, null, true)

                        else

                            call KnockBack(u, Drag, GetUnitsAngle(.t, u), 0., Speed, null, null, true)

                        endif

                    endif

                    call GroupRemoveUnit(bj_lastCreatedGroup, u)

                endloop

            else

                set u = null    

            endif

        endif

        set .tick = .tick + HeroIndexer.period // deals the damage

        if .tick > dt then

            set .tick = 0.

            set bj_lastCreatedUnit = .c

            call ForGroup(.g, function thistype.DoDamage)

            set bj_lastCreatedUnit = null

        endif

        if GetUnitAbilityLevel(.t, BuffID) < 1 and .on then // checks if the effect buff has finished

            set .c = null

            set .t = null

            call GroupClear(.g)

            call .deallocate()

        endif

        implement endloop

        return false

    endmethod

    

    static method start takes unit c, unit t, integer level returns nothing

        local thistype d = thistype.allocate()

        set d.c = c

        set d.t = t

        set d.on = false

        set d.tick = 0.

        if d.g == null then

            set d.g = CreateGroup()

        endif

    endmethod

endstruct



private function DoStuff takes nothing returns boolean

    local unit u = GetTriggerUnit()

    local unit t = GetSpellTargetUnit()

    if GetSpellAbilityId() == SpellID and GetUnitAbilityLevel(t, BuffID) < 1 then

        call data.start(u, t, GetUnitAbilityLevel(u, SpellID))

    endif

    set u = null

    set t = null

    return false

endfunction



private function init takes nothing returns nothing

    call HeroIndexer.AddCode(function data.update)

    call PreloadAbility(SpellID, "thunderbolt", false)

    call RegisterAnyUnitEvent(EVENT_PLAYER_UNIT_SPELL_EFFECT, function DoStuff, null)

endfunction



endlibrary//===========================================================================

// Trigger: FireExplosion

//

// requires RegisterAnyUnitEvent, DummyCast

//===========================================================================

//TESH.scrollpos=0

//TESH.alwaysfold=0

library FireExplosion initializer init requires RegisterAnyUnitEvent, DummyCast



globals

    private constant integer SpellID = 'A00T'

    private constant integer Cloud   = 'o005' // summoned unit

    private constant integer DummyAb = 'A038' // invisible ability

    private constant real    AOE     = 200.

endglobals



private function Conditions takes nothing returns boolean

    local unit u

    local unit c = GetSummonedUnit()

    local integer level = GetUnitAbilityLevel(GetSummoningUnit(), SpellID)

    if GetUnitTypeId(c) == Cloud then

        call DummyCastOnTarget(c, c, 'A027', 1, "stomp", true) // stuns enemies near the explosion

        call GroupEnumUnitsInRange(bj_lastCreatedGroup, GetUnitX(c), GetUnitY(c), AOE, True)

        loop

            set u = FirstOfGroup(bj_lastCreatedGroup)

            exitwhen u == null

            if IsUnitAlly(u, GetOwningPlayer(c)) then

                call DummyCastOnTarget(c, u, DummyAb, level, "invisibility", false)

            endif

            call GroupRemoveUnit(bj_lastCreatedGroup, u)

        endloop

    endif

    set c = null

    return false

endfunction



private function init takes nothing returns nothing

    call PreloadAbility(SpellID, "ward", true)

    call RegisterAnyUnitEvent(EVENT_PLAYER_UNIT_SUMMON, function Conditions, null)

endfunction



endlibrary//===========================================================================

// Trigger: Havoc

//

// requires RegisterAnyUnitEvent, Indexor2, TimedEffects

//===========================================================================

//TESH.scrollpos=19

//TESH.alwaysfold=0

library Havoc initializer init requires RegisterAnyUnitEvent, Indexor2, TimedEffects



globals

    private constant integer SPELLID = 'A00Y'

    private constant integer DUMMYAB = 'A039' // ability which produce illusions

    private constant integer DUMMYBU = 'B00U' // buff effect on units

    private constant real    AOE     = 1000.

    private constant real    DT      = 1.

endglobals



private struct data extends array

    integer order

    unit c

    real tick

    

    implement AllocLoop

    

    static method Cool takes nothing returns boolean

        local unit u

        implement loop

        if .order != GetUnitCurrentOrder(.c) then

            set .c = null

            call .deallocate()

        else

            set .tick = .tick  + HeroIndexer.period

            if .tick > DT then

                set .tick = 0.

                call GroupEnumUnitsInRange(bj_lastCreatedGroup, GetUnitX(.c), GetUnitY(.c), AOE*1.2, True)

                loop

                    set u = FirstOfGroup(bj_lastCreatedGroup)

                    exitwhen u == null

                    if IsUnitEnemy(u, GetOwningPlayer(.c)) and not IsUnitType(u, UNIT_TYPE_DEAD) and GetUnitAbilityLevel(u, DUMMYBU) < 1 then

                        call DummyCastTarget(.c, u, DUMMYAB, GetRandomInt(1,4), "firebolt")

                    endif

                    call GroupRemoveUnit(bj_lastCreatedGroup, u)

                endloop

            endif

        endif

        set u = null

        implement endloop

        return false

    endmethod

    

    static method Start takes unit c returns nothing

        local thistype d = thistype.allocate()

        set d.c = c

        set d.tick = DT + 1.

        set d.order = GetUnitCurrentOrder(c)

        set c = null

    endmethod

endstruct



private function DoStuff takes nothing returns boolean

    if GetSpellAbilityId() == SPELLID then

        call data.Start(GetTriggerUnit())

    endif

    return false

endfunction



private function init takes nothing returns nothing

    call HeroIndexer.AddCode(function data.Cool)

    call RegisterAnyUnitEvent(EVENT_PLAYER_UNIT_SPELL_EFFECT, function DoStuff, null)

endfunction



endlibrary//===========================================================================

// Trigger: Summon Artifact Pit

//===========================================================================

//TESH.scrollpos=0

//TESH.alwaysfold=0

scope SummonPit initializer init 



globals

    private constant integer UnitID = 'h006'

endglobals



//===========================================================================

private function init takes nothing returns nothing

    call PreloadUnitType(UnitID)

endfunction



endscope



//===========================================================================

// Trigger: Slave Harvest

//

// requires DataPreloader, RegisterAnyUnitEvent, TimedEffects

//===========================================================================

//TESH.scrollpos=0

//TESH.alwaysfold=0

library SlaveHarvest initializer init requires DataPreloader, RegisterAnyUnitEvent, TimedEffects



globals

    private constant string  Order   = "harvest"

    private constant integer SpellID = 'A00U'// Spell ID

    private constant real    radius  = 150. // range used to put random fire on minegolds

    private constant real    dt      = 2.1  // fire effect duration

    private constant real    TreeBlight = 100. // set the blight radius for trees

    private          string  FireFX

endglobals



private function Conditions takes nothing returns boolean

    local destructable d = GetOrderTargetDestructable()

    local real x

    local real y

    local real a = GetRandomReal(0, 359) * bj_DEGTORAD

    if OrderId2String(GetIssuedOrderId()) == Order and not PlayerIsNaga(GetOwningPlayer(GetTriggerUnit())) then

        if d != null then

            set x = GetWidgetX(d)

            set y = GetWidgetY(d)

            call TEffect.Start(AddSpecialEffect(FireFX, x, y), 10. * dt)

            if not IsPointBlighted(x, y) then

                call SetBlight(GetOwningPlayer(GetTriggerUnit()), x, y, TreeBlight, true)

            endif

        else

            set x = GetUnitX(GetOrderTargetUnit()) + radius * Cos(a)

            set y = GetUnitY(GetOrderTargetUnit()) + radius * Sin(a)

            if not IsPointBlighted(GetUnitX(GetOrderTargetUnit()), GetUnitY(GetOrderTargetUnit())) then

                call SetBlight(GetOwningPlayer(GetTriggerUnit()), GetUnitX(GetOrderTargetUnit()), GetUnitY(GetOrderTargetUnit()), radius + TreeBlight, true)

            endif

            if not IsPointBlighted(x, y) then

                call SetBlight(GetOwningPlayer(GetTriggerUnit()), x, y, TreeBlight, true)

            endif

            call TEffect.Start(AddSpecialEffect(FireFX, x, y), dt)

        endif

    endif

    set d = null

    return false

endfunction



//===========================================================================

private function init takes nothing returns nothing

    call RegisterAnyUnitEvent( EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER, function Conditions, null )

    set FireFX = GetAbilityEffectById(SpellID, EFFECT_TYPE_EFFECT, 0)

    call PreloadAbility(SpellID, Order, true)

endfunction



endlibrary



//===========================================================================

// Trigger: DoubleAttack

//

// requires Alloc, DataPreloader, ProjSys, TimedEffects, SpellBlocker

//===========================================================================

//TESH.scrollpos=0

//TESH.alwaysfold=0

library DoubleAttack initializer init requires Alloc, DataPreloader, ProjSys, TimedEffects, SpellBlocker



globals

    private constant integer SpellID   = 'A00Z'

    private constant real    MinRange  = 200. // the range where the caster will deal damage

    private constant real    Height    = 100. // Max Height the caster will fly

    private constant real    Dur       = 1.134 // fly time duration

    private constant real    Speed     = 1500. // movement speed

    private constant real    TagHeight = 150. //the initial height when the damage tag will start.

    // AI values

    private constant real    LifePerc  = 0.5 // victims life required to cast it

    private constant string  Order     = "slow" // the spell order

    

    private          string  FX

    private          string  Blood

endglobals



private struct data extends array

    unit t

    boolean on

    

    implement Alloc

    

    method destroy takes nothing returns nothing

        set .on = false

        set .t = null

        call .deallocate()

    endmethod

    

    static method Add takes unit t returns thistype

        local thistype D = thistype.allocate()

        set D.t = t

        set D.on = true

        return D

    endmethod

endstruct



private function Damage takes integer level returns real

    return level * 50.0 * GetRandomReal(0.7, 1.3)

endfunction



private function ShowTag takes string value, unit c, real z returns nothing

    local texttag tx = CreateTextTag()

    call SetTextTagText(tx, value, 0.025)

    call SetTextTagPos(tx, GetUnitX(c), GetUnitY(c), z)

    call SetTextTagColor(tx, 255, 0, 0, 255)

    call SetTextTagVelocity(tx, 0, 0.03)

    call SetTextTagVisibility(tx, true)

    call SetTextTagFadepoint(tx, 2)

    call SetTextTagLifespan(tx, 3)

    call SetTextTagPermanent(tx, false)

endfunction



private function start takes nothing returns boolean

    local unit u = GetUnitProjectile()

    call TEffect.Start(AddSpecialEffect(FX, GetUnitX(u), GetUnitY(u)), Dur)

    call SetUnitSpellInvulnerable(u, true)

    set u = null

    return false

endfunction



private function end takes nothing returns boolean

    local unit c = GetUnitProjectile()

    local data t = data( GetData(c, SpellID) )

    if IsUnitInRange(c, t.t, MinRange) then

        call UnitDamageTarget( c, t.t, Damage(GetUnitAbilityLevel(c,SpellID)), true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_UNKNOWN, WEAPON_TYPE_WHOKNOWS )

        call ShowTag(I2S(R2I(Damage(GetUnitAbilityLevel(c,SpellID)))) + "!", t.t, TagHeight)

        call TEffect.Start(AddSpecialEffectTarget(Blood, t.t, "chest"), Dur)

    else

        call ShowTag("MISS!", c, TagHeight)

    endif

    if t.on then

        call t.destroy()

    endif

    call SetUnitSpellInvulnerable(c, false)

    call SetUnitFlyHeight(c, 0., 0.)

    call ClearValue(c, SpellID)

    set c = null

    return false

endfunction



private function Conditions takes nothing returns boolean

    local unit c = GetTriggerUnit()

    local unit t = GetSpellTargetUnit()

    if GetSpellAbilityId() == SpellID then

        call StoreData(c, SpellID, integer(data.Add(t)))

        call KnockBack(c, GetUnitsDist(c, t), GetUnitsAngle(c, t), Height, Speed, function start, function end, false)

    endif

    set c = null

    set t = null

    return false

endfunction



private function AIConditions takes nothing returns boolean

    local unit u = GetAttacker()

    local unit v = GetTriggerUnit()

    if GetPlayerController(GetOwningPlayer(u)) == MAP_CONTROL_COMPUTER and GetUnitAbilityLevel(u, SpellID) > 0 and GetWidgetLife(v)/GetUnitState(v, UNIT_STATE_MAX_LIFE ) < LifePerc then

        return IssueTargetOrder(u, Order, v)

    endif

    set u = null

    set v = null

    return false

endfunction



//===========================================================================

private function init takes nothing returns nothing

    call RegisterAnyUnitEvent( EVENT_PLAYER_UNIT_SPELL_EFFECT, function Conditions, null )

    call RegisterAnyUnitEvent( EVENT_PLAYER_UNIT_ATTACKED, function AIConditions, null )

    set FX = GetAbilityEffectById(SpellID, EFFECT_TYPE_SPECIAL, 0)

    set Blood = GetAbilityEffectById(SpellID, EFFECT_TYPE_SPECIAL, 1)

    call PreloadAbility(SpellID, Order, false)

endfunction



endlibrary

//===========================================================================

// Trigger: TreacherousAttack

//

// requires Alloc, ProjSys, TimedEffects, SpellBlocker

//===========================================================================

//TESH.scrollpos=0

//TESH.alwaysfold=0

library Treacherous initializer init requires Alloc, ProjSys, TimedEffects, SpellBlocker



globals

    private constant integer SpellID = 'A01N'

    private constant real    offset  = 116. // distance between the target and the attacker when the attacker reach the target

    private constant real    Damage  = 100. //additional damage dealt

    private constant real    Speed   = 900. // movement duration.

    private constant real    Deg     = bj_PI / 2.

    // AI values

    private constant real    LifePerc  = 0.5 // victims life required to cast it

    private constant string  Order     = "cripple" // the spell order

    

    private          string  DustFX

endglobals



private struct data extends array

    unit t

    boolean on

    implement Alloc

    

    method destroy takes nothing returns nothing

        set .on = false

        set .t = null

        call .deallocate()

    endmethod

    

    static method Add takes unit t returns data

        local thistype D = thistype.allocate()

        set D.t = t

        set D.on = true 

        return D

    endmethod

endstruct



private function start takes nothing returns boolean

    local unit c = GetUnitProjectile()

    local data d = data(GetData(c, SpellID))

    call SetUnitVertexColor(c, 255, 255, 255, 150)

    call SetUnitSpellInvulnerable(c, true)

    call SetUnitAnimation(c, "Stand")

    call TEffect.Start(AddSpecialEffectTarget(DustFX, c, "origin"), GetUnitsDist(c, d.t)/Speed)

    set c = null

    return false 

endfunction



private function move takes nothing returns boolean

    local Projectile P = GetMovingProjectile()

    local data t = data( GetData(P.p, SpellID) )

    if GetWidgetLife(t.t) < 0.405 then

        call P.destroy()

    else

        if not IsUnitInRangeXY(t.t, P.pf.x, P.pf.y, offset) then

            call P.pf.setdata(GetUnitX(t.t), GetUnitY(t.t), 0.)

            call P.SetData(P.p, P.pi, P.pf, P.vi, P.vf, P.tf, P.DV, P.pU)

        endif

        call SetUnitFacing(P.p, Atan2(P.vv.y, P.vv.x) * bj_RADTODEG) // used to give direction to the moving unit

    endif

    return false 

endfunction



private function end takes nothing returns boolean

    local unit c = GetUnitProjectile()

    local data t = data( GetData(c, SpellID) )

    call ClearData(c)

    call SetUnitAnimation(c, "stand")

    call SetUnitVertexColor(c, 255, 255, 255, 255)

    call SetUnitSpellInvulnerable(c, false)

    if GetWidgetLife(t.t) > 0.405 then

        call IssueTargetOrder(c, "attack", t.t)

        call UnitDamageTarget(c, t.t, Damage, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_SHADOW_STRIKE, WEAPON_TYPE_METAL_HEAVY_SLICE)

    endif

    if t.on then

        call t.destroy()

    endif

    set c = null

    return false 

endfunction



private function Conditions takes nothing returns boolean

    return GetSpellAbilityId() == SpellID

endfunction



private function Actions takes nothing returns nothing

    local unit c = GetTriggerUnit()

    local unit t = GetSpellTargetUnit()

    local real a = GetUnitFacing(t) * bj_DEGTORAD

    local real x = GetUnitX(t) - offset * Cos(a)

    local real y = GetUnitY(t) - offset * Sin(a)

    local vector pi = vector.create(GetUnitX(c), GetUnitY(c), 0.)

    local vector pf = vector.create(x, y, 0.)

    local vector vi = vector.create(Speed, GetUnitFacing(c) * bj_DEGTORAD + GetRandomReal( -Deg, Deg), 0.)

    local vector vf = vector.create(1., a, 0.)

    local Projectile P = Projectile.createSpherical(c, pi, pf, vi, vf, GetUnitsDist(c, t) / Speed, true, true)

    call StoreData(c, SpellID, integer(data.Add(t)))

    call P.SetStartCode(function start)

    call P.SetMoveCode(function move)

    call P.SetEndCode(function end)

    set c = null

    set t = null

endfunction



private function AIConditions takes nothing returns boolean

    local unit u = GetAttacker()

    local unit v = GetTriggerUnit()

    if GetPlayerController(GetOwningPlayer(u)) == MAP_CONTROL_COMPUTER and GetUnitAbilityLevel(u, SpellID) > 0 and GetWidgetLife(v)/GetUnitState(v, UNIT_STATE_MAX_LIFE ) < LifePerc then

        return IssueTargetOrder(u, Order, v)

    endif

    set u = null

    set v = null

    return false

endfunction



//===========================================================================

private function init takes nothing returns nothing

    call RegisterAnyUnitEvent( EVENT_PLAYER_UNIT_SPELL_EFFECT, function Conditions, function Actions )

    call RegisterAnyUnitEvent( EVENT_PLAYER_UNIT_ATTACKED, function AIConditions, null )

    set DustFX = GetAbilityEffectById(SpellID, EFFECT_TYPE_SPECIAL, 0)

    call Preload(DustFX)

endfunction



endlibrary

//===========================================================================

// Trigger: RabidBite

//===========================================================================

//TESH.scrollpos=32

//TESH.alwaysfold=0

library RabidBite initializer init requires Indexor2, MicroTable, DamageCredit

//Configuration

globals

    private constant integer    SpellID  = 'A022' //Rabid Bite's spell rawcode

    private constant integer    BuffID   = 'B018' //Rabid Bite's spell rawcode

    private constant real       dt       = 0.5 //Rabid Bite's timer rate to deal damage

    private constant damagetype WhatType = DAMAGE_TYPE_DISEASE //Rabid Bite's damage type

endglobals



private constant function DamagePerSecond takes integer level returns real

    return 3. * level //Rabid Bite's damage dealt

endfunction



private struct RabidB extends array

    static group G = CreateGroup()



    unit caster

    unit target

    integer level

    boolean hasbuff

    real tick

    player p

    

    implement AllocLoop

    

    static method create takes unit caster, unit target returns thistype

        local thistype a = thistype.allocate()

        set a.caster = caster

        set a.target = target

        set a.level = GetUnitAbilityLevel(caster,SpellID)

        set a.hasbuff = false // always this tag must start as false

        set a.p = GetOwningPlayer(caster)

        set a.tick = 0.

        call GroupAddUnit(thistype.G, target)

        call StoreData(target, SpellID, integer(a))

        return a

    endmethod

    

    method destroy takes nothing returns nothing

        call ClearValue(.target, SpellID)

        call GroupRemoveUnit(thistype.G, .target)

        set .caster = null

        set .target = null

        call .deallocate()

    endmethod

    

    static method Update takes nothing returns boolean

        implement loop

            set .tick = .tick + UnitIndexer.period

            if .tick > dt then

                set .tick = 0.

                if not .hasbuff and GetUnitAbilityLevel(.target, BuffID) > 0 then

                    set .hasbuff = true

                endif

                if .hasbuff and GetUnitAbilityLevel(.target, BuffID) > 0 then

                    call DoSafeDamage(DamageCredit(.caster, .p), .target, DamagePerSecond(.level) * dt, false, false, ATTACK_TYPE_CHAOS, WhatType, WEAPON_TYPE_WHOKNOWS)

                endif

                if .hasbuff and GetUnitAbilityLevel(.target, BuffID) < 1 then

                    call .destroy()

                endif

            endif

        implement endloop

        return false 

    endmethod

endstruct



private function Conditions takes nothing returns boolean

    local unit c = GetTriggerUnit()

    local unit t = GetSpellTargetUnit()

    if GetSpellAbilityId() == SpellID then

        if IsUnitInGroup(t, RabidB.G) then

            set RabidB( GetData(t, SpellID) ).caster = c

        else

            call RabidB.create(c, t)

        endif

    endif

    set c = null

    set t = null

    return false

endfunction



private function init takes nothing returns nothing

    call UnitIndexer.AddCode( function RabidB.Update )

    call RegisterAnyUnitEvent( EVENT_PLAYER_UNIT_SPELL_EFFECT, function Conditions, null )

endfunction



endlibrary//===========================================================================

// Trigger: Torment

//

// requires UnitDamage

//===========================================================================

//TESH.scrollpos=0

//TESH.alwaysfold=0

library Torment initializer init requires UnitDamage



globals

    private constant integer BuffID  = 'B01B' //Torment's buff rawcode

    private constant real    Percent = 0.35 // Indicates the damage return to the attacker

endglobals



//Casting functions

private function Return takes nothing returns boolean

    local unit u = GetTriggerUnit()

    local unit a = GetEventDamageSource()

    if GetUnitAbilityLevel(a, BuffID) > 0 then

        call UnitDamageTarget(u, a, GetEventDamage() * Percent, false, true, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_UNIVERSAL, WEAPON_TYPE_WHOKNOWS)

        call DestroyEffect(AddSpellEffectTargetById(BuffID, EFFECT_TYPE_SPECIAL, a, "chest"))

    endif

    set u = null

    set a = null

    return false

endfunction



private function init takes nothing returns nothing

    call AddDamageCondition( function Return )

endfunction



endlibrary//===========================================================================

// Trigger: Drain Magic

//

// requires Alloc, MainGlobals, TimedEffects, DataPreloader

//===========================================================================

//TESH.scrollpos=85

//TESH.alwaysfold=0

library DrainMagic initializer init requires Alloc, MainGlobals, TimedEffects, DataPreloader



globals

    private constant integer SpellID = 'A010'

    private constant real    CastAoE = 250.

    private constant real    Damage  = 250.

    

    private          string   ManaRegFX

    private          string   HealthRegFX

endglobals



private constant function ManaGain takes integer level, integer summons returns real

    return (20.*level)*summons

endfunction



private constant function GiveAoE takes integer level returns real

    return 250.*level

endfunction



private struct DrainM extends array

    integer buffs

    integer summoned

    

    implement Alloc

    

    method destroy takes nothing returns nothing

        call .deallocate()

    endmethod

    

    static method create takes unit c, integer buffs, integer summoned returns thistype

        local thistype a = thistype.allocate()

        set a.buffs = buffs

        set a.summoned = summoned

        call StoreData(c, SpellID, integer(a))

        return a

    endmethod

endstruct



private function FilterAlly takes nothing returns boolean

    return IsUnitAlly(GetFilterUnit(),bj_groupEnumOwningPlayer)

endfunction



private function CountBuffs takes nothing returns nothing

    set bj_destInRegionDiesCount = bj_destInRegionDiesCount + UnitCountBuffsEx(GetEnumUnit(), false, false, true, false, false, false, false)

    if IsUnitType(GetEnumUnit(), UNIT_TYPE_SUMMONED) == true then

        set bj_groupCountUnits = bj_groupCountUnits + 1

    endif

endfunction



private function CountManaUnits takes nothing returns nothing

    if GetUnitState(GetEnumUnit(), UNIT_STATE_MAX_MANA) > 0 then

        set bj_groupCountUnits = bj_groupCountUnits + 1

    endif

endfunction



private function DealEffect takes nothing returns nothing

    if GetUnitState(GetEnumUnit(), UNIT_STATE_MAX_MANA) > 0 then

        call SetUnitState(GetEnumUnit(), UNIT_STATE_MANA, GetUnitState(GetEnumUnit(), UNIT_STATE_MANA) + bj_enumDestructableRadius)

        call TEffect.Start(AddSpecialEffectTarget(ManaRegFX, GetEnumUnit(), "origin"), 1.)

    endif

    call SetWidgetLife(GetEnumUnit(), GetWidgetLife(GetEnumUnit()) + bj_randomSubGroupChance)

    call TEffect.Start(AddSpecialEffectTarget(HealthRegFX, GetEnumUnit(), "origin"), 1.)

endfunction





private function Conditions takes nothing returns boolean

    return GetSpellAbilityId() == SpellID

endfunction



private function Count takes nothing returns nothing

    local unit c = GetTriggerUnit()

    call GroupEnumUnitsInRange(bj_lastCreatedGroup, GetSpellTargetX(), GetSpellTargetY(), CastAoE, True)

    set bj_destInRegionDiesCount = 0

    set bj_groupCountUnits = 0

    call ForGroup(bj_lastCreatedGroup, function CountBuffs)

    if bj_destInRegionDiesCount > 0 or bj_groupCountUnits > 0 then

        call DrainM.create(c, bj_destInRegionDiesCount, bj_groupCountUnits)

    else

        call IssueImmediateOrder(c, "stop")

        call SimError(GetOwningPlayer(c), "There's no buffs or summoned units to drain...")

    endif

    call GroupClear(bj_lastCreatedGroup)

    set c = null

endfunction



private function Actions takes nothing returns nothing

    local unit c = GetTriggerUnit()

    local DrainM DM = DrainM(GetData(c, SpellID))

    local integer l = GetUnitAbilityLevel(c,SpellID)

    call GroupEnumUnitsInRange(bj_lastCreatedGroup, GetUnitX(c), GetUnitY(c), GiveAoE(l), Condition(function FilterAlly))

    call GroupRemoveUnit(bj_lastCreatedGroup, c)

    set bj_groupCountUnits = 0

    call ForGroup(bj_lastCreatedGroup, function CountUnitsInGroupEnum)

    if bj_groupCountUnits > 0 then

        set bj_randomSubGroupChance = DM.summoned * Damage / bj_groupCountUnits

    else

        set bj_randomSubGroupChance = 0.

    endif

    set bj_groupCountUnits = 0

    call ForGroup(bj_lastCreatedGroup, function CountManaUnits)

    if bj_groupCountUnits > 0 then

        set bj_enumDestructableRadius = ManaGain(l, DM.buffs) / bj_groupCountUnits

    else

        set bj_enumDestructableRadius = 0.

    endif

    call ForGroup(bj_lastCreatedGroup, function DealEffect)

    call ClearValue(c, SpellID)

    call DM.destroy()

    call GroupClear(bj_lastCreatedGroup)

    set c = null

endfunction



private function AIConditions takes nothing returns boolean

    if GetPlayerController(GetOwningPlayer(GetAttacker())) == MAP_CONTROL_COMPUTER and GetUnitAbilityLevel(GetAttacker(), SpellID) > 0 and UnitCountBuffsEx(GetTriggerUnit(), false, false, true, false, false, false, false) > 0 then

        return IssueTargetOrder(GetAttacker(), "drain", GetTriggerUnit())

    endif

    return false

endfunction



private function init takes nothing returns nothing

    call RegisterAnyUnitEvent( EVENT_PLAYER_UNIT_SPELL_EFFECT, function Conditions, function Actions )

    call RegisterAnyUnitEvent( EVENT_PLAYER_UNIT_SPELL_CAST, function Conditions, function Count )

    call RegisterAnyUnitEvent( EVENT_PLAYER_UNIT_ATTACKED, function AIConditions, null )

    set ManaRegFX = GetAbilityEffectById(SpellID, EFFECT_TYPE_SPECIAL, 1)

    set HealthRegFX = GetAbilityEffectById(SpellID, EFFECT_TYPE_SPECIAL, 2)

    call PreloadAbility(SpellID, "drain", false)

endfunction



endlibrary//===========================================================================

// Trigger: Vampire Claymore

//

// requires DataPreloader, UnitDamage, TimedEffects

//===========================================================================

//TESH.scrollpos=0

//TESH.alwaysfold=0

library VampireClaymore initializer init requires DataPreloader, UnitDamage, TimedEffects



globals

    private constant integer SpellID = 'A02B'

    private constant integer UpgradeID = 'R00G'

    private constant unitstate State = UNIT_STATE_MANA

    private constant real    Dur = 5.

    

    private string           RestoreFX

endglobals



private constant function Manastealpercent takes integer level returns real

    return .15

endfunction



private function Manasteal takes nothing returns boolean

    local unit a = GetEventDamageSource()

    local real r

    if GetUnitAbilityLevel(a, SpellID) > 0 and GetPlayerTechCount(GetOwningPlayer(a),UpgradeID,true) == 2 and GetUnitState(a, UNIT_STATE_MANA) < GetUnitState(a, UNIT_STATE_MAX_MANA) and IsUnitType(GetTriggerUnit(), UNIT_TYPE_MECHANICAL) == false then

        set r = GetEventDamage() * Manastealpercent(GetUnitAbilityLevel(a,SpellID))

        call TEffect.Start(AddSpecialEffectTarget(RestoreFX, a, "overhead"), 1.)

        call SetUnitState(a, State, GetUnitState(a,State) + r)

    endif

    set a = null

    return false

endfunction



private function init takes nothing returns nothing

    call AddDamageCondition( function Manasteal )

    set RestoreFX = GetAbilityEffectById(SpellID,EFFECT_TYPE_SPECIAL,0)

    call PreloadAbility(SpellID, "", true)

endfunction



endlibrary//===========================================================================

// Trigger: Manipulation

//

// requires Indexor2, SetUnitMaxState, UnitDamage

//===========================================================================

//TESH.scrollpos=65

//TESH.alwaysfold=0

library Manipulation initializer init requires Indexor2, SetUnitMaxState, DataPreloader



globals

    private constant integer  SpellID = 'A029' // Spell ID

    private constant integer  BuffID  = 'B019' //Buff ID

    private constant string   Order   = "unholyfrenzy"

    private constant boolean  ChangeColour = true // change the color of the target unit.

    private constant real     TimerRate = .1

endglobals



private struct MindC extends array

    static group CU = CreateGroup()



    unit target

    player towner

    unit caster

    real maxhitp

    real tick

    implement AllocLoop

    

    static method create takes unit c, unit t returns thistype

        local thistype a = MindC.allocate()

        set a.target = t

        set a.towner = GetOwningPlayer(t)

        set a.caster = c

        set a.maxhitp = GetUnitState(t, UNIT_STATE_MAX_LIFE)

        set a.tick = 0.

        call SetUnitMaxState(t, UNIT_STATE_MAX_LIFE, R2I(a.maxhitp + GetWidgetLife(c)))

        call GroupAddUnit(thistype.CU, t)

        if GetOwningPlayer(c) != a.towner then

            call SetUnitOwner(t, GetOwningPlayer(c), ChangeColour)

        endif

        call ShowUnit(c, false)

        return a

    endmethod

    

    method destroy takes nothing returns nothing

        call SetUnitX(.caster, GetUnitX(.target))

        call SetUnitY(.caster, GetUnitY(.target))

        call DestroyEffect(AddSpellEffectTargetById(SpellID, EFFECT_TYPE_SPECIAL, .caster, "chest"))

        call ShowUnit(.caster, true)

        if .towner != GetOwningPlayer(.caster) then

            call SetUnitOwner(.target, .towner, ChangeColour)

        endif

        call GroupRemoveUnit(thistype.CU, .target)

        call SetUnitMaxState(.target, UNIT_STATE_MAX_LIFE, R2I(.maxhitp))

        if GetWidgetLife(.target) < .405 and GetWidgetLife(.caster) > 0.405 then

            call KillUnit(.caster)

        endif

        if IsUnitSelected(.target, .towner) then

            call SelectUnitAddForPlayer(.caster, .towner)

        endif

        set .target = null

        set .caster = null

        call .deallocate()

    endmethod

    

    static method Update takes nothing returns boolean

        implement loop

        set .tick = .tick + UnitIndexer.period

        if .tick > TimerRate then

            set .tick = 0.

            if (GetUnitAbilityLevel(.target, BuffID) < 1 or GetWidgetLife(.caster) < 0.405) then

                call .destroy()

            endif

        endif

        implement endloop

        return false 

    endmethod

endstruct

    

private function Conditions takes nothing returns boolean

    return GetSpellAbilityId() == SpellID

endfunction



private function Check takes nothing returns nothing

    local unit t = GetSpellTargetUnit()

    local unit c = GetTriggerUnit()

    if GetUnitAbilityLevel(t, SpellID) > 0 then

        call IssueImmediateOrder(c, "stop")

        call SimError(GetOwningPlayer(t),"You can't target a unit with Manipulation Ability...")

        set c = null

        set t = null

        return

    endif

    if IsUnitInGroup(t,MindC.CU) or GetUnitAbilityLevel(c, BuffID) > 0 then

        call IssueImmediateOrder(c, "stop")

        call SimError(GetOwningPlayer(t),"This unit is already affected by Manipulation")

    endif

    set t = null

    set c = null

endfunction



private function Actions takes nothing returns nothing

    local unit t = GetSpellTargetUnit()

    if not IsUnitInGroup(t, MindC.CU) then 

        call MindC.create(GetTriggerUnit(), t)

    endif

    set t = null

endfunction



private function init takes nothing returns nothing

    call UnitIndexer.AddCode(function MindC.Update)

    call RegisterAnyUnitEvent( EVENT_PLAYER_UNIT_SPELL_CAST, function Conditions, function Check )

    call RegisterAnyUnitEvent( EVENT_PLAYER_UNIT_SPELL_EFFECT, function Conditions, function Actions )

    call PreloadAbility(SpellID, Order, true)

endfunction



endlibrary//===========================================================================

// Trigger: Blood Aroma

//

// requires RegisterAnyUnitEvent, TimedEffects

//===========================================================================

//TESH.scrollpos=0

//TESH.alwaysfold=0

// Blood aroma, by Av3n

// Improvements by moyack

// 2009.

library BloodAroma initializer init requires RegisterAnyUnitEvent, TimedEffects



globals

    private constant integer SpellID = 'A02M' // Blood Aroma (Item) id

    private constant integer BonusID = 'A02I' // Blood Aroma (Speed Bonus) id

    private constant string  OrderID = "bloodlust"

    private constant real    AoE = 250. // Blood Aroma's area of effect

endglobals



private function Cond takes nothing returns boolean

    local unit u = GetFilterUnit()

    if GetWidgetLife(u) > 0.405 and IsUnitAlly(u, bj_groupEnumOwningPlayer) and IsUnitType(u, UNIT_TYPE_STRUCTURE) == false then

        call DummyCastTarget(bj_lastCreatedUnit, u, BonusID, 1, OrderID)

    endif

    set u = null

    return false

endfunction



private function Conditions takes nothing returns boolean

    if GetSpellAbilityId() == SpellID then

        set bj_lastCreatedUnit = GetTriggerUnit()

        set bj_groupEnumOwningPlayer = GetOwningPlayer(bj_lastCreatedUnit)

        call GroupEnumUnitsInRange(bj_lastCreatedGroup, GetSpellTargetX(), GetSpellTargetY(), AoE, Condition(function Cond))

    endif

    return false

endfunction



private function init takes nothing returns nothing

    call RegisterAnyUnitEvent( EVENT_PLAYER_UNIT_SPELL_EFFECT, function Conditions, null )

endfunction



endlibrary

//===========================================================================

// Trigger: Spring of Azshara

//

// requires Indexor2, RegisterAnyUnitEvent, TimedEffects

//===========================================================================

//TESH.scrollpos=0

//TESH.alwaysfold=0

library DoSplash initializer init requires Indexor2, RegisterAnyUnitEvent, TimedEffects



globals

    private constant integer UnitID = 'o003'

    private constant string  Order  = "healingspray"

    private constant string  Place  = "chest"

    private constant real    AOE    = 500.

    private constant real    dt     = 1.

    private constant real    Heal   = 5.

    private constant real    TE     = 1.8

endglobals



struct data extends array

    unit s

    real tick

    boolean on

    

    implement AllocLoop

    

    method destroy takes nothing returns nothing

        set .s = null

        set .on = false

        call .deallocate()

    endmethod

    

    static method create takes unit s returns thistype

        local thistype D = thistype.allocate()

        set D.s = s

        set D.tick = 0.

        set D.on = true

        return D

    endmethod

    

    static method DoEffect takes nothing returns boolean

        local unit u = GetFilterUnit()

        if IsUnitAlly(u, bj_groupEnumOwningPlayer) and GetWidgetLife(u) > 0.405 and GetWidgetLife(u) < GetUnitState(u, UNIT_STATE_MAX_LIFE) and IsUnitType(u, UNIT_TYPE_MECHANICAL) == false then

            call SetWidgetLife(u, GetWidgetLife(u) + Heal)

            call TEffect.Start(AddSpellEffectTargetById(UnitID, EFFECT_TYPE_SPECIAL, u, Place), TE)

        endif

        set u = null

        return false

    endmethod



    static method Update takes nothing returns boolean

        implement loop

        set this.tick = this.tick + UnitIndexer.period

        if this.tick > dt then

            set this.tick = 0.

            set bj_groupEnumOwningPlayer = GetOwningPlayer(this.s)

            call GroupEnumUnitsInRange(bj_lastCreatedGroup, GetUnitX(this.s), GetUnitY(this.s), AOE, Condition(function thistype.DoEffect))

            if GetWidgetLife(this.s) < 0.405 and this.on then

                call this.destroy()

            endif

        endif

        implement endloop

        return false

    endmethod

endstruct



private function Conditions takes nothing returns boolean

    local unit u = GetSummonedUnit()

    if GetUnitTypeId(u) == UnitID then

        call data.create(u)

        call IssuePointOrder( u, Order, GetUnitX(u), GetUnitY(u))

    endif

    set u = null

    return false

endfunction



//===========================================================================

private function init takes nothing returns nothing

    call UnitIndexer.AddCode(function data.Update)

    call RegisterAnyUnitEvent( EVENT_PLAYER_UNIT_SUMMON, function Conditions, null )

endfunction



endlibrary

//===========================================================================

// Trigger: NerubianGuardian

//===========================================================================

//TESH.scrollpos=0

//TESH.alwaysfold=0

//***************************************************************************************************************

//* This trigger is used to set in the summoned unit the level of the ability "Spider Eggs"

//*

scope NerubGuardian initializer init



globals

    private constant integer SpellID       = 'A033' // the ability that summons the Nerubian Guardian

    private constant integer SummonSpellID = 'A00V' // The ability in the Nerubian that must be levelized

endglobals



private function Conditions takes nothing returns boolean

    local unit u = GetSummoningUnit()

    local unit t = GetSummonedUnit()

    if GetUnitAbilityLevel(u, SpellID) > 0 then

        call SetUnitAbilityLevel(t, SummonSpellID, GetUnitAbilityLevel(u, SpellID))

    endif

    set u = null

    set t = null

    return false

endfunction



//===========================================================================

private function init takes nothing returns nothing

    call RegisterAnyUnitEvent( EVENT_PLAYER_UNIT_SUMMON, function Conditions, null )

endfunction



endscope//===========================================================================

// Trigger: SpiderEggs

//===========================================================================

//TESH.scrollpos=0

//TESH.alwaysfold=0

scope SpiderEggs initializer init



globals

    private constant integer UnitID = 'o001' // the unit rawcode

    private constant integer SpiderUnit = 'nspd' // the produced spider by the eggs

endglobals



private function Conditions takes nothing returns boolean

    local unit c = GetTriggerUnit()

    local unit u

    if GetUnitTypeId(GetTriggerUnit()) == UnitID and GetKillingUnit() == null then

        set u = CreateUnit(GetOwningPlayer(c), SpiderUnit, GetUnitX(c), GetUnitY(c), GetUnitFacing(c))

        call UnitAddType(u, UNIT_TYPE_SUMMONED)

    endif

    set c = null

    set u = null

    return false 

endfunction



//===========================================================================

private function init takes nothing returns nothing

    call RegisterAnyUnitEvent( EVENT_PLAYER_UNIT_DEATH, function Conditions, null)

endfunction



endscope//===========================================================================

// Trigger: AI Hydra Control

//

// requires RegisterAnyUnitEvent

//===========================================================================

//TESH.scrollpos=0

//TESH.alwaysfold=0

library HydraAI initializer init requires RegisterAnyUnitEvent



globals

    private constant real     Radius        = 1000. // range where the trigger will count units

    private constant integer  SplitHydraID  = 'n00L' // the unit to be splitted

    private constant integer  FusionHydraID = 'n00N' // the unit to be fusioned

    private          boolexpr Cnd1 // stores the getHydras condition

    private          boolexpr Cnd2 // stores the getAllies condition

    private          boolexpr Cnd3 // stores the getEnemies condition

endglobals



private function GetAllies takes nothing returns boolean

    return IsUnitAlly(GetFilterUnit(), bj_groupEnumOwningPlayer)

endfunction



private function GetEnemies takes nothing returns boolean

    return IsUnitEnemy(GetFilterUnit(), bj_groupEnumOwningPlayer)

endfunction



private function GetHydras takes nothing returns boolean

    return GetUnitTypeId(GetFilterUnit()) == SplitHydraID

endfunction



private function SplitConditions takes nothing returns boolean

    local unit t = GetTriggerUnit()

    local player p = GetOwningPlayer(t)

    local unit u

    local integer c1 

    local integer c2 

    local integer c3

    if GetPlayerController(p) == MAP_CONTROL_COMPUTER then

        set bj_groupEnumOwningPlayer = GetOwningPlayer(t)

        // Get the amount of allied units

        call GroupEnumUnitsInRange(bj_lastCreatedGroup, GetUnitX(t), GetUnitY(t), Radius, Cnd2)

        set bj_groupCountUnits = 0

        call ForGroup(bj_lastCreatedGroup, function CountUnitsInGroupEnum)

        set c1 = bj_groupCountUnits

        call GroupClear(bj_lastCreatedGroup)

        // Get the amount of enemy units

        call GroupEnumUnitsInRange(bj_lastCreatedGroup, GetUnitX(t), GetUnitY(t), Radius, Cnd3)

        set bj_groupCountUnits = 0

        call ForGroup(bj_lastCreatedGroup, function CountUnitsInGroupEnum)

        set c2 = bj_groupCountUnits

        call GroupClear(bj_lastCreatedGroup)

        // Get the amount of Naga Hydras

        call GroupEnumUnitsInRange(bj_lastCreatedGroup, GetUnitX(t), GetUnitY(t), Radius, Cnd1)

        set bj_groupCountUnits = 0

        call ForGroup(bj_lastCreatedGroup, function CountUnitsInGroupEnum)

        set c3 = bj_groupCountUnits

        call GroupClear(bj_lastCreatedGroup)

        if (c1 < c2) and (c3 > 0) then

            call GroupEnumUnitsOfPlayer(bj_lastCreatedGroup, p, Cnd1)

            loop

                set u = FirstOfGroup(bj_lastCreatedGroup)

                exitwhen u == null

                if IsUnitInRange(t, u, Radius) then

                    call IssueImmediateOrder( u, "decouple" )

                endif

                call GroupRemoveUnit(bj_lastCreatedGroup, u)

            endloop

        endif

    endif

    set t = null

    return false 

endfunction



//***************************************************************************************************************

//* APPLY HYDRA FUSION Trigger conditions

//*

private function FusionConditions takes nothing returns boolean

    local unit t = GetTriggerUnit()

    if GetPlayerController(GetOwningPlayer(t)) == MAP_CONTROL_COMPUTER and GetWidgetLife(t) / GetUnitState(t, UNIT_STATE_MAX_LIFE) < 0.5 and GetUnitTypeId(t) == FusionHydraID then

        call IssueImmediateOrder( t, "coupleinstant" )

    endif

    set t = null

    return false

endfunction



//===========================================================================

private function init takes nothing returns nothing

    set Cnd1 = Condition( function GetHydras )

    set Cnd2 = Condition( function GetAllies )

    set Cnd3 = Condition( function GetEnemies )

    call RegisterAnyUnitEvent( EVENT_PLAYER_UNIT_ATTACKED, function SplitConditions, null )

    call RegisterAnyUnitEvent( EVENT_PLAYER_UNIT_ATTACKED, function FusionConditions, null )

endfunction



endlibrary

//===========================================================================

// Trigger: Protect weak units

//

// requires MicroTable

//===========================================================================

//TESH.scrollpos=0

//TESH.alwaysfold=0

library ProtectWeak initializer init requires RegisterAnyUnitEvent, MicroTable



globals

    private constant real Radius = 250.

    private constant real Perc   = 0.3

    private constant real PercR  = 0.7

    private constant integer UID  = 'n00J' // transport turtle

    private constant integer UID2 = 'n00I' // Demon Zeppelin

    private player P

endglobals



private struct data extends array

    private static key A

    static group G = CreateGroup()

    unit t

    unit l

    

    implement Alloc

    

    method destroy takes nothing returns nothing

        call GroupRemoveUnit(thistype.G, .l)

        call ClearValue(.l, thistype.A)

        set .t = null

        set .l = null

        call .deallocate()

    endmethod

    

    static method Load takes unit t, unit u returns nothing

        local thistype D = thistype.allocate()

        set D.t = t

        set D.l = u

        call GroupAddUnit(thistype.G, u)

        call StoreData(u, thistype.A, integer(D))

    endmethod

    

    static method GetTransporter takes unit u returns unit 

        return thistype(GetData(u, thistype.A)).t

    endmethod

    

    static method Check takes nothing returns nothing

        local unit u = GetEnumUnit()

        local unit t

        if GetPlayerController(GetOwningPlayer(u)) == MAP_CONTROL_COMPUTER and GetWidgetLife(u) / GetUnitState(u, UNIT_STATE_MAX_LIFE) > PercR then

            set t = thistype.GetTransporter(u)

            call IssueTargetOrder(t, "unload", u)

            call thistype(GetData(u, thistype.A)).destroy()

        endif

        set t = null

        set u = null

    endmethod

    

    static method Loop takes nothing returns nothing

        call ForGroup(thistype.G, function thistype.Check)

    endmethod

endstruct



private function IsTransport takes nothing returns boolean

    return IsUnitTransport(GetFilterUnit()) and GetOwningPlayer(GetFilterUnit()) == P and GetWidgetLife(GetFilterUnit()) > 0.405

endfunction



private function CheckTransport takes nothing returns boolean

    local unit u = GetTriggerUnit()

    local unit t

    if GetPlayerController(GetOwningPlayer(u)) == MAP_CONTROL_COMPUTER and GetWidgetLife(u) / GetUnitState(u, UNIT_STATE_MAX_LIFE) < Perc then

        set P = GetOwningPlayer(u)

        call GroupEnumUnitsInRange(bj_lastCreatedGroup, GetUnitX(u), GetUnitY(u), Radius, Condition(function IsTransport))

        set t = FirstOfGroup(bj_lastCreatedGroup)

        if t != null and IssueTargetOrder(t, "load", u) then

            call data.Load(t, u)

        endif

        call GroupClear(bj_lastCreatedGroup)

    endif

    set u = null

    set t = null

    return false

endfunction



private function init takes nothing returns nothing

    call RegisterAnyUnitEvent(EVENT_PLAYER_UNIT_ATTACKED, function CheckTransport, null)

    call TimerStart(CreateTimer(), 1.5, true, function data.Loop)

endfunction



endlibrary//===========================================================================

// Trigger: Low gold

//

// requires Multiboard

//===========================================================================

//TESH.scrollpos=0

//TESH.alwaysfold=0

// Checks if Ai player requires to use devotion points to convert them into gold

library LowGold initializer init requires Multiboard



globals

	private constant real MinGold = 500. // sets the min gold that the player should have before trading its DevPoints

endglobals





// Low Gold Actions

private function Conditions takes nothing returns boolean

    local player p = GetTriggerPlayer()

    local unit u

    if stats(GetPlayerId(p)).devpoints >= lumberPayment and GetPlayerTypedUnitCount(p, UnitId2String(GetShop(p)), false, true) > 0 then

        set bj_groupEnumTypeId = GetShop(p)

        call GroupEnumUnitsOfPlayer(bj_lastCreatedGroup, p, filterGetUnitsOfPlayerAndTypeId)

        set u = FirstOfGroup(bj_lastCreatedGroup)

        call GroupClear(bj_lastCreatedGroup)

        if u != null then

            call IssueImmediateOrder(u, "gold2lumber")

        endif

    endif

    set u = null

    return false 

endfunction

//===========================================================================

private function init takes nothing returns nothing

    local integer i = 0

    local trigger t = CreateTrigger(  )

    loop

        exitwhen i == 12

        if GetPlayerController(Player(i)) == MAP_CONTROL_COMPUTER and GetPlayerSlotState(Player(i)) == PLAYER_SLOT_STATE_PLAYING then

            call TriggerRegisterPlayerStateEvent( t, Player(i), PLAYER_STATE_RESOURCE_GOLD, LESS_THAN, MinGold )

        endif

        set i = i + 1

    endloop

    call TriggerAddCondition( t, Condition( function Conditions ) )

    set t = null

endfunction



endlibrary

//===========================================================================

// Trigger: Low lumber

//

// requires Multiboard

//===========================================================================

//TESH.scrollpos=2

//TESH.alwaysfold=0

// Checks if Ai player requires to use devotion points to convert them into lumber

//******************************************************************************

//*

//******************************************************************************



library LowLumber initializer init requires Multiboard



globals

	private constant real MinLumber = 100. // sets the min lumber that the player should have before trading its DevPoints

endglobals





// Low lumber Actions

private function Conditions takes nothing returns boolean

    local player p = GetTriggerPlayer()

    local unit u

    if stats(GetPlayerId(p)).devpoints >= lumberPayment and GetPlayerTypedUnitCount(p, UnitId2String(GetShop(p)), false, true) > 0 then

        set bj_groupEnumTypeId = GetShop(p)

        call GroupEnumUnitsOfPlayer(bj_lastCreatedGroup, p, filterGetUnitsOfPlayerAndTypeId)

        set u = FirstOfGroup(bj_lastCreatedGroup)

        call GroupClear(bj_lastCreatedGroup)

        if u != null then

            call IssueImmediateOrder(u, "grabtree")

        endif

    endif

    set u = null

    return false 

endfunction



//===========================================================================

private function init takes nothing returns nothing

    local integer i = 0

    local trigger t = CreateTrigger(  )

    loop

        exitwhen i == 12

        if GetPlayerController(Player(i)) == MAP_CONTROL_COMPUTER and GetPlayerSlotState(Player(i)) == PLAYER_SLOT_STATE_PLAYING then

            call TriggerRegisterPlayerStateEvent( t, Player(i), PLAYER_STATE_RESOURCE_LUMBER, LESS_THAN, MinLumber )

        endif

        set i = i + 1

    endloop

    call TriggerAddCondition( t, Condition( function Conditions ) )

    set t = null

endfunction



endlibrary

//===========================================================================

// Trigger: Random AI names

//===========================================================================

//TESH.scrollpos=125

//TESH.alwaysfold=0

library RandomAINames initializer init requires Alloc



globals

    private constant integer ANY_RACE   = 0

    private constant integer NAGA_RACE  = 1

    private constant integer DEMON_RACE = 2

endglobals



//! textmacro DataStruct takes NAME, REPEAT

private struct $NAME$ extends array

    static integer counter = 0

    static boolean Repeat = $REPEAT$

    string name

    integer race

    boolean on

    

    implement Alloc

    

    method destroy takes nothing returns nothing

        set .on = false

        if integer(this) == thistype.counter then

            set thistype.counter = thistype.counter - 1

        endif

        set .name = null

        call .deallocate()

    endmethod

    

    static method Add takes string s, integer Race returns nothing

        local thistype D = thistype.allocate()

        set D.name = s

        set D.race = Race

        set D.on = true

        set thistype.counter = integer(D)

    endmethod

    

    static method GetRandomName takes player p returns string 

        local integer i = 0

        local integer P

        local string S

        if PlayerIsNaga(p) then

            set P = NAGA_RACE

        else

            set P = DEMON_RACE

        endif

        loop

            set i = GetRandomInt(1, thistype.counter)

            set S = thistype(i).name

            exitwhen thistype(i).on and (thistype(i).race == P or thistype(i).race == 0)

        endloop

        if not thistype.Repeat then

            call thistype(i).destroy()

        endif

        return S

    endmethod

endstruct

//! endtextmacro



//! runtextmacro DataStruct("Name", "false")

//! runtextmacro DataStruct("Title", "false")



private function SetupNames takes nothing returns nothing

    // First name part

    call Name.Add("Leviathan",     NAGA_RACE )

    call Name.Add("Cosmicat",      ANY_RACE  )

    call Name.Add("Peppers",       ANY_RACE  )

    call Name.Add("Kyrbi0",        ANY_RACE  )

    call Name.Add("Alevice",       NAGA_RACE )

    call Name.Add("Archmage",      ANY_RACE  )

    call Name.Add("Av3n",          ANY_RACE  )

    call Name.Add("Moyack",        ANY_RACE  )

    call Name.Add("Tarrasque",     DEMON_RACE)

    call Name.Add("JetFangInferno",  ANY_RACE)

    call Name.Add("Queen Azshara", NAGA_RACE )

    call Name.Add("Lady Vashj",    NAGA_RACE )

    call Name.Add("Karathress",    NAGA_RACE )

    call Name.Add("Lord Shalzaru", NAGA_RACE )

    call Name.Add("Lord Krellian", NAGA_RACE )

    call Name.Add("Naj'entus",     NAGA_RACE )

    call Name.Add("Thespia",       NAGA_RACE )

    call Name.Add("Nazjatar",      NAGA_RACE )

    call Name.Add("Kazzak",        DEMON_RACE)

    call Name.Add("Highlord Kruul",DEMON_RACE)

    call Name.Add("Talgath",       DEMON_RACE)

    call Name.Add("Baelmon",       DEMON_RACE)

    call Name.Add("Azgalor",       DEMON_RACE)

    call Name.Add("Magtheridon96", DEMON_RACE)

    call Name.Add("Arazzius",      DEMON_RACE)

    call Name.Add("Razuun",        DEMON_RACE)

    call Name.Add("Brutallus",     DEMON_RACE)

    call Name.Add("Mephistroth",   DEMON_RACE)

    call Name.Add("Patch 1.24+",   DEMON_RACE)

    // title part: Naga

    call Title.Add("The Empress",            NAGA_RACE)

    call Title.Add("The Fathom-Lord",        NAGA_RACE)

    call Title.Add("The Warlord",            NAGA_RACE)

    call Title.Add("The Overseer",           NAGA_RACE)

    call Title.Add("The Rightful Heir",      NAGA_RACE)

    call Title.Add("The Terror of the Deep", NAGA_RACE)

    call Title.Add("The Bleeding Gill",      NAGA_RACE)

    call Title.Add("The Zealous",            NAGA_RACE)

    call Title.Add("The Piranha",            NAGA_RACE)

    call Title.Add("The Maelstrom Seer",     NAGA_RACE)

    call Title.Add("The Deepstar",           NAGA_RACE)

    call Title.Add("The Shadow Eel",         NAGA_RACE)

    call Title.Add("The Kraken Hunter",      NAGA_RACE)

    call Title.Add("The Mur'gul Master",     NAGA_RACE)

    call Title.Add("Of The Rift",            NAGA_RACE)

    call Title.Add("Of The Black Depths",    NAGA_RACE)

    call Title.Add("The Kelp Spectre",       NAGA_RACE)

    call Title.Add("The Clam-shelled",       NAGA_RACE)

    call Title.Add("The Lobsterborn",        NAGA_RACE)

    // title part: Demon

    call Title.Add("The Deceiver",             DEMON_RACE)

    call Title.Add("The Doom Lord",            DEMON_RACE)

    call Title.Add("The Hound Master",         DEMON_RACE)

    call Title.Add("The Warbringer",           DEMON_RACE)

    call Title.Add("The HellRaiser",           DEMON_RACE)

    call Title.Add("The Damned",               DEMON_RACE)

    call Title.Add("The Netherfiend",          DEMON_RACE)

    call Title.Add("The Devourer",             DEMON_RACE)

    call Title.Add("The Soul-gorger",          DEMON_RACE)

    call Title.Add("The Defiler",              DEMON_RACE)

    call Title.Add("The Dreadnought",          DEMON_RACE)

    call Title.Add("The Dreadful",             DEMON_RACE)

    call Title.Add("The Wicked",               DEMON_RACE)

    call Title.Add("The Wrathful",             DEMON_RACE)

    call Title.Add("The Prideful",             DEMON_RACE)

    call Title.Add("The Envious",              DEMON_RACE)

    call Title.Add("The Sulphorous",           DEMON_RACE)

    call Title.Add("Of The Void",              DEMON_RACE)

    call Title.Add("The Unhygienic",           DEMON_RACE)

    call Title.Add("The Unpleasantly Scented", DEMON_RACE)

    call Title.Add("Of The Reeking Pits",      DEMON_RACE)

    // title part: Miscelaneous...

    call Title.Add("The Ugly",     ANY_RACE)

    call Title.Add("The Unfair",   ANY_RACE)

    call Title.Add("The Slow",     ANY_RACE)

    call Title.Add("The Harasser", ANY_RACE)

    call Title.Add("The Noob",     ANY_RACE)

    call Title.Add("The Filty one",ANY_RACE)

endfunction



private function SetName takes player p returns nothing

    call SetPlayerName(p, Name.GetRandomName(p) + " " + Title.GetRandomName(p))

endfunction



private function init takes nothing returns nothing

    local integer index = 0

    call SetupNames()

    loop

        if GetPlayerController(Player(index)) == MAP_CONTROL_COMPUTER and GetPlayerSlotState(Player(index)) == PLAYER_SLOT_STATE_PLAYING then

            call SetName(Player(index))

        endif

        set index = index + 1

        exitwhen index == bj_MAX_PLAYER_SLOTS

    endloop

    set index = 1

    loop

        exitwhen index > Name.counter and index > Title.counter

        if Name(index) != 0 then

            call Name(index).destroy()

        elseif Title(index) != 0 then

            call Title(index).destroy()

        endif

        set index = index + 1

    endloop

endfunction



endlibrary//===========================================================================

// Trigger: Cheat

//

// requires RegisterAnyUnitEvent

//===========================================================================

//TESH.scrollpos=99

//TESH.alwaysfold=0

library Cheating initializer init requires RegisterAnyUnitEvent



globals

    private constant real OFX = -250.

    private constant real OFY = 0.

    private constant integer Level = 6

    

    private          unit U = null

    private          integer array I

    private          integer ItemCounter = 0

    private          location L = null

    private          group G = CreateGroup()

endglobals



private function PlaceHero takes integer id returns nothing

    set U = CreateUnitAtLoc(Player(0), id, L, bj_UNIT_FACING )

    call SetHeroLevel( U, Level, true )

    call GroupAddUnit(G, U)

endfunction



private function PlaceUnit takes integer m, integer id returns nothing

    local integer i = 1

    loop

        exitwhen i > m

        set U = CreateUnitAtLoc(Player(0), id, L, bj_UNIT_FACING )

        call GroupAddUnit(G, U)

        set i = i+1

    endloop

endfunction



private function IsItem takes nothing returns nothing

    local integer i = 0

    local integer id = GetItemTypeId(GetManipulatedItem())

    local unit u = GetTriggerUnit()

    call TriggerSleepAction(1.)

    loop

        exitwhen i > ItemCounter

        if I[i] == id and GetInventoryIndexOfItemTypeBJ(u, id) < 1 then

            call UnitAddItemById(u, id)

            exitwhen true

        else

            set i = i+1

        endif

    endloop

    set u = null

endfunction



private function AddItem takes integer id returns nothing

    call UnitAddItemById(U, id)

    set I[ItemCounter] = id

    set ItemCounter = ItemCounter + 1

endfunction



private function Heal takes nothing returns nothing

    local unit u = GetEnumUnit()

    call SetWidgetLife(u, GetUnitState(u, UNIT_STATE_MAX_LIFE))

    call SetUnitState(u, UNIT_STATE_MANA, GetUnitState(u, UNIT_STATE_MAX_MANA))

    call UnitResetCooldown(u)

    set u = null

endfunction



private function Cheat2 takes nothing returns nothing

    call ForGroup(G, function Heal)

endfunction



private function Revive takes nothing returns nothing

    local unit u = GetTriggerUnit()

    local integer id = GetUnitTypeId(u)

    if IsUnitInGroup(u, G) then

        call TriggerSleepAction(3.)

        if IsUnitType(u, UNIT_TYPE_HERO) == true then

            call ReviveHeroLoc(u, L, true)

        else

            call RemoveUnit(u)

            call GroupRemoveUnit(G, u)

            set u = CreateUnitAtLoc(Player(0), id, L, bj_UNIT_FACING)

            call GroupAddUnit(G, u)

        endif

    endif

    set u = null

endfunction



private function Conditions takes nothing returns boolean

    return GetPlayerName(GetTriggerPlayer()) == "moyack" or GetPlayerName(GetTriggerPlayer()) == "WorldEdit"

endfunction



private function Actions takes nothing returns nothing

    local trigger T = CreateTrigger()

    call DisplayTimedTextFromPlayer(GetLocalPlayer(), 0,0,3, "Cheating!!!")

    set L = GetPlayerStartLocationLoc(Player(0))

    call MoveLocation(L, GetLocationX(L) + OFX, GetLocationY(L) + OFY)

    call SetPlayerStateBJ( Player(0), PLAYER_STATE_RESOURCE_FOOD_CAP, 100 )

    //Neutral heroes

    call PlaceHero('U008') //Arachnian Queen

    // Demon units

    call PlaceHero('U005')

    call PlaceHero('H000')

    call PlaceHero('N013')

    call PlaceHero('N014')

    // Demon Item stuff

    call AddItem('I003')

    call AddItem('I002')

    call AddItem('I001')

    call AddItem('I008')

    call AddItem('I007')

    // End Demon Item stuff

    call PlaceUnit( 2, 'n00R')

    call PlaceUnit( 2, 'n00O')

    call PlaceUnit( 2, 'n00Q')

    call PlaceUnit( 2, 'n00P')

    call PlaceUnit( 2, 'n00T')

    call PlaceUnit( 2, 'u007')

    call PlaceUnit( 1, 'n007')

    call PlaceUnit( 1, 'n00U')

    call PlaceUnit( 1, 'n015')

    call SetPlayerTechResearched(Player(0), 'R00F', 2)

    call SetPlayerTechResearched(Player(0), 'R00G', 2)

    call SetPlayerTechResearched(Player(0), 'R00E', 1)

    call SetPlayerTechResearched(Player(0), 'R00A', 1)

    call SetPlayerTechResearched(Player(0), 'R009', 1)

    // Naga Units

    call MoveLocation(L, GetLocationX(L) - (2 * OFX), GetLocationY(L))

    call PlaceHero('H002')

    call PlaceHero('H003')

    call PlaceHero('H005')

    call PlaceHero('H001')

    // Naga Item stuff

    call AddItem('I000')

    call AddItem('I005')

    call AddItem('I009')

    call AddItem('I006')

    call AddItem('will')

    // End Naga item stuff

    call PlaceUnit( 2, 'nwgs')

    call PlaceUnit( 1, 'nhyc')

    call PlaceUnit( 2, 'nnsw')

    call PlaceUnit( 1, 'n002')

    call PlaceUnit( 2, 'n00K')

    call PlaceUnit( 1, 'n00J')

    call PlaceUnit( 1, 'n012')

    call SetPlayerTechResearched(Player(0), 'Rnsi', 1)

    call SetPlayerTechResearched(Player(0), 'Rnsw', 2)

    call SetPlayerTechResearched(Player(0), 'R002', 2)

    call SetPlayerTechResearched(Player(0), 'R005', 1)

    call MoveLocation(L, GetLocationX(L) + OFX, GetLocationY(L))

    // Other stuff

    call Cheat("iseedeadpeople")

    call RegisterAnyUnitEvent(EVENT_PLAYER_UNIT_USE_ITEM, null, function IsItem)

    call RegisterAnyUnitEvent(EVENT_PLAYER_UNIT_DEATH, null, function Revive)

    call TriggerRegisterPlayerEventEndCinematic( T, Player(0) )

    call TriggerAddAction( T, function Cheat2 )

    set T = null

    call DisableTrigger(GetTriggeringTrigger())

endfunction



//===========================================================================

private function init takes nothing returns nothing

    local trigger T = CreateTrigger()

    call TriggerRegisterPlayerChatEvent( T, Player(0), "level6", true )

    call TriggerAddCondition(T, Condition(function Conditions))

    call TriggerAddAction( T, function Actions )

    set T = null

endfunction



endlibrary//===========================================================================

function InitCustomTriggers takes nothing returns nothing

    call InitTrig_HCL(  )

    call InitTrig_ARGB(  )

    call InitTrig_Board(  )

    call InitTrig_Alloc(  )

    call InitTrig_Indexor2(  )

    call InitTrig_DataPreloader(  )

    call InitTrig_MainGlobals(  )

    call InitTrig_CACHE(  )

    call InitTrig_RegisterAnyUnitEvent(  )

    call InitTrig_SpellBlocker(  )

    call InitTrig_MicroTable(  )

    call InitTrig_UnitDamage(  )

    call InitTrig_DamageCredit(  )

    call InitTrig_SetUnitMaxState(  )

    call InitTrig_MovSys(  )

    call InitTrig_ProjSys(  )

    call InitTrig_DummyCast(  )

    call InitTrig_TimedEffects(  )

    call InitTrig_LastCommand(  )

    call InitTrig_IsUnitStuck_n_jump_ability(  )

    call InitTrig_Melee_Initialization(  )

    call InitTrig_Play_Race_Music(  )

    call InitTrig_Credits(  )

    call InitTrig_Multiboard_Control(  )

    call InitTrig_Handle_Counter(  )

    call InitTrig_Devotion_points(  )

    call InitTrig_Pray_for_Gold(  )

    call InitTrig_Pray_for_Lumber(  )

    call InitTrig_Naga_Ability(  )

    call InitTrig_Poisoning_Skin(  )

    call InitTrig_Illusion(  )

    call InitTrig_SoulControl(  )

    call InitTrig_SoulThirst(  )

    call InitTrig_Betrayal(  )

    call InitTrig_WaterBurst(  )

    call InitTrig_CrushingTide(  )

    call InitTrig_Freeze(  )

    call InitTrig_Lightning_Vortex(  )

    call InitTrig_LoyaltyandSacrifice(  )

    call InitTrig_Murgulogenesis(  )

    call InitTrig_FearPoison(  )

    call InitTrig_ToxicFog(  )

    call InitTrig_WaterShield(  )

    call InitTrig_Sonic(  )

    call InitTrig_Broodlings(  )

    call InitTrig_Summon_Magic_Vault(  )

    call InitTrig_Demon_Ability(  )

    call InitTrig_Inner_Hell(  )

    call InitTrig_HellFire(  )

    call InitTrig_Sadism(  )

    call InitTrig_Fetid_Stomach(  )

    call InitTrig_Mighty_Smash(  )

    call InitTrig_Stunning_Punch(  )

    call InitTrig_Gluttony(  )

    call InitTrig_NetherVortex(  )

    call InitTrig_TributeoftheCursed(  )

    call InitTrig_AuraofDamnation(  )

    call InitTrig_SoulofDarkness(  )

    call InitTrig_LavaBombs(  )

    call InitTrig_FierceArrow(  )

    call InitTrig_FireExplosion(  )

    call InitTrig_Havoc(  )

    call InitTrig_Summon_Artifact_Pit(  )

    call InitTrig_Slave_Harvest(  )

    call InitTrig_DoubleAttack(  )

    call InitTrig_TreacherousAttack(  )

    call InitTrig_RabidBite(  )

    call InitTrig_Torment(  )

    call InitTrig_Drain_Magic(  )

    call InitTrig_Vampire_Claymore(  )

    call InitTrig_Manipulation(  )

    call InitTrig_Blood_Aroma(  )

    call InitTrig_Spring_of_Azshara(  )

    call InitTrig_NerubianGuardian(  )

    call InitTrig_SpiderEggs(  )

    call InitTrig_AI_Hydra_Control(  )

    call InitTrig_Protect_weak_units(  )

    call InitTrig_Low_gold(  )

    call InitTrig_Low_lumber(  )

    call InitTrig_Random_AI_names(  )

    call InitTrig_Cheat(  )

endfunction



//===========================================================================

function RunInitializationTriggers takes nothing returns nothing

    call ConditionalTriggerExecute( gg_trg_Random_AI_names )

endfunction



//***************************************************************************

//*

//*  Players

//*

//***************************************************************************



function InitCustomPlayerSlots takes nothing returns nothing



    // Player 0

    call SetPlayerStartLocation( Player(0), 0 )

    call SetPlayerColor( Player(0), ConvertPlayerColor(0) )

    call SetPlayerRacePreference( Player(0), RACE_PREF_RANDOM )

    call SetPlayerRaceSelectable( Player(0), true )

    call SetPlayerController( Player(0), MAP_CONTROL_USER )



    // Player 1

    call SetPlayerStartLocation( Player(1), 1 )

    call SetPlayerColor( Player(1), ConvertPlayerColor(1) )

    call SetPlayerRacePreference( Player(1), RACE_PREF_RANDOM )

    call SetPlayerRaceSelectable( Player(1), true )

    call SetPlayerController( Player(1), MAP_CONTROL_USER )



    // Player 2

    call SetPlayerStartLocation( Player(2), 2 )

    call SetPlayerColor( Player(2), ConvertPlayerColor(2) )

    call SetPlayerRacePreference( Player(2), RACE_PREF_RANDOM )

    call SetPlayerRaceSelectable( Player(2), true )

    call SetPlayerController( Player(2), MAP_CONTROL_USER )



    // Player 3

    call SetPlayerStartLocation( Player(3), 3 )

    call SetPlayerColor( Player(3), ConvertPlayerColor(3) )

    call SetPlayerRacePreference( Player(3), RACE_PREF_RANDOM )

    call SetPlayerRaceSelectable( Player(3), true )

    call SetPlayerController( Player(3), MAP_CONTROL_USER )



endfunction



function InitCustomTeams takes nothing returns nothing

    // Force: TRIGSTR_1487

    call SetPlayerTeam( Player(0), 0 )

    call SetPlayerTeam( Player(1), 0 )

    call SetPlayerTeam( Player(2), 0 )

    call SetPlayerTeam( Player(3), 0 )



endfunction



function InitAllyPriorities takes nothing returns nothing



    call SetStartLocPrioCount( 0, 2 )

    call SetStartLocPrio( 0, 0, 2, MAP_LOC_PRIO_HIGH )

    call SetStartLocPrio( 0, 1, 3, MAP_LOC_PRIO_HIGH )



    call SetStartLocPrioCount( 1, 2 )

    call SetStartLocPrio( 1, 0, 2, MAP_LOC_PRIO_HIGH )

    call SetStartLocPrio( 1, 1, 3, MAP_LOC_PRIO_HIGH )



    call SetStartLocPrioCount( 2, 3 )

    call SetStartLocPrio( 2, 0, 0, MAP_LOC_PRIO_HIGH )

    call SetStartLocPrio( 2, 1, 1, MAP_LOC_PRIO_HIGH )

    call SetStartLocPrio( 2, 2, 3, MAP_LOC_PRIO_LOW )



    call SetStartLocPrioCount( 3, 2 )

    call SetStartLocPrio( 3, 0, 0, MAP_LOC_PRIO_HIGH )

    call SetStartLocPrio( 3, 1, 1, MAP_LOC_PRIO_HIGH )

endfunction



//***************************************************************************

//*

//*  Main Initialization

//*

//***************************************************************************



//===========================================================================

function main takes nothing returns nothing

    call SetCameraBounds( -9472.0 + GetCameraMargin(CAMERA_MARGIN_LEFT), -9728.0 + GetCameraMargin(CAMERA_MARGIN_BOTTOM), 9472.0 - GetCameraMargin(CAMERA_MARGIN_RIGHT), 9216.0 - GetCameraMargin(CAMERA_MARGIN_TOP), -9472.0 + GetCameraMargin(CAMERA_MARGIN_LEFT), 9216.0 - GetCameraMargin(CAMERA_MARGIN_TOP), 9472.0 - GetCameraMargin(CAMERA_MARGIN_RIGHT), -9728.0 + GetCameraMargin(CAMERA_MARGIN_BOTTOM) )

    call SetDayNightModels( "Environment\\DNC\\DNCLordaeron\\DNCLordaeronTerrain\\DNCLordaeronTerrain.mdl", "Environment\\DNC\\DNCLordaeron\\DNCLordaeronUnit\\DNCLordaeronUnit.mdl" )

    call NewSoundEnvironment( "Default" )

    call SetAmbientDaySound( "SunkenRuinsDay" )

    call SetAmbientNightSound( "SunkenRuinsNight" )

    call SetMapMusic( "Music", true, 0 )

    call InitRandomGroups(  )

    call CreateAllUnits(  )

    call InitBlizzard(  )

    call InitGlobals(  )

    call InitCustomTriggers(  )

    call RunInitializationTriggers(  )



endfunction



//***************************************************************************

//*

//*  Map Configuration

//*

//***************************************************************************



function config takes nothing returns nothing

    call SetMapName( "TRIGSTR_009" )

    call SetMapDescription( "TRIGSTR_011" )

    call SetPlayers( 4 )

    call SetTeams( 4 )

    call SetGamePlacement( MAP_PLACEMENT_TEAMS_TOGETHER )



    call DefineStartLocation( 0, 6336.0, -5888.0 )

    call DefineStartLocation( 1, -6400.0, 5248.0 )

    call DefineStartLocation( 2, 6336.0, 5376.0 )

    call DefineStartLocation( 3, -6208.0, -5824.0 )



    // Player setup

    call InitCustomPlayerSlots(  )

    call SetPlayerSlotAvailable( Player(0), MAP_CONTROL_USER )

    call SetPlayerSlotAvailable( Player(1), MAP_CONTROL_USER )

    call SetPlayerSlotAvailable( Player(2), MAP_CONTROL_USER )

    call SetPlayerSlotAvailable( Player(3), MAP_CONTROL_USER )

    call InitGenericPlayerSlots(  )

    call InitAllyPriorities(  )

endfunction



