1. Are you planning to upload your awesome map to Hive? Please review the rules here.
    Dismiss Notice
  2. Updated Resource Submission Rules: All model & skin resource submissions must now include an in-game screenshot. This is to help speed up the moderation process and to show how the model and/or texture looks like from the in-game camera.
    Dismiss Notice
  3. DID YOU KNOW - That you can unlock new rank icons by posting on the forums or winning contests? Click here to customize your rank or read our User Rank Policy to see a list of ranks that you can unlock. Have you won a contest and still haven't received your rank award? Then please contact the administration.
    Dismiss Notice
  4. Let your favorite entries duke it out in the 15th Techtree Contest Poll.
    Dismiss Notice
  5. Weave light to take you to your highest hopes - the 6th Special Effect Contest is here!
    Dismiss Notice
  6. Check out the Staff job openings thread.
    Dismiss Notice
Dismiss Notice
60,000 passwords have been reset on July 8, 2019. If you cannot login, read this.

Trigger Viewer

BUGS 1_7.w3x
Variables
Game Basics
Globals
CoreSystem
Init
Quest Log
Game Startup
Game End
DEXP
Player leaves game
Bugs
Score Board
Abilities
Burrow
Ally
Creeps
CreepSystem
Beehive
Ants
Food
Various stuff
Make AI Bugs run around
Spawn Random Underground Effects
Weather
Holes
Commands
Killme
Set Level
Health
Orders
AI
Random XY
Count
Creeps
AntsDisp
BeesDisp
attack
External Systems
Fog Fading System 13
Fog Fading System
GCU
TimerUtils
Enter map-specific custom script code below. This text will be included in the map script after variables are declared and before any trigger code.
//TESH.scrollpos=0
//TESH.alwaysfold=0
Name Type Is Array Initial Value
d dialog No
//TESH.scrollpos=0
//TESH.alwaysfold=0
    globals
        constant string TITLE = "|cffd2fc78B|r|cffc9f074U|r|cffc0e570G|r|cffb7da6cS|r|cffaecf69!|r" // "|cffD2FC78BUGS!|r"
        constant string VERSION = "|cffF6CA9Fv1.7|r"
        constant string AUTHOR = "|cff515151 by MoCo|r"
      //  constant boolean DEBUG_MODE = false
       
        // Set up the map borders
        constant real MIN_X = -5120
        constant real MAX_X = 5120
       
        constant real GROUND_MIN_Y = 512
        constant real GROUND_MAX_Y = 7168
       
        constant real UNDERGROUND_MIN_Y = -7168
        constant real UNDERGROUND_MAX_Y = -512
       
        // Tags
        constant string DEBUG   = "|cffEA34DFDebug-Info:|r "
        constant string EVENT   = "|cffF7A647Game Event:|r "
        constant string HINT    = "|cff34A3EAHint:|r "
       
        constant real SIZE_START = 0.3
        constant real SIZE_PER_LEVEL = 0.01   // 0.007 With each level, the bug grows this size
        constant integer MAX_LEVEL = 70
        constant integer MAX_LEVEL_DIF = 19
       
       
        // Player Stuff
        constant integer MAX_PLAYERS = 9
       
        force Players = CreateForce()
        integer NumberOfPlayers = 0
        string array PlayerColors[1]
        string array PlayerNames[1]
       
        real Wait_Time = 0
       
        unit array Bugs[1]
        unit array Bugs_AI[1]
        unit Winning_Bug = null
               
        real array Sizes[1]
        sound Sound_Start
        sound Sound_Victory
        sound Sound_Request
       
        boolean GameOver = false
       
        rect Ground_Area
        rect Underground_Area
       
        // Abilities      
        constant integer CARAPACE_REQ = 5
        constant integer IMPALE_REQ = 5
        constant integer POISON_REQ = 5
        constant integer VAMPIRE_REQ = 5
       
        integer array Poison[1]
        integer array Carapace[1]
        integer array Vampire[1]
       
        weathereffect redfog
       
    endglobals
//TESH.scrollpos=0
//TESH.alwaysfold=0
library CoreSystem


function Debug_Mode takes nothing returns boolean
    return DEBUG_MODE
endfunction
   
function NotGameOver takes nothing returns boolean
    return GameOver == false
endfunction  

function IsHero takes unit u returns boolean
    return IsUnitType(u, UNIT_TYPE_HERO)
endfunction    

function IsAI takes unit u returns boolean
    return GetPlayerController(GetOwningPlayer(u)) == MAP_CONTROL_COMPUTER
endfunction  

function Get_Random_X_Underground takes nothing returns real
    return GetRandomReal(MIN_X, 0)
endfunction

function Get_Random_X takes nothing returns real
    return GetRandomReal(MIN_X, MAX_X)
endfunction

function Get_Random_Y takes boolean IsUnderground returns real
    if IsUnderground then
        return GetRandomReal(UNDERGROUND_MIN_Y, UNDERGROUND_MAX_Y)
    endif
    return GetRandomReal(GROUND_MIN_Y, GROUND_MAX_Y)
endfunction    

function Is_Ground takes unit u returns boolean
    if GetUnitY(u) >= GROUND_MIN_Y and GetUnitY(u) <= GROUND_MAX_Y then
        return true
    endif
    return false
endfunction

function Is_Underground takes unit u returns boolean
    return GetUnitY(u) < 0
endfunction

function Is_Underground_Complex takes unit u returns boolean
    if GetUnitY(u) >= UNDERGROUND_MIN_Y and GetUnitY(u) <= UNDERGROUND_MAX_Y then
        return true
    endif
    return false
endfunction
   
function CoreSystem_Set_Size takes unit u returns nothing
    local real size
   
    set size = SIZE_START + ( GetHeroLevel(u) * SIZE_PER_LEVEL ) - SIZE_PER_LEVEL
    call SetUnitScale(u, size, size, size)
   
    set u = null
endfunction    

function CoreSystem_Message takes string Message returns nothing
    call DisplayTimedTextToForce(GetPlayersAll(), 15, Message)
endfunction

function CoreSystem_Game_Message takes string Message returns nothing
    call DisplayTimedTextToForce(GetPlayersAll(), 15, EVENT + Message)
endfunction

function CoreSystem_Debug_Message takes string Message returns nothing
    if DEBUG_MODE then
        call DisplayTimedTextToForce(GetPlayersAll(), 15, DEBUG + Message)
    endif
endfunction    

function CoreSystem_CreateTagOnUnit takes unit TargetUnit, string Text returns nothing
  local integer id = GetPlayerId(GetOwningPlayer(TargetUnit))
  local texttag t = CreateTextTag()
  local string value
 
  set Text = "|c00" + PlayerColors[id] + Text + "|r"
  call SetTextTagColor(t, 182, 91, 234, 255)
  call SetTextTagText(t, Text, 0.0184)
  call SetTextTagPos(t, GetUnitX(TargetUnit), GetUnitY(TargetUnit), 0.00)
  call SetTextTagVelocity(t, 0, 0.03)
  call SetTextTagVisibility(t, true)
  call SetTextTagFadepoint(t, 3)
  call SetTextTagLifespan(t, 4)
  call SetTextTagPermanent(t, false)  
  set t = null
endfunction


function CoreSystem_Init_Players takes nothing returns nothing
    local integer id
   
    // Init Colors first
   
    // User Players
    set PlayerColors[0] = "FF0202"
    set PlayerColors[1] = "0041FF"
    set PlayerColors[2] = "1BE5B8"
    set PlayerColors[3] = "530080"
    set PlayerColors[4] = "FFFC00"
    set PlayerColors[5] = "FE890D"
    set PlayerColors[6] = "1FBF00"
    set PlayerColors[7] = "E45AAF"
    set PlayerColors[8] = "949596"
    set PlayerColors[9] = "7DBEF1"
    set PlayerColors[10] = "0F6145"
    set PlayerColors[11] = "4D2903"
       
    // Other Players
    set PlayerColors[GetPlayerId(Player(PLAYER_NEUTRAL_AGGRESSIVE))] = "DA4949"
    set PlayerColors[GetPlayerId(Player(bj_PLAYER_NEUTRAL_VICTIM))] = "B6B6B6"
    set PlayerColors[GetPlayerId(Player(bj_PLAYER_NEUTRAL_EXTRA))] = "B6B6B6"
    set PlayerColors[GetPlayerId(Player(PLAYER_NEUTRAL_PASSIVE))] = "94D598"
   
    // Player Names
    set PlayerNames[0] = "|cff" + PlayerColors[0] + GetPlayerName(Player(0)) + "|r"
    set PlayerNames[1] = "|cff" + PlayerColors[1] + GetPlayerName(Player(1)) + "|r"
    set PlayerNames[2] = "|cff" + PlayerColors[2] + GetPlayerName(Player(2)) + "|r"
    set PlayerNames[3] = "|cff" + PlayerColors[3] + GetPlayerName(Player(3)) + "|r"
    set PlayerNames[4] = "|cff" + PlayerColors[4] + GetPlayerName(Player(4)) + "|r"
    set PlayerNames[5] = "|cff" + PlayerColors[5] + GetPlayerName(Player(5)) + "|r"
    set PlayerNames[6] = "|cff" + PlayerColors[6] + GetPlayerName(Player(6)) + "|r"
    set PlayerNames[7] = "|cff" + PlayerColors[7] + GetPlayerName(Player(7)) + "|r"
    set PlayerNames[8] = "|cff" + PlayerColors[8] + GetPlayerName(Player(8)) + "|r"
    set PlayerNames[9] = "|cff" + PlayerColors[9] + GetPlayerName(Player(9)) + "|r"
    set PlayerNames[10] = "|cff" + PlayerColors[10] + GetPlayerName(Player(10)) + "|r"
    set PlayerNames[11] = "|cff" + PlayerColors[11] + GetPlayerName(Player(11)) + "|r"
   
    // Init all players
    set id = 0
    loop
        exitwhen id > MAX_PLAYERS-1      
        if GetPlayerSlotState(Player(id)) == PLAYER_SLOT_STATE_PLAYING then
            call ForceAddPlayer( Players, Player(id) )
            set NumberOfPlayers = NumberOfPlayers + 1
        //    call CoreSystem_Debug_Message("Player added: Player("+I2S(id)+")")
        endif
        set id = id + 1
    endloop
   
   // call CoreSystem_Debug_Message("Number of Players: "+I2S(NumberOfPlayers))
endfunction
   
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
function Init_Text_Callback takes nothing returns nothing
    call DisplayTimedTextToPlayer(GetEnumPlayer(),0,0, Wait_Time, "Thanks for playing:  "+TITLE)
    call DisplayTimedTextToPlayer(GetEnumPlayer(),0,0, Wait_Time, " ")
    call DisplayTimedTextToPlayer(GetEnumPlayer(),0,0, Wait_Time, "|cffCEF497Your life's a challenge:|r  |cffFF3939kill|r, |cffFDD982eat|r and |cffFF944Devolve|r,")
    call DisplayTimedTextToPlayer(GetEnumPlayer(),0,0, Wait_Time, "but try not to get eaten by someone larger than you!")
    call DisplayTimedTextToPlayer(GetEnumPlayer(),0,0, Wait_Time, " ")
    call DisplayTimedTextToPlayer(GetEnumPlayer(),0,0, Wait_Time, "In your evolution, you will aquire the abilities of the insects you kill.")
    call DisplayTimedTextToPlayer(GetEnumPlayer(),0,0, Wait_Time, " ")
    call DisplayTimedTextToPlayer(GetEnumPlayer(),0,0, Wait_Time, "The first bug who reaches level |cffF6CA9F" + I2S(MAX_LEVEL) + "|r wins the game!")
    call DisplayTimedTextToPlayer(GetEnumPlayer(),0,0, Wait_Time, " ")
endfunction

function Trig_Init_Actions takes nothing returns nothing
    // Let's init 2 basic fogs, one for noon time and one for midnight

    local integer i
    local location TempPoint
    local fog FogInitial_A = fog.create()
    local fog FogInitial_B = fog.create()
   
    set FogInitial_A.name    = "Intro fog"
    set FogInitial_A.start   = 4000    // fog starting distance
    set FogInitial_A.end     = 8000    // end distance
    set FogInitial_A.density = 1.0     // density
    set FogInitial_A.red     = 0.74     // RGB red value (min=0, max=1.0)
    set FogInitial_A.green   = 0.83     // RGB green value
    set FogInitial_A.blue    = 0.8     // RGB blue value
   
    set FogInitial_B.name    = "Intro fog"
    set FogInitial_B.start   = 1050    // fog starting distance
    set FogInitial_B.end     = 4000    // end distance
    set FogInitial_B.density = 1.0     // density
    set FogInitial_B.red     = 0.74     // RGB red value (min=0, max=1.0)
    set FogInitial_B.green   = 0.83     // RGB green value
    set FogInitial_B.blue    = 0.8     // RGB blue value
   
    call CinematicFadeBJ( bj_CINEFADETYPE_FADEIN, 10, "ReplaceableTextures\\CameraMasks\\Black_mask.blp", 0, 0, 0, 0 )

    call SetFloatGameState(GAME_STATE_TIME_OF_DAY, 6)
    call SuspendTimeOfDay(true)
    call EnableUserControl(false)
    call FFS_Change_Fog( FogInitial_A, 0, 0 )
    call CameraSetupApplyForceDuration(gg_cam_StartCam, true, 0)
   
    set Ground_Area = Rect( MIN_X, GROUND_MIN_Y, MAX_X, GROUND_MAX_Y )
    set Underground_Area = Rect( MIN_X, UNDERGROUND_MIN_Y, MAX_X, UNDERGROUND_MAX_Y )
   
    // Init Players
    call CoreSystem_Init_Players()
    // Activate red dungeon fog for underground
    set redfog = AddWeatherEffect(Underground_Area, 'FDrh')
    // call AddWeatherEffectSaveLast( gg_rct_Underground, 'FDrh' )
    call EnableWeatherEffect(redfog, true)
    // Quest Log
    call TriggerExecute(gg_trg_Quest_Log)
    // Init size array used for the bugs
    set i = 0
    loop
        exitwhen i > 11
        set Sizes[i] = SIZE_START
        set i = i + 1
    endloop
   
    // Set Master Sound (used for different stuff)
    call Preload( "Sound\\Interface\\ArrangedTeamInvitation.wav" )
    call Preload( "Sound\\Interface\\NewTournament.wav" )
    call Preload( "Sound\\Interface\\SecretFound.wav" )
    set Sound_Start = CreateSound("Sound\\Interface\\ArrangedTeamInvitation.wav", false, false, true, 12700, 12700, "")
    set Sound_Victory = CreateSound("Sound\\Interface\\NewTournament.wav", false, false, true, 12700, 12700, "")
    set Sound_Request = CreateSound("Sound\\Interface\\SecretFound.wav", false, false, true, 12700, 12700, "")
   
    call TriggerSleepAction(0.1)
   
    set Wait_Time = 12.0
    call ResetToGameCamera(Wait_Time)
    call FFS_Change_Fog( FogInitial_B, Wait_Time, 0.1 )
   
    if DEBUG_MODE then
        set Wait_Time = 2.0
    endif
   
    if DEBUG_MODE then
        call CreateFogModifierRectBJ( true, Player(0), FOG_OF_WAR_VISIBLE, GetPlayableMapRect() )
    endif
   
    // Let's make one of the plants stay at it's position forever
    call IssueImmediateOrder( gg_unit_h000_0000, "holdposition" )
   
    call TriggerSleepAction(0.1)
   
    call ForForce(Players, function Init_Text_Callback)
   
    if DEBUG_MODE then
        call TriggerSleepAction(2)
    else
        call TriggerSleepAction(8)
    endif
   
    call EnableUserControl(true)
   
    call TriggerSleepAction(4)
   
    // Game start
    call TriggerExecute(gg_trg_Game_Startup)
   
    set TempPoint = null
endfunction

//===========================================================================
function InitTrig_Init takes nothing returns nothing
    set gg_trg_Init = CreateTrigger(  )
    call TriggerAddAction( gg_trg_Init, function Trig_Init_Actions )
endfunction

 
Quest Log
  Events
  Conditions
  Actions
    Quest - Create a Required quest titled |cffD2FC78Map info|r with the description Thanks for playing this map!- Your goal is to reach level |cffFFB46B70|r before all other players.- You can ally with up to 3 other players for a team victory.If you find any bugs (haha) or want to give general feedback, please feel free to contact me, MoCo, via PM at |cffFFB46Bwww.hiveworkshop.com|r.Enjoy! :), using icon path ReplaceableTextures\CommandButtons\BTNCarrionScarabs.blp
//TESH.scrollpos=0
//TESH.alwaysfold=0
function Spawn_Players_Callback takes nothing returns nothing
    local integer id = GetPlayerId(GetEnumPlayer())
    local unit u
   
    if GetPlayerSlotState(Player(id)) == PLAYER_SLOT_STATE_PLAYING  then
        call CoreSystem_Debug_Message("Bug created for Player "+I2S(id))
        set Bugs[id] = CreateUnit( Player(id), 'U000', Get_Random_X(), Get_Random_Y(false), bj_UNIT_FACING )
       
        set u = Bugs[id]
       
        if GetPlayerController(Player(id)) == MAP_CONTROL_COMPUTER then
            set Bugs_AI[id] = Bugs[id]
            call UnitRemoveAbility( Bugs_AI[id], 'A00R' )
        endif
           
        call ClearSelectionForPlayer(Player(id))
        call SelectUnitForPlayerSingle(Bugs[id], Player(id))
       
        if not DEBUG_MODE then
            if Player(id) == GetLocalPlayer() then
                call SetCameraTargetController(u, 0, 0, false)
            endif
        endif

    endif
   
endfunction

function Startup_Text_Callback1 takes nothing returns nothing
    call DisplayTimedTextToPlayer(GetEnumPlayer(),0,0, 3, "Get ready to survive, the game will begin in.. ")
    call DisplayTimedTextToPlayer(GetEnumPlayer(),0,0, 1, "                                          |cffFF16163|r")
endfunction

function Startup_Text_Callback2 takes nothing returns nothing
    call DisplayTimedTextToPlayer(GetEnumPlayer(),0,0, 1, "                                          |cffFF16162|r")
endfunction

function Startup_Text_Callback3 takes nothing returns nothing
    call DisplayTimedTextToPlayer(GetEnumPlayer(),0,0, 1, "                                          |cffFF16161|r")
   endfunction

function Startup_Text_Callback4 takes nothing returns nothing
    call DisplayTimedTextToPlayer(GetEnumPlayer(),0,0, 10, "Your |cffFFA647evolution|r begins now!")
    call DisplayTimedTextToPlayer(GetEnumPlayer(),0,0, 2, " ")
    call DisplayTimedTextToPlayer(GetEnumPlayer(),0,0, 10, "For the start, you should search for some |cffAADE68Green Worms|r to eat..")
endfunction


function Trig_Game_Startup_Actions takes nothing returns nothing
    local integer id
   
    // call SetFloatGameState(GAME_STATE_TIME_OF_DAY, 6)
   
    // Spawn Creeps
    call Spawn_Creeps_First()
    //call Beehive_Start()
   
    call ForForce(Players, function Startup_Text_Callback1 )
    call TriggerSleepAction(1.0)
    call ForForce(Players, function Startup_Text_Callback2 )
    call TriggerSleepAction(1.0)
    call ForForce(Players, function Startup_Text_Callback3 )
    call TriggerSleepAction(1.0)
    call ForForce(Players, function Startup_Text_Callback4 )

    call StartSound(Sound_Start)
   
    // Spawn Players
    call ForForce(Players, function Spawn_Players_Callback)
   
    call CinematicFadeBJ( bj_CINEFADETYPE_FADEIN, 5, "ReplaceableTextures\\CameraMasks\\Black_mask.blp", 0, 0, 0, 0 )
    call SuspendTimeOfDay(false)
    call Start_Fog_Timer()
   
endfunction

//===========================================================================
function InitTrig_Game_Startup takes nothing returns nothing
    set gg_trg_Game_Startup = CreateTrigger(  )
    call TriggerAddAction( gg_trg_Game_Startup, function Trig_Game_Startup_Actions )
endfunction

 
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope GameEnd
   
private function Cam_To_Winner takes nothing returns nothing
    call SetCameraTargetControllerNoZForPlayer( GetEnumPlayer(), Winning_Bug, 0, 0, false )
endfunction

private function GameEnd_For_Other_Players takes nothing returns nothing
    local integer id = GetPlayerId(GetOwningPlayer(Winning_Bug))
   
    if IsPlayerAlly(GetEnumPlayer(), Player(id)) then
        call CustomVictoryBJ( GetEnumPlayer(), true, true )
    else
        call CustomDefeatBJ( GetEnumPlayer(), "You have been defeated!" )
    endif
   
endfunction

function Game_End takes nothing returns nothing
    local integer id = GetPlayerId(GetOwningPlayer(Winning_Bug))
   
    set GameOver = true
   
    call ForForce(Players, function Cam_To_Winner )
   
    call StartSound(Sound_Victory)
    call CoreSystem_Message("|cffFFA656Congratulations!|r")
    call CoreSystem_Message(" ")
    call CoreSystem_Message(PlayerNames[id] + " has mastered the unmerciful rules of evolution and has become the most advanced species in the carrot garden!")
    call PauseAllUnitsBJ( true )
   
    call TriggerSleepAction(9.0)
   
    call CustomVictoryBJ( Player(id), true, true )
    call ForceRemovePlayer(Players, Player(id))
    call ForForce(Players, function GameEnd_For_Other_Players)
   
endfunction

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

endscope
 
//TESH.scrollpos=12
//TESH.alwaysfold=0
scope DEXP initializer Init

  //Configuration globals
globals
  private constant real RADIUS = 1400. //Radius to consider heroes for exp gain
  private constant real CLOSE = 600. //Determines "Close" for distance effect. Gives full exp
  private constant real MEDIUM = 1000. //Determines the "Middle" for distance effect. Gives less exp
  private constant real FAR = 1400. //Determines the "Far" for distance effect. Gives even less exp
  //Should probably be the same as Radius.
  private constant real CLOSE_FACTOR = 1. //Determines what % of exp heroes in the "close" range get. (1 == 100%)
  private constant real MEDIUM_FACTOR = .5 //Determines what % of exp heroes in the "medium" range get. (.5 == 50%)
  private constant real FAR_FACTOR = .25  //Determines what % of exp heroes in the "far" range get. (.25 == 25%)
 
  private constant integer UNIT_EXP = 100 //How much exp per level (of the unit) units give.
  private constant integer HERO_EXP = 100 //How much exp per level (of the dying hero) heroes give.
  private constant integer BONUS_EXP = 0 //How much exp is granted per allies hero nearby.
  //If this value is positive, more heroes == more exp each
  //if this value is negative, more heroes == less exp each ('Blizzard' method)
  //If this value is 0, the number of heroes effects nothing.
 
  //This is for the displaying of exp in textag format
  private constant real DURATION = 5. //How long the message will last
  private constant integer SIZE = 12 //Font size
  private constant integer RED = 0 //Red value (of 255) for the text
  private constant integer GREEN = 74 //Green value (of 255) for the text
  private constant integer BLUE = 255 //Blue value (of 255) for the text
 
  private constant boolean SHOW_TEXT = true //Set this to false to stop texttags
  private constant boolean SPLIT = false //Set to true to divide the final exp by the number of heroes
  private constant boolean DISTANCE_EFFECT = true //Set to false if you do not want the
  //distance from the kill to determine how much exp the heroes get.
endglobals

private constant function Formula takes integer XPfactor, integer unitlevel, integer heroesinradius, integer bonus returns integer
  return (XPfactor * unitlevel) + (heroesinradius * bonus)
    //This is the function that determines how XP is calculted.
    //Unless you have a different method, don't touch this.
endfunction

private function CreateXPTag takes unit TargetUnit, string message returns nothing
    local unit u = TargetUnit
    local string s = message
    local texttag t = CreateTextTag()

    call SetTextTagColor(t, 182, 91, 234, 255)
    call SetTextTagText(t, s, 0.02) // 0.0184
    call SetTextTagPos(t, GetUnitX(u), GetUnitY(u), 0.00)
    call SetTextTagVelocity(t, 0, 0.08)
    call SetTextTagVisibility(t, true)
    call SetTextTagFadepoint(t, 1)
    call SetTextTagLifespan(t, 2)
    call SetTextTagPermanent(t, false)  
   
    set u = null
    set t = null
endfunction

private function Add_XP_New takes nothing returns nothing
   
endfunction

//This is the filter that picks up heroes in the radius of the killer.
//To modify it, simply add more booleans.
private function filter takes nothing returns boolean
  local unit u = GetFilterUnit()
  local boolean b1 = IsUnitType(u, UNIT_TYPE_DEAD) == false
  local boolean b2 = IsUnitType(u, UNIT_TYPE_HERO) == true
  local boolean b3 = IsUnitAlly(u, GetOwningPlayer(GetKillingUnit())) == true
 
  set u = null
  return b1 and b2 and b3
endfunction

//Use this filter to modify the exp given for certain conditions.
//For example, say you didn't want units from player 3 to give exp.
//See example below.
//Of course, if you don't want this then remove all the contents inside except "return exp"
private function ExpFilter takes integer exp, unit u returns integer
//  local boolean b1 = IsUnitInGroup(u, udg_Heroes) == false
   
//  if b1 then
//    return exp * 0
//  endif
 
  return exp
endfunction

//This applies the XP accordingly.
private function GiveXP takes nothing returns nothing
    local unit u = GetDyingUnit()  
    local unit f
    local unit Killer = GetKillingUnit()
    local player p = GetOwningPlayer(Killer)
    local integer add = 0
    local integer KilledUnitLevel
    local integer unitNum = 0
    local group g = CreateGroup()
    local real x = GetUnitX(Killer)
    local real y = GetUnitY(Killer)
    local real distance  
 
    local integer level_dif = 0   // MoCo
    local string level_mod = " "
 
    set bj_groupCountUnits = 0
 
    call GroupEnumUnitsInRange(g, x, y, RADIUS, Condition(function filter))
    call ForGroup(g, function CountUnitsInGroupEnum)
    set unitNum = bj_groupCountUnits

//============================================================
    // MoCo
    if GetUnitLevel(u) < GetHeroLevel(Killer) then
        set level_dif = GetHeroLevel(Killer) - GetUnitLevel(u)
    endif
//============================================================
    if IsUnitAlly(u, p) == false then    
        if IsUnitType(u, UNIT_TYPE_HERO) == true then
            set KilledUnitLevel = GetHeroLevel(u)
            set add = Formula(HERO_EXP, KilledUnitLevel, unitNum, BONUS_EXP)
        else
            set KilledUnitLevel = GetUnitLevel(u)
            set add = Formula(UNIT_EXP, KilledUnitLevel, unitNum, BONUS_EXP)
        endif  
    endif
   
    if SPLIT then
        set add = R2I(add / unitNum)
    endif
//============================================================
         
    if DISTANCE_EFFECT then

        set add = ExpFilter(add, u)
        loop
            set f = FirstOfGroup(g)
            exitwhen f == null
            set distance = ((GetUnitX(Killer)-GetUnitX(f)) * (GetUnitX(Killer)-GetUnitX(f))) + ((GetUnitY(Killer)-GetUnitY(f)) * (GetUnitY(Killer)-GetUnitY(f)))
     
            // xp modificator
            if level_dif >     40 then
                set add = 0
            elseif level_dif > 30 then
                set add = R2I(add * 0.25)
                set level_mod = "|cff828282 -75%|r"
            elseif level_dif > 20 then
                set add = R2I(add * 0.5)
                set level_mod = "|cff828282 -50%|r"
            elseif level_dif > 10 then
                set add = R2I(add * 0.75)
                set level_mod = "|cff828282 -25%|r"
            endif
           
            if SHOW_TEXT and add > 0 and GetLocalPlayer() == GetOwningPlayer(f) then
                call CreateXPTag(f, "+" + I2S(add) + "xp" + level_mod)
            endif
           
            //Far Away Units
            if distance > MEDIUM*MEDIUM and distance <= FAR*FAR then
                call SetPlayerHandicapXP(GetOwningPlayer(f), 1.00)
                call AddHeroXP(f, R2I(add * FAR_FACTOR), true)
                call SetPlayerHandicapXP(GetOwningPlayer(f), 0.00)
            //Medium Distance Units  
            elseif distance > CLOSE*CLOSE and distance <= MEDIUM*MEDIUM then
                call SetPlayerHandicapXP(GetOwningPlayer(f), 1.00)
                call AddHeroXP(f, R2I(add * MEDIUM_FACTOR), true)
                call SetPlayerHandicapXP(GetOwningPlayer(f), 0.00)
            //Close Range Units
            elseif distance <= CLOSE*CLOSE then
                call SetPlayerHandicapXP(GetOwningPlayer(f), 1.00)
                call AddHeroXP(f, R2I(add * CLOSE_FACTOR), true)
                call SetPlayerHandicapXP(GetOwningPlayer(f), 0.00)
            endif
            call GroupRemoveUnit(g, f)
        endloop
   
    else
        set add = ExpFilter(add, u)
        loop
            set f = FirstOfGroup(g)
            exitwhen f == null  
            call SetPlayerHandicapXP(GetOwningPlayer(f), 1.00)
           
            // xp modificator
            if level_dif >     40 then
                set add = 0
            elseif level_dif > 30 then
                set add = R2I(add * 0.25)
                set level_mod = "|cff828282 -75%|r"
            elseif level_dif > 20 then
                set add = R2I(add * 0.5)
                set level_mod = "|cff828282 -50%|r"
            elseif level_dif > 10 then
                set add = R2I(add * 0.75)
                set level_mod = "|cff828282 -25%|r"
            endif
               
            call AddHeroXP(f, add, true)
           
            if SHOW_TEXT and add > 0 and GetLocalPlayer() == GetOwningPlayer(f) then
                call CreateXPTag(f, "+" + I2S(add) + "xp" + level_mod)
            endif
     
            call SetPlayerHandicapXP(GetOwningPlayer(f), 0.00)
            call GroupRemoveUnit(g, f)
        endloop          
    endif

    call DestroyGroup(g)
    set g = null
    set u = null
    set Killer = null
    set f = null                          
endfunction


//This trigger stops players from gaining XP when they shouldn't be.
private function Cut_XP_Gain takes nothing returns nothing
   local integer i = 0
   loop
     exitwhen i > 12
     call SetPlayerHandicapXP(Player(i), 0.00)
     set i = i + 1
   endloop
   call DestroyTimer(GetExpiredTimer())
endfunction

//===========================================================================
private function Init takes nothing returns nothing
    local trigger t = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_DEATH )
    call TriggerAddAction(t, function GiveXP )
    call TimerStart(CreateTimer(), .04, false, function Cut_XP_Gain)
    set t = null
endfunction

//private function InitTrig_DEXP takes nothing returns nothing
//    local trigger t = CreateTrigger(  )
//    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_DEATH )
//    call TriggerAddAction(t, function GiveXP )
//    call TimerStart(CreateTimer(), .04, false, function Cut_XP_Gain)
//    set t = null
//endfunction

endscope
 
//TESH.scrollpos=0
//TESH.alwaysfold=0
function Trig_Player_leaves_game_Actions takes nothing returns nothing
    local integer id = GetPlayerId(GetTriggerPlayer())
   
    call CoreSystem_Game_Message(PlayerNames[id] + " has left the game. AI now will take over control of his bug!")
   
    set Bugs_AI[id] = Bugs[id]
   
endfunction

//===========================================================================
function InitTrig_Player_leaves_game takes nothing returns nothing
    set gg_trg_Player_leaves_game = CreateTrigger(  )
    call TriggerRegisterPlayerEvent(gg_trg_Player_leaves_game, Player(0), EVENT_PLAYER_LEAVE)
    call TriggerRegisterPlayerEvent(gg_trg_Player_leaves_game, Player(1), EVENT_PLAYER_LEAVE)
    call TriggerRegisterPlayerEvent(gg_trg_Player_leaves_game, Player(2), EVENT_PLAYER_LEAVE)
    call TriggerRegisterPlayerEvent(gg_trg_Player_leaves_game, Player(3), EVENT_PLAYER_LEAVE)
    call TriggerRegisterPlayerEvent(gg_trg_Player_leaves_game, Player(4), EVENT_PLAYER_LEAVE)
    call TriggerRegisterPlayerEvent(gg_trg_Player_leaves_game, Player(5), EVENT_PLAYER_LEAVE)
    call TriggerRegisterPlayerEvent(gg_trg_Player_leaves_game, Player(6), EVENT_PLAYER_LEAVE)
    call TriggerRegisterPlayerEvent(gg_trg_Player_leaves_game, Player(7), EVENT_PLAYER_LEAVE)
    call TriggerRegisterPlayerEvent(gg_trg_Player_leaves_game, Player(8), EVENT_PLAYER_LEAVE)
    call TriggerRegisterPlayerEvent(gg_trg_Player_leaves_game, Player(9), EVENT_PLAYER_LEAVE)
    call TriggerRegisterPlayerEvent(gg_trg_Player_leaves_game, Player(10), EVENT_PLAYER_LEAVE)
    call TriggerRegisterPlayerEvent(gg_trg_Player_leaves_game, Player(11), EVENT_PLAYER_LEAVE)
    call TriggerAddAction( gg_trg_Player_leaves_game, function Trig_Player_leaves_game_Actions )
endfunction

 
//TESH.scrollpos=135
//TESH.alwaysfold=0
scope Bugs initializer Init

private function IsKillerHero takes nothing returns boolean
    return IsUnitType(GetKillingUnit(), UNIT_TYPE_HERO)
endfunction

private function IsDyingHero takes nothing returns boolean
    return IsUnitType(GetDyingUnit(), UNIT_TYPE_HERO)
endfunction

private function Ability_Gain takes nothing returns nothing
    local integer id = GetPlayerId(GetOwningPlayer(GetKillingUnit()))
    local integer id2 = GetPlayerId(GetOwningPlayer(GetDyingUnit()))
    local integer Ability
       
    // Carapace
    if GetUnitTypeId(GetDyingUnit()) == 'z000' and Carapace[id] < CARAPACE_REQ then
        set Carapace[id] = Carapace[id] + 1
        if Carapace[id] < CARAPACE_REQ then
            call DisplayTimedTextToPlayer(Player(id),0,0,10,"Kill |cffFFE596"+I2S(CARAPACE_REQ)+"|r "+GetUnitName(GetDyingUnit())+" to adept: " + GetObjectName('A005') + " |cffD0D0D0(" + I2S(Carapace[id]) + "/" + I2S(CARAPACE_REQ) + ")|r" )
        elseif Carapace[id] == CARAPACE_REQ then
            call UnitAddAbility(GetKillingUnit(), 'A005')
            call DisplayTimedTextToPlayer(Player(id),0,0,10,"New ability gained: " + GetObjectName('A005') )
        endif
    endif
   
    // Poison
    if Poison[id] < POISON_REQ and ( GetUnitTypeId(GetDyingUnit()) == 'n007' or GetUnitTypeId(GetDyingUnit()) == 'n00J' ) then
        set Poison[id] = Poison[id] + 1
        if Poison[id] < POISON_REQ then
            call DisplayTimedTextToPlayer(Player(id),0,0,10,"Kill |cffFFE596"+I2S(CARAPACE_REQ)+"|r spiders to adept: " + GetObjectName('A003') + " |cffD0D0D0(" + I2S(Poison[id]) + "/" + I2S(POISON_REQ) + ")|r" )
        elseif Poison[id] == POISON_REQ then
            call UnitAddAbility(GetKillingUnit(), 'A003')
            call UnitAddAbility(GetKillingUnit(), 'A002')
            call DisplayTimedTextToPlayer(Player(id),0,0,10,"New ability gained: " + GetObjectName('A003') )
        endif
    endif
   
    // Vampirism
    if Vampire[id] < VAMPIRE_REQ and ( GetUnitTypeId(GetDyingUnit()) == 'u00D' or GetUnitTypeId(GetDyingUnit()) == 'u00I' ) then
        set Vampire[id] = Vampire[id] + 1
        if Vampire[id] < VAMPIRE_REQ then
            call DisplayTimedTextToPlayer(Player(id),0,0,10,"Kill |cffFFE596"+I2S(VAMPIRE_REQ)+"|r beetles to adept: " + GetObjectName('A004') + " |cffD0D0D0(" + I2S(Vampire[id]) + "/" + I2S(VAMPIRE_REQ) + ")|r" )
        elseif Vampire[id] == VAMPIRE_REQ then
            call UnitAddAbility(GetKillingUnit(), 'A004')
            call DisplayTimedTextToPlayer(Player(id),0,0,10,"New ability gained: " + GetObjectName('A004') )
        endif
    endif
   
endfunction

private function A_Bug_Kills takes nothing returns nothing
    local integer id = GetPlayerId(GetOwningPlayer(GetKillingUnit()))
    local integer id_d = GetPlayerId(GetOwningPlayer(GetDyingUnit()))
   
    // Set Total Kills
    // set Score_Kills[id] = Score_Kills[id] + 1
   
    // Hero Kill?
    if IsUnitType(GetDyingUnit(), UNIT_TYPE_HERO) == true then
        //set Score_Hero_Kills[id] = Score_Hero_Kills[id] + 1
       
        if Score_Hero_Kills[id] <= IMPALE_REQ then
            call DisplayTimedTextToPlayer(Player(id),0,0,10,"Kill |cffFFE596"+I2S(IMPALE_REQ)+"|r other player's bugs to adept: " + GetObjectName('A007') + " |cffD0D0D0(" + I2S(Score_Hero_Kills[id]) + "/" + I2S(IMPALE_REQ) + ")|r" )
            if Score_Hero_Kills[id] == IMPALE_REQ then
                call UnitAddAbility(GetKillingUnit(), 'A007')
                call DisplayTimedTextToPlayer(Player(id),0,0,10,"New ability gained: " + GetObjectName('A007') )
            endif
        endif
    endif
   
    // Update Scoreboard
    //call ScoreSystem_UpdatePlayerScore(id)
   
endfunction

private function A_Bug_Dies takes nothing returns nothing
    local integer id = GetPlayerId(GetOwningPlayer(GetDyingUnit()))
    local integer level = GetHeroLevel(GetDyingUnit())
    local integer loss
   
    if level >= 80 then
        set loss = 8
    elseif level >= 70 then
        set loss = 7
    elseif level >= 60 then
        set loss = 6
    elseif level >= 50 then
        set loss = 5
    elseif level >= 40 then
        set loss = 4
    elseif level >= 30 then
        set loss = 3
    elseif level >= 20 then
        set loss = 2
    elseif level >= 10 then
        set loss = 1
    else
        set loss = 0
    endif
   
    // advantage for AI heroes
    if IsAI(GetDyingUnit()) then
        set loss = loss/2
    endif
   
    if loss > 0 then
        call UnitStripHeroLevel(GetDyingUnit(), loss)
        call DisplayTextToPlayer(GetOwningPlayer(GetDyingUnit()), 0, 0, "|cffFE3030Your bug died!|r  You will respawn at level |cffF5B45F" + I2S(GetHeroLevel(GetDyingUnit())) + "|r")
    else
        call DisplayTextToPlayer(GetOwningPlayer(GetDyingUnit()), 0, 0, "|cffFE3030Your bug died!|r  Don't worry, you will respawn immediately!")

    endif
   
    //set Score_Deaths[id] = Score_Deaths[id] + 1
   
    // Update Scoreboard
    //call ScoreSystem_UpdatePlayerScore(id)
   
    call TriggerSleepAction(3.0)
   
    call ReviveHero( GetDyingUnit(), Get_Random_X(), Get_Random_Y(false), true )
   
    //if GetLocalPlayer() == Player(id) then
    //    call FFS_Change_Fog( FogNoon, 0, 0 )
    //endif
       
    call CoreSystem_Set_Size(GetDyingUnit())
   
    if (GetLocalPlayer() == Player(id)) then
        // Use only local code (no net traffic) within this block to avoid desyncs.
        call ClearSelection()
        call SelectUnit(GetDyingUnit(), true)
    endif
    call SetUnitState(GetDyingUnit(), UNIT_STATE_MANA, GetUnitState(GetDyingUnit(), UNIT_STATE_MAX_MANA))
   
endfunction

private function A_Bug_LevelsUp takes nothing returns nothing
   
    // Increase Size
    call CoreSystem_Set_Size(GetLevelingUnit())
   
    // Level 10
    if GetHeroLevel(GetKillingUnit()) == 10 then
        call DisplayTextToPlayer(GetOwningPlayer(GetKillingUnit()), 0, 0, "|cffC6F490Congratulations!|r You've reached level |cffFFC79610|r. |cffFF6F53But beware now:|r If you die, you'll loose |cffFF1F1F1|r level!")
    endif
    if GetHeroLevel(GetKillingUnit()) == 20 then
        call DisplayTextToPlayer(GetOwningPlayer(GetKillingUnit()), 0, 0, "|cffC6F490Congratulations!|r You've reached level |cffFFC79620|r. |cffFF6F53But beware now:|r If you die, you'll loose |cffFF1F1F2|r levels!")
    endif
    if GetHeroLevel(GetKillingUnit()) == 30 then
        call DisplayTextToPlayer(GetOwningPlayer(GetKillingUnit()), 0, 0, "|cffC6F490Congratulations!|r You've reached level |cffFFC79630|r. |cffFF6F53But beware now:|r If you die, you'll loose |cffFF1F1F3|r levels!")
    endif
    if GetHeroLevel(GetKillingUnit()) == 40 then
        call DisplayTextToPlayer(GetOwningPlayer(GetKillingUnit()), 0, 0, "|cffC6F490Congratulations!|r You've reached level |cffFFC79640|r. |cffFF6F53But beware now:|r If you die, you'll loose |cffFF1F1F4|r levels!")
    endif
    if GetHeroLevel(GetKillingUnit()) == 50 then
        call DisplayTextToPlayer(GetOwningPlayer(GetKillingUnit()), 0, 0, "|cffC6F490Congratulations!|r You've reached level |cffFFC79650|r. |cffFF6F53But beware now:|r If you die, you'll loose |cffFF1F1F5|r levels!")
    endif
    if GetHeroLevel(GetKillingUnit()) == 60 then
        call DisplayTextToPlayer(GetOwningPlayer(GetKillingUnit()), 0, 0, "|cffC6F490Congratulations!|r You've reached level |cffFFC79660|r. |cffFF6F53But beware now:|r If you die, you'll loose |cffFF1F1F6|r levels!")
    endif
           
    // Max level?
    if GetHeroLevel(GetLevelingUnit()) >= MAX_LEVEL then
        set Winning_Bug = GetLevelingUnit()
        call Game_End()
    endif
   
endfunction

//===========================================================================
function Init takes nothing returns nothing
    local trigger t1 = CreateTrigger()
    local trigger t2 = CreateTrigger()
    local trigger t3 = CreateTrigger()
   
    call TriggerRegisterAnyUnitEventBJ( t1, EVENT_PLAYER_UNIT_DEATH )
    call TriggerAddCondition( t1, Condition( function IsKillerHero ) )
    call TriggerAddAction( t1, function A_Bug_Kills )
    call TriggerAddAction( t1, function Ability_Gain )
   
    call TriggerRegisterAnyUnitEventBJ( t2, EVENT_PLAYER_UNIT_DEATH )
    call TriggerAddCondition( t2, Condition( function IsDyingHero ) )
    call TriggerAddAction( t2, function A_Bug_Dies )
   
    call TriggerRegisterAnyUnitEventBJ( t3, EVENT_PLAYER_HERO_LEVEL )
    call TriggerAddCondition( t3, Condition( function NotGameOver ) )
    call TriggerAddAction( t3, function A_Bug_LevelsUp )
   
endfunction

endscope
//TESH.scrollpos=3
//TESH.alwaysfold=0
scope ScoreBoard initializer Init

    globals
       
        private string SCORE_TITLE// = TITLE + "   " + VERSION + "   " + AUTHOR
       
        private multiboard Score_Table // Don't use "= CreateMultiboard()"! else the game will crash
       
        private integer array ScoreBoard_Positions[1]
       
        integer array Score_Hero_Kills[1]
        private integer array Score_Deaths[1]
        private integer array Score_Kills[1]
        private integer array Score_Levels[1]
       
        private timer GameTime = CreateTimer()
        private integer GameTime_Minutes
        private integer GameTime_Seconds
        private integer ClockRow
       
        private trigger trg_once
       
    endglobals

private function Update_Callback takes nothing returns nothing
    local multiboarditem field
    local integer id = GetPlayerId(GetEnumPlayer())
   
    // call CoreSystem_Debug_Message("Updating Scoreboard, id="+I2S(id))
   
    // Name
    set field = MultiboardGetItem(Score_Table, ScoreBoard_Positions[id], 0)
    call MultiboardSetItemValue( field, " " + PlayerNames[id] )
   
    // Level
    set field = MultiboardGetItem(Score_Table, ScoreBoard_Positions[id], 1)
    call MultiboardSetItemValue( field, " " + I2S(GetHeroLevel(Bugs[id])) )

    // PvP
    set field = MultiboardGetItem(Score_Table, ScoreBoard_Positions[id], 2)
    call MultiboardSetItemValue( field, " " + I2S(Score_Hero_Kills[id]) )
   
    // Kills
    set field = MultiboardGetItem(Score_Table, ScoreBoard_Positions[id], 3)
    call MultiboardSetItemValue( field, " " + I2S(Score_Kills[id]) )
   
    // Deaths
    set field = MultiboardGetItem(Score_Table, ScoreBoard_Positions[id], 4)
    call MultiboardSetItemValue( field, I2S(Score_Deaths[id]) )
   
    set field = null
   
endfunction

private function Update takes nothing returns nothing
    call ForForce(Players, function Update_Callback)
endfunction

private function Conditions_Bug_Kills takes nothing returns boolean
    return IsUnitType(GetKillingUnit(), UNIT_TYPE_HERO)
endfunction

private function A_Bug_Kills takes nothing returns nothing
    local integer id = GetPlayerId(GetOwningPlayer(GetKillingUnit()))
    set Score_Kills[id] = Score_Kills[id] + 1
   
    if IsUnitType(GetDyingUnit(), UNIT_TYPE_HERO) then
        set Score_Hero_Kills[id] = Score_Hero_Kills[id] + 1
    endif
   
    call Update()
   
endfunction

private function Conditions_Bug_Dies takes nothing returns boolean
    return IsUnitType(GetDyingUnit(), UNIT_TYPE_HERO)
endfunction

private function A_Bug_Dies takes nothing returns nothing
    local integer id = GetPlayerId(GetOwningPlayer(GetTriggerUnit()))
    set Score_Deaths[id] = Score_Deaths[id] + 1
    call Update()
endfunction

private function Set_Clock takes nothing returns nothing
    local multiboarditem clockfield = null
    set clockfield = MultiboardGetItem(Score_Table, ClockRow, 2)
   
    set GameTime_Minutes = ( R2I(TimerGetElapsed(GameTime)) / 60 )
    set GameTime_Seconds = ModuloInteger(R2I(TimerGetElapsed(GameTime)), 60)
   
    if GameTime_Seconds >= 10 then
        call MultiboardSetItemValue( clockfield, I2S(GameTime_Minutes) + ":" + I2S(GameTime_Seconds) )
    else
        call MultiboardSetItemValue( clockfield, I2S(GameTime_Minutes) + ":0" + I2S(GameTime_Seconds) )
    endif
   
    set clockfield = null
endfunction

function Conditions_Init takes nothing returns boolean
    return IsUnitType(GetTriggerUnit(), UNIT_TYPE_HERO) == true
endfunction

private function Init_Score_Board takes nothing returns nothing
    local integer i
    local integer j
    local integer id
    local multiboarditem field = null
    local integer PlayersCount = NumberOfPlayers
   
    call TriggerSleepAction( 1.00 )
    call TimerStart( GameTime, 999999.00, false, null )
   
    set SCORE_TITLE = TITLE + "   " + VERSION + "   " + AUTHOR
   
    // Now create the actual Multiboard
    set Score_Table = CreateMultiboard()
    call MultiboardSetRowCount(Score_Table, 4 + NumberOfPlayers )
    call MultiboardSetColumnCount(Score_Table, 5)
    call MultiboardSetTitleText(Score_Table, SCORE_TITLE)
    call MultiboardDisplay(Score_Table, true)

    //  Adjust color and display style
    set i = 0
    loop
        exitwhen ( i > MultiboardGetRowCount(Score_Table)-1 )
        set j = 0
        loop
            exitwhen ( j > 4 )
            set field = MultiboardGetItem(Score_Table, i, j)
            call MultiboardSetItemStyle( field, true, false )
            call MultiboardSetItemValueColor( field, 220, 220, 220, 255 )
            set j = j + 1
        endloop
        set i = i + 1
    endloop
   
    // Adjust column width
    set i = 0
    loop
        exitwhen ( i > MultiboardGetRowCount(Score_Table)-1 )
        set field = MultiboardGetItem(Score_Table, i, 0)
        call MultiboardSetItemWidth(field, 0.10)
        set field = MultiboardGetItem(Score_Table, i, 1)
        call MultiboardSetItemWidth(field, 0.03) // 0.01
        set field = MultiboardGetItem(Score_Table, i, 2)
        call MultiboardSetItemWidth(field, 0.03)
        set field = MultiboardGetItem(Score_Table, i, 3)
        call MultiboardSetItemWidth(field, 0.03)
        set field = MultiboardGetItem(Score_Table, i, 4)
        call MultiboardSetItemWidth(field, 0.01)
        set i = i + 1
    endloop
   
    // Headline
    set field = MultiboardGetItem(Score_Table, 0, 1)
        call MultiboardSetItemValue( field, "|cffFFDD8DLv|r" )
        call MultiboardSetItemValueColor( field, 255, 255, 255, 255 )
    set field = MultiboardGetItem(Score_Table, 0, 2)
        call MultiboardSetItemValue( field, "|cffFF974APvP|r" )
        call MultiboardSetItemValueColor( field, 255, 255, 255, 255 )
    set field = MultiboardGetItem(Score_Table, 0, 3)
        call MultiboardSetItemValue( field, "|cffD60505Kills|r" )
        call MultiboardSetItemValueColor( field, 255, 255, 255, 255 )
    set field = MultiboardGetItem(Score_Table, 0, 4)
        call MultiboardSetItemStyle( field, true, true )
        call MultiboardSetItemIcon(field, "ReplaceableTextures\\CommandButtons\\BTNPunisher.blp")
   
    // Add Players    
    set id = 0
    set j = 2
    loop
        exitwhen id > MAX_PLAYERS-1
       
        // loop all player slots, if playing, add
        if GetPlayerSlotState(Player(id)) == PLAYER_SLOT_STATE_PLAYING then
       
            set ScoreBoard_Positions[id] = j
           
            set field = MultiboardGetItem(Score_Table, j, 0)
            call MultiboardSetItemValue(field, " "+PlayerNames[id])
           
            set field = MultiboardGetItem(Score_Table, j, 1)
            call MultiboardSetItemValue(field, "1")
       
            set field = MultiboardGetItem(Score_Table, j, 2)
            call MultiboardSetItemValue(field, "0")
           
            set field = MultiboardGetItem(Score_Table, j, 3)
            call MultiboardSetItemValue(field, "0")
           
            set field = MultiboardGetItem(Score_Table, j, 4)
            call MultiboardSetItemValue(field, "0")
           
            set j = j + 1
        endif
        set id = id + 1
    endloop
   
    // Game Time
    set ClockRow = ( j + 1 )
    set field = MultiboardGetItem(Score_Table, ClockRow, 0)
    call MultiboardSetItemValueColor( field, 100, 100, 100, 255 )
    call MultiboardSetItemValue( field, " Game Time:" )
    set field = MultiboardGetItem(Score_Table, ClockRow, 2)
    call MultiboardSetItemValueColor( field, 180, 180, 180, 255 )
    call MultiboardSetItemValue( field, "0:00" )
 
    call MultiboardDisplay( Score_Table, true )
    call DisableTrigger( trg_once )
    set field = null
   
endfunction

//===========================================================================
public function Init takes nothing returns nothing
    local trigger trg = CreateTrigger()
    set trg_once = CreateTrigger()
    call TriggerRegisterEnterRectSimple( trg_once, bj_mapInitialPlayableArea )
    call TriggerAddCondition( trg_once, Condition( function Conditions_Init ) )
    call TriggerAddAction(trg_once, function Init_Score_Board)
   
    // Death
    call TriggerRegisterAnyUnitEventBJ( trg, EVENT_PLAYER_UNIT_DEATH )
    call TriggerAddCondition( trg, Condition( function Conditions_Bug_Dies ) )
    call TriggerAddAction(trg, function A_Bug_Dies )
   
    // Killing
    set trg = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ( trg, EVENT_PLAYER_UNIT_DEATH )
    call TriggerAddCondition( trg, Condition( function Conditions_Bug_Kills ) )
    call TriggerAddAction(trg, function A_Bug_Kills )
   
    set trg = CreateTrigger()
    call TriggerRegisterTimerEvent(trg, 1.00, true)
    call TriggerAddAction(trg, function Set_Clock)
   
   
endfunction

endscope
 
//TESH.scrollpos=12
//TESH.alwaysfold=0
function Trig_Burrow_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A00R'
endfunction

function Trig_Burrow_Actions takes nothing returns nothing
    local integer id = GetPlayerId(GetOwningPlayer(GetTriggerUnit()))
    local unit u = GetTriggerUnit()
    local effect e
    local integer dist = 7680
   
    call TriggerSleepAction(0.01)
   
    call PauseUnit(u, true)
    call SetUnitInvulnerable( u, true )
   
    // burrow in
    if Is_Underground(u) == false then
        call SetUnitAnimationByIndex( u, 8 )
        call TriggerSleepAction(0.6)
        call SetUnitPosition(u, GetUnitX(u), GetUnitY(u)-dist)
        set e = AddSpecialEffectTarget("Objects\\Spawnmodels\\Undead\\ImpaleTargetDust\\ImpaleTargetDust.mdl", u, "overhead")
        call SetUnitAnimationByIndex( u, 7 )

        //if GetLocalPlayer() == Player(id) then
        //    call FFS_Change_Fog( FogUnderground, 0, 0 )
        //endif
    // burrow out
    else
        set e = AddSpecialEffectTarget("Objects\\Spawnmodels\\Undead\\ImpaleTargetDust\\ImpaleTargetDust.mdl", u, "overhead")
        call TriggerSleepAction(0.1)
        call SetUnitPosition(u, GetUnitX(u), GetUnitY(u)+dist)
        call SetUnitAnimationByIndex( u, 10 )
        call TriggerSleepAction(0.5)
       
       // if GetLocalPlayer() == Player(id) then
        //    call FFS_Change_Fog( FogNoon, 0, 0 )
        //endif
    endif
   
    call PauseUnit(u, false)
    call SetUnitInvulnerable( u, false )
   
    call DestroyEffect(e)
    set e = null
    set u = null
endfunction

//===========================================================================
function InitTrig_Burrow takes nothing returns nothing
    set gg_trg_Burrow = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Burrow, EVENT_PLAYER_UNIT_SPELL_CAST )
    call TriggerAddCondition( gg_trg_Burrow, Condition( function Trig_Burrow_Conditions ) )
    call TriggerAddAction( gg_trg_Burrow, function Trig_Burrow_Actions )
endfunction

 
//TESH.scrollpos=48
//TESH.alwaysfold=0
scope AllySystem initializer Init

    globals
        private constant real ALLY_TIME = 10
        private constant integer ALLIES_MAX = 3
        private constant integer NOREQ = 15
       
        private integer array AllyRequests[1]
        private integer array Allies[1]
        private timer array AllyTimers[1]

    endglobals
   
private function Request_Alliance_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A00C'
endfunction

private function Quit_Alliance_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A00K'
endfunction

private function Ally_Dialog_Timer_Callback takes nothing returns nothing
    local integer id = GetTimerData(GetExpiredTimer())
    set AllyRequests[id] = NOREQ
    call ReleaseTimer(AllyTimers[id])
endfunction

private function Quit_Alliance takes nothing returns nothing
    local integer id = GetPlayerId(GetOwningPlayer(GetSpellAbilityUnit()))
    local integer target_id = GetPlayerId(GetOwningPlayer(GetSpellTargetUnit()))  
   
    call SetPlayerAllianceStateBJ( Player(id), Player(target_id), bj_ALLIANCE_UNALLIED )
    call SetPlayerAllianceStateBJ( Player(target_id), Player(id), bj_ALLIANCE_UNALLIED )
   
    call DisplayTimedTextToPlayer(Player(id),0,0,10,"You have quit your alliance with "+PlayerNames[target_id])
    call DisplayTimedTextToPlayer(Player(target_id),0,0,10,PlayerNames[id] + " has quit the alliance with you!")
   
    set Allies[id] = Allies[id] - 1
    set Allies[target_id] = Allies[target_id] - 1
   
endfunction

private function Request_Alliance takes nothing returns nothing
    local integer id = GetPlayerId(GetOwningPlayer(GetSpellAbilityUnit()))
    local integer target_id = GetPlayerId(GetOwningPlayer(GetSpellTargetUnit()))
   
    if Allies[id] >= ALLIES_MAX then
        call DisplayTimedTextToPlayer(Player(id),0,0,10,"You cannot have more than "+I2S(ALLIES_MAX)+" buddies!")
    elseif AllyRequests[id] != NOREQ then
        call DisplayTimedTextToPlayer(Player(id),0,0,10,"You can only have one ally request active at a time!")
    elseif AllyRequests[id] == NOREQ then
   
        if AllyRequests[target_id] == id then   // if other player has requested you too..
           
            set Allies[id] = Allies[id] + 1
            set Allies[target_id] = Allies[target_id] + 1
           
            call DisplayTimedTextToPlayer(Player(id),0,0,10,"You are now allied with "+PlayerNames[target_id])
            call DisplayTimedTextToPlayer(Player(target_id),0,0,10,"You are now allied with "+PlayerNames[id])
           
            call SetPlayerAllianceStateBJ( Player(id), Player(target_id), bj_ALLIANCE_ALLIED_VISION )
            call SetPlayerAllianceStateBJ( Player(target_id), Player(id), bj_ALLIANCE_ALLIED_VISION )
           
            if GetLocalPlayer() == Player(id) or GetLocalPlayer() == Player(target_id) then
                call StartSound(Sound_Start)
            endif
        else
            set AllyRequests[id] = target_id
           
            call DisplayTimedTextToPlayer(Player(id),0,0,ALLY_TIME,"You've send an ally request to " + PlayerNames[target_id])
            call DisplayTimedTextToPlayer(Player(id),0,0,ALLY_TIME,"He has "+R2S(ALLY_TIME)+" seconds to ally with you too")
           
            call DisplayTimedTextToPlayer(Player(target_id),0,0,ALLY_TIME,PlayerNames[id] + " wants to ally up with you!")
            call DisplayTimedTextToPlayer(Player(target_id),0,0,ALLY_TIME," ")
            call DisplayTimedTextToPlayer(Player(target_id),0,0,ALLY_TIME,"You have "+R2S(ALLY_TIME)+" seconds to ally with him")
            call DisplayTimedTextToPlayer(Player(target_id),0,0,ALLY_TIME,"(Just use your ally ability on his hero)")
           
            call SetTimerData(AllyTimers[id], id)
            call TimerStart(AllyTimers[id], ALLY_TIME, false, function Ally_Dialog_Timer_Callback)
           
            if GetLocalPlayer() == Player(id) or GetLocalPlayer() == Player(target_id) then
                call StartSound(Sound_Request)
            endif
           
        endif
    endif

endfunction

private function Start takes nothing returns nothing
    local integer i = 0
    loop
        exitwhen i > MAX_PLAYERS-1
        set AllyRequests[i] = NOREQ
        set AllyTimers[i] = NewTimer()
        set i = i + 1
    endloop
endfunction

//===========================================================================
private function Init takes nothing returns nothing
    local trigger t = CreateTrigger()
    local trigger t1 = CreateTrigger()
    local trigger t2 = CreateTrigger()
   
    call TriggerRegisterTimerEvent(t, 0.01, false)
    call TriggerAddAction( t, function Start )
   
    call TriggerRegisterAnyUnitEventBJ( t1, EVENT_PLAYER_UNIT_SPELL_CAST )
    call TriggerAddCondition( t1, Condition( function Request_Alliance_Conditions ) )
    call TriggerAddAction( t1, function Request_Alliance )
   
    call TriggerRegisterAnyUnitEventBJ( t2, EVENT_PLAYER_UNIT_SPELL_CAST )
    call TriggerAddCondition( t2, Condition( function Quit_Alliance_Conditions ) )
    call TriggerAddAction( t2, function Quit_Alliance )
   
endfunction

endscope
 
//TESH.scrollpos=0
//TESH.alwaysfold=0
library CreepSystem initializer Init requires CoreSystem
   
    struct Insect
        integer level = 1
        integer id
        integer family = 0
// 0 = none, 1 = ant, 2 = red ant, 3 = spider, 4 = beetle, 5 = bee, 6=scorpion, 7=zerg 99 = neutral
        integer max = 0    // Maximum number of units of this time at a time
        boolean ug = false
    endstruct
   
    globals
        unit array All_Creeps[1]
        integer N = 1
       
        private Insect array All_Insects[1]
       
        private Insect GreenWorm
        private Insect EarthWorm
       
       
       
        // ground creeps
        private integer array Creep_Type[1]
        integer array Creep_Count[1]
        private integer array Creep_Max[1]
       
        // underground creeps
        private integer array Creep_Type_UG[1]
        private integer array Creep_Count_UG[1]
        private integer array Creep_Max_UG[1]        

        private unit TempUnit
       
        private group Pray = CreateGroup()
       
    endglobals

private function IsAggressive takes unit u returns boolean
    if GetUnitTypeId(u) == 'n003' then
        return false
    endif
    if GetUnitTypeId(u) == 'n000' then
        return false
    endif
    if GetUnitTypeId(u) == 'u001' then
        return false
    endif
    if GetUnitTypeId(u) == 'u002' then
        return false
    endif
    if GetUnitTypeId(u) == 'u00F' then
        return false
    endif
    if GetUnitTypeId(u) == 'u00E' then
        return false
    endif
    return true
endfunction

private function Creep_Attack_Back takes nothing returns nothing
    if IsAggressive(GetTriggerUnit()) then
        call IssueTargetOrder( GetTriggerUnit(), "attack", GetAttacker() )
    endif
endfunction

private function GetCreepFamily takes unit u returns integer

    // 0 = unknown
    // 1 = black ants
    // 2 = red ants
    // 3 = spiders
    // 4 = beetles
   
    // Ants
    if GetUnitTypeId(u) == 'n00F' then
        return 1
    endif
    if GetUnitTypeId(u) == 'n00I' then
        return 1
    endif
    if GetUnitTypeId(u) == 'n00G' then
        return 1
    endif
   
    // Spiders
    if GetUnitTypeId(u) == 'n007' then
        return 3
    endif
    if GetUnitTypeId(u) == 'n00L' then
        return 3
    endif
    if GetUnitTypeId(u) == 'n00J' then
        return 3
    endif
   
    // Beetles
    if GetUnitTypeId(u) == 'u00I' then
        return 4
    endif
    if GetUnitTypeId(u) == 'u00D' then
        return 4
    endif
   
    // Bees
    if GetUnitTypeId(u) == 'n001' then
        return 5
    endif
   
    // Scorpions
    if GetUnitTypeId(u) == 'n004' then
        return 6
    endif
    if GetUnitTypeId(u) == 'n005' then
        return 6
    endif    
    if GetUnitTypeId(u) == 'n006' then
        return 6
    endif    
   
    // Zerg
    if GetUnitTypeId(u) == 'z000' then
        return 7
    endif
   
    // Coakroach
    if GetUnitTypeId(u) == 'z001' then
        return 8
    endif
   
    // Neutral - don't get attacked
    if GetUnitTypeId(u) == 'h000' then
        return 99
    endif
   
   
    return 0
   
endfunction


private function Make_Creeps_Attack_Filter takes nothing returns boolean
    local boolean b
   
    if GetFilterUnit() == TempUnit then
        return false
    endif
   
   // if GetUnitLevel(TempUnit) - GetUnitLevel(GetFilterUnit()) > 30 then
   //     return false
   // endif
   
    if GetUnitLevel(GetFilterUnit()) > GetUnitLevel(TempUnit) then
        return false
    endif
   
    if GetUnitState(GetFilterUnit(), UNIT_STATE_LIFE) <= 0 then
        return false
    endif
   
    if GetCreepFamily(GetFilterUnit()) == 99 then
        return false
    endif
   
    if GetCreepFamily(GetFilterUnit()) != 0 and GetCreepFamily(GetFilterUnit()) == GetCreepFamily(TempUnit) then
        return false
    endif
   
    if GetUnitTypeId(GetFilterUnit()) == 'n008' then
        return false
    endif
   
    return true    
endfunction
   
private function Creeps_AI takes nothing returns nothing
    local integer i
    local unit t
    local real x
    local real y
   
    set i = 0
    loop
        exitwhen i >= N
        set TempUnit = All_Creeps[i]
        set t = null
      //  set t = GetClosestUnitInRange(GetUnitX(All_Creeps[i]), GetUnitY(All_Creeps[i]), GetUnitAcquireRange(All_Creeps[i]), Condition(function Make_Creeps_Attack_Filter))
        call GroupClear(Pray)
        call GroupEnumUnitsInRange(Pray, GetUnitX(All_Creeps[i]), GetUnitY(All_Creeps[i]), GetUnitAcquireRange(All_Creeps[i]), Condition(function Make_Creeps_Attack_Filter))
       
        set t = FirstOfGroup(Pray)
       
        //if i == 0 then
        //    call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,5,"Spider range: "+R2S(GetUnitAcquireRange(All_Creeps[i])))
        //    call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,5,"t : "+GetUnitName(t))
        //endif
       
        // Found enemy in range?
    //    if t != null and GetUnitCurrentOrder(All_Creeps[i]) != OrderId("attack") and IsAggressive(All_Creeps[i]) then
        if t != null and IsAggressive(All_Creeps[i]) then
            call IssueTargetOrder( All_Creeps[i], "attack", t )
            //if i == 0 then
            //    call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,5,"Spider attacks: "+GetUnitName(t))
            //endif
        elseif GetUnitCurrentOrder(All_Creeps[i]) == 0 then
            set x = Get_Random_X
            if Is_Ground(All_Creeps[i]) then
                set y = Get_Random_Y(false)
            else
                set y = Get_Random_Y(true)
            endif
            call IssuePointOrder( All_Creeps[i], "move", x, y )
            //if i == 0 then
            //    call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,5,"Spider move on")
            //endif
        endif
       
        set i = i + 1
    endloop
   
    set t = null    
endfunction

private function CreateCreep takes nothing returns nothing

endfunction

private function Spawn_Creeps takes nothing returns nothing
    local integer i
    local real x
    local real y
    local effect e
   
    // Ground creeps
    set i = 0
    loop
        exitwhen i > 60
        if Creep_Count[i] < Creep_Max[i] and Creep_Type[i] != null then
            set x = Get_Random_X()
            set y = Get_Random_Y(false)
            set e = AddSpecialEffect("Abilities\\Spells\\Undead\\AnimateDead\\AnimateDeadTarget.mdl", x, y)
            set All_Creeps[N] = CreateUnit(Player(PLAYER_NEUTRAL_AGGRESSIVE), Creep_Type[i], x, y, bj_UNIT_FACING)
           
            call SetUnitUserData(All_Creeps[N], N)

            set Creep_Count[i] = Creep_Count[i] + 1
        //    call CoreSystem_Debug_Message("Creep created: " + GetUnitName(All_Creeps[N]) + ", count: " + I2S(Creep_Count[i]) )
         
            set N = N + 1
            call DestroyEffect(e)
        endif
        set i = i + 5
    endloop
   
    // Underground creeps
    set i = 0
    loop
        exitwhen i > 50
        if Creep_Count_UG[i] < Creep_Max_UG[i] and Creep_Type_UG[i] != null then
            set x = Get_Random_X_Underground()
            set y = Get_Random_Y(true)
            set e = AddSpecialEffect("Objects\\Spawnmodels\\Undead\\ImpaleTargetDust\\ImpaleTargetDust.mdl", x, y)
            set All_Creeps[N] = CreateUnit(Player(PLAYER_NEUTRAL_AGGRESSIVE), Creep_Type_UG[i], x, y, bj_UNIT_FACING)
           
            call SetUnitUserData(All_Creeps[N], N)
           
            set Creep_Count_UG[i] = Creep_Count_UG[i] + 1
          //  call CoreSystem_Debug_Message("Creep created: " + GetUnitName(All_Creeps[N]) + ", count: " + I2S(Creep_Count_UG[i]) )
            set N = N + 1
            call DestroyEffect(e)
        endif
        set i = i + 5
    endloop
   
    set e = null
   
endfunction

private function A_Creep_dies takes nothing returns nothing
    local integer id = GetPlayerId(GetOwningPlayer(GetKillingUnit()))
    local integer i = GetUnitLevel(GetDyingUnit())
    local effect e
    local integer n = GetUnitUserData(GetDyingUnit())
   
    if n == 0 then
        call CoreSystem_Debug_Message("Dying Unit without Data: "+GetUnitName(GetDyingUnit()))
    endif
   
    // the last creep on stack takes place of the dying unit
    if n != 0 then
        set N = N - 1
        set All_Creeps[n] = All_Creeps[N]
        call SetUnitUserData(All_Creeps[n], n)
        set All_Creeps[N] = null
    endif
   
    if i == 1 then
        set i = 0
    endif
   
    if Is_Underground(GetDyingUnit()) then
        set Creep_Count_UG[i] = Creep_Count_UG[i] - 1
    else
        set Creep_Count[i] = Creep_Count[i] - 1
    endif
   
    // Worms
    if GetUnitTypeId(GetDyingUnit()) == 'u001' then
        set e = AddSpecialEffectTarget("Objects\\Spawnmodels\\NightElf\\NightElfBlood\\NightElfBloodArcher.mdl", GetDyingUnit(), "origin")
    endif
   
    // Evil Spider
    if GetUnitTypeId(GetDyingUnit()) == 'n00L' then
        call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0, 15, PlayerNames[id] + " has slain |cff996CFFThe Evil Spider|r!"  )
        call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0, 15, "Seems, she's not the most dangerous insect in the carrot garden any more.." )
    endif    
   
    call DestroyEffect(e)
    set e = null
   
endfunction


private function Init_CreepSystem takes nothing returns nothing
    local integer n = 0
   
    // Init special bosses
    set All_Creeps[1] = gg_unit_n00L_0026   // Evil Spider
    call SetUnitUserData(All_Creeps[1], 1)
   
    // Plants
    set All_Creeps[2] = gg_unit_h000_0000
    call SetUnitUserData(All_Creeps[2], 2)
    set All_Creeps[3] = gg_unit_h000_0028
    call SetUnitUserData(All_Creeps[3], 4)
    set All_Creeps[4] = gg_unit_h000_0004
    call SetUnitUserData(All_Creeps[4], 4)
   
   // set All_Creeps[1] = CreateUnit(Player(PLAYER_NEUTRAL_AGGRESSIVE), 'u003', Get_Random_X, Get_Random_Y(true), bj_UNIT_FACING )
   // set All_Creeps[2] = CreateUnit(Player(PLAYER_NEUTRAL_AGGRESSIVE), 'n00K', Get_Random_X, Get_Random_Y(true), bj_UNIT_FACING )
    set N = 5 // Set N to the next free slot
   
   
    //  Ground creeps
   
    // Green worm
    set GreenWorm       = Insect.create()
    set GreenWorm.level = 1
    set GreenWorm.id    = 'u001'
    set GreenWorm.max   = 30
    set All_Insects[n]  = GreenWorm
    set n = n + 1
   
    // baby ant
    set EarthWorm       = Insect.create()
    set EarthWorm.level = 1
    set EarthWorm.id    = 'u002'
    set EarthWorm.max   = 20
   
    // Init creep types
    set Creep_Type[0]  = 'u001' // green worm
    set Creep_Type[5]  = 'n00G' // baby ant
    set Creep_Type[10] = 'n00F' // ant
    set Creep_Type[15] = 'u00F' // slug
  //  set Creep_Type[20] = 'n00I' // red ant
    set Creep_Type[25] = 'u00E' // snail
    set Creep_Type[30] = 'n007' // green spider
    set Creep_Type[35] = 'n003' // fly
    set Creep_Type[40] = 'u00D' // carrion beetle
    set Creep_Type[45] = 'n000' // dragon-fly
    set Creep_Type[50] = 'n00J' // spitting spider
    set Creep_Type[60] = 'u00I' // bark beetle
   
    // Init creep max
    set Creep_Max[0]   = 35 // green worm
    set Creep_Max[5]   = 8 // baby ant
    set Creep_Max[10]  = 5  // ant
    set Creep_Max[15]  = 3  // slug
 //   set Creep_Max[20]  = 3  // red ant
    set Creep_Max[25]  = 2  // snail
    set Creep_Max[30]  = 4  // green spider
    set Creep_Max[35]  = 5  // fly
    set Creep_Max[40]  = 3  // carrion beetle
    set Creep_Max[45]  = 2  // dragon-fly
    set Creep_Max[50]  = 1  // spitting spider
    set Creep_Max[60]  = 1  // bark beetle
   
   
    //  Underground creeps
    set Creep_Type_UG[0]  = 'u002' // earth worm
    set Creep_Type_UG[10] = 'z001' // coackroach
    set Creep_Type_UG[20] = 'z000' // zergling
    set Creep_Type_UG[30] = 'n005' // baby scorpion
    set Creep_Type_UG[40] = 'n004' // scorpion
    set Creep_Type_UG[50] = 'n006' // giant scorpion
   
    set Creep_Max_UG[0]   = 20 // earth worm
    set Creep_Max_UG[10]  = 10 // coackroach
    set Creep_Max_UG[20]  = 8 // zergling
    set Creep_Max_UG[30]  = 5 // baby scorpion
    set Creep_Max_UG[40]  = 3 // scorpion
    set Creep_Max_UG[50]  = 2 // giant scorpion
   
endfunction

function Spawn_Creeps_First takes nothing returns nothing
    local integer i
    // Spawn initial creeps
    set i = 0
    loop
        exitwhen i > 35
        call Spawn_Creeps()
        set i = i + 1
    endloop
   
endfunction

//===========================================================================
private function Init takes nothing returns nothing
    local trigger t = CreateTrigger()
    local trigger t2 = CreateTrigger()
    local trigger t3 = CreateTrigger()
    local trigger t4 = CreateTrigger()
    local trigger t5 = CreateTrigger()
    call TriggerRegisterTimerEvent(t, 0.01, false)
    call TriggerAddAction(t, function Init_CreepSystem)
    call TriggerRegisterTimerEvent(t2, 5, true)
    call TriggerAddAction(t2, function Spawn_Creeps)
    call TriggerRegisterTimerEvent(t3, 2, true)
    call TriggerAddAction(t3, function Creeps_AI)
    call TriggerRegisterPlayerUnitEvent(t4, Player(PLAYER_NEUTRAL_AGGRESSIVE), EVENT_PLAYER_UNIT_DEATH, null)
    call TriggerAddAction( t4, function A_Creep_dies )
    call TriggerRegisterPlayerUnitEvent( t5, Player(PLAYER_NEUTRAL_AGGRESSIVE), EVENT_PLAYER_UNIT_ATTACKED, null )
    call TriggerAddAction( t5, function Creep_Attack_Back )
endfunction

endlibrary
 
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope Beehive initializer Init

    globals
        private constant integer HIVE_ID = 'o000'
       
        private constant real HIVE_X = -4100
        private constant real HIVE_Y = 6150
       
        private constant real INNER_HIVE_X = -4930 //-4800
        private constant real INNER_HIVE_Y = 6980 //6840
       
        private constant boolean BeeAttack = false
        private constant integer BEES_MAX = 10
       
        private constant integer BEE_ID = 'n001'
       
        private  unit The_Hive
       
        integer Bee_N = 0
        unit array Bees
       
        private boolean BeeSleepingTime = false
       
        private integer Flowers_Count = 0
        private destructable array Flowers[1]
       
    endglobals


private function IsBee takes nothing returns boolean
    return GetUnitTypeId(GetTriggerUnit()) == BEE_ID
endfunction

private function IsBeeInHive takes unit u returns boolean
    if GetUnitX(u) < -4350 and GetUnitY(u) > 6300 then
        return true
    endif
    return false
endfunction

private function GetRandomX_AtHive takes nothing returns real
    return GetRandomReal(-5120, -3584)
endfunction

private function GetRandomY_AtHive takes nothing returns real
    return GetRandomReal(5632, 7168)
endfunction

private function GetRandomFlower takes nothing returns destructable
    return Flowers[GetRandomInt(0, Flowers_Count-1)]
endfunction

private function InitFlowers_Callback takes nothing returns nothing
    set Flowers[Flowers_Count] = GetEnumDestructable()
    set Flowers_Count = Flowers_Count + 1
endfunction

private function InitFlowers_Filter takes nothing returns boolean
    return GetDestructableTypeId(GetFilterDestructable()) == 'B000' or GetDestructableTypeId(GetFilterDestructable()) == 'B005'
endfunction

private function InitFlowers takes nothing returns nothing
    call EnumDestructablesInRect(bj_mapInitialPlayableArea, Filter(function InitFlowers_Filter), function InitFlowers_Callback)
endfunction

private function BackToHive takes nothing returns nothing
    if not BeeAttack then
        call IssuePointOrder(GetTriggerUnit(), "attack", HIVE_X, HIVE_Y)
    endif
endfunction

private function Bee_Attack_Back takes nothing returns nothing
    call IssueTargetOrder( GetTriggerUnit(), "shadowstrike", GetAttacker() )
endfunction

private function Bees_AI takes nothing returns nothing
    local integer i

    set i = 1
    loop
        exitwhen i > Bee_N

        if BeeSleepingTime then
            if not IsBeeInHive(Bees[i]) then
                call IssuePointOrder(Bees[i], "move", INNER_HIVE_X, INNER_HIVE_Y)
            endif
        else
            if GetUnitCurrentOrder(Bees[i]) == 0 then
                // Bee is in hive?
                if IsBeeInHive(Bees[i]) then
                    call IssuePointOrder(Bees[i], "move", HIVE_X, HIVE_Y)
                else
                    call IssueTargetOrder( Bees[i], "harvest", GetRandomFlower() )
                endif
            elseif GetUnitCurrentOrder(Bees[i]) == 852017 then
                call IssueTargetOrder( Bees[i], "smart", The_Hive )
                call IssuePointOrder(Bees[i], "move", INNER_HIVE_X, INNER_HIVE_Y)
            elseif GetUnitCurrentOrder(Bees[i]) == 852660 then
                call IssueImmediateOrder( Bees[i], "resumeharvesting" )
            endif
        endif
           
        set i = i + 1
    endloop
   
    set i = 0
    loop
        exitwhen i > Flowers_Count-1
        call SetDestructableLife( Flowers[i], GetDestructableMaxLife(Flowers[i]))
        set i = i + 1
    endloop
endfunction

private function Bees_Idle_At_Hive takes nothing returns nothing
    local integer i = 0
    if not BeeSleepingTime then
        loop
            exitwhen i > Bee_N
            call IssuePointOrder(Bees[i], "attack", GetRandomX_AtHive(), GetRandomY_AtHive())
            set i = i + 1
        endloop
    endif
endfunction

private function Hive_Under_Attack takes nothing returns nothing
    local integer i
   
    call DisplayTimedTextToPlayer(GetOwningPlayer(GetAttacker()),0,0,5,"This will make the bees very angry..")
   
    set i = 1
    loop
        exitwhen i > Bee_N
        call IssueTargetOrder(Bees[i], "shadowstrike", GetAttacker())
        set i = i + 1
    endloop
endfunction

private function BeesGoToBed takes nothing returns nothing
    local integer i
   
    if BeeSleepingTime == false then
        set BeeSleepingTime = true
        set i = 1
        loop
            exitwhen i > Bee_N-1
            call IssuePointOrder(Bees[i], "move", INNER_HIVE_X, INNER_HIVE_Y)
            set i = i + 1
        endloop
    endif
endfunction

function BeesAwake takes nothing returns nothing
    local integer i
   
    if BeeSleepingTime == true then
        set BeeSleepingTime = false
        set i = 1
        loop
            exitwhen i > Bee_N
            call IssuePointOrder(Bees[i], "move", HIVE_X, HIVE_Y)
            set i = i + 1
        endloop
    endif
endfunction

private function Create_Bee takes nothing returns nothing
    if Bee_N < BEES_MAX then
        set Bee_N = Bee_N + 1
        set Bees[Bee_N] = CreateUnit(Player(9), BEE_ID, INNER_HIVE_X, INNER_HIVE_Y, bj_UNIT_FACING)
        call SetUnitUserData(Bees[Bee_N], Bee_N)
        call IssuePointOrder(Bees[Bee_N], "move", HIVE_X, HIVE_Y)
    endif
endfunction

private function Bee_Triggers takes nothing returns nothing
    // call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,5,"Periodic Bee trigger")
    call Create_Bee()
    call Bees_AI()
   
    // call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,5,"Bee Honey: "+I2S(GetPlayerState(Player(9), PLAYER_STATE_RESOURCE_LUMBER)) )
   
endfunction

function Beehive_Start takes nothing returns nothing
    local integer i
   
    call InitFlowers()
   
    set i = 0
    loop
        exitwhen i > BEES_MAX-1
        call Create_Bee()
        set i = i + 1
    endloop
   
    set The_Hive = CreateUnit(Player(9), HIVE_ID, INNER_HIVE_X, INNER_HIVE_Y, bj_UNIT_FACING)
   
endfunction

private function A_Bee_dies takes nothing returns nothing
    local integer dead_n = GetUnitUserData(GetDyingUnit())
   
    if dead_n == 0 then
        call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,5,"|cffFF0000Bee without User data died!|r")
    endif
   
    // The last unit on stack takes place of the dead unit
    set Bees[dead_n] = Bees[Bee_N]
    // The last place on stack get's nulled
    set Bees[Bee_N] = null
    // The stack-moved unit gets new user data
    call SetUnitUserData(Bees[dead_n], dead_n)
    // decrease stack
    set Bee_N = Bee_N - 1
   
endfunction

// =====================================================
private function Init takes nothing returns nothing
    local trigger t = CreateTrigger()
    local trigger t2 = CreateTrigger()
    local trigger t3 = CreateTrigger()
    local trigger t4 = CreateTrigger()
    local trigger t5 = CreateTrigger()
    local trigger t6 = CreateTrigger()
    local trigger t7 = CreateTrigger()

    call TriggerRegisterTimerEvent(t, 0.01, false)
    call TriggerAddAction( t, function Beehive_Start )
   
   // call TriggerRegisterLeaveRectSimple( t, gg_rct_Beehive )
   // call TriggerAddCondition( t, Condition( function IsBee ) )
   // call TriggerAddAction( t, function BackToHive )
   
    call TriggerRegisterPlayerUnitEvent(t2, Player(9), EVENT_PLAYER_UNIT_DEATH, null)
    call TriggerAddCondition( t2, Condition( function IsBee ) )
    call TriggerAddAction( t2, function A_Bee_dies )
   
    call TriggerRegisterTimerEvent(t3, 5.0, true)
    call TriggerAddAction( t3, function Bee_Triggers )
   
    call TriggerRegisterGameStateEvent(t4, GAME_STATE_TIME_OF_DAY, EQUAL, 17.50)
    call TriggerAddAction( t4, function BeesGoToBed )
   
    call TriggerRegisterGameStateEvent(t5, GAME_STATE_TIME_OF_DAY, EQUAL, 6.00)
    call TriggerAddAction( t5, function BeesAwake )
   
    call TriggerRegisterPlayerUnitEvent(t6, Player(9), EVENT_PLAYER_UNIT_ATTACKED, null)
    call TriggerAddAction( t6, function Bee_Attack_Back )
   
    call TriggerRegisterUnitEvent( t7, gg_unit_h001_0015, EVENT_UNIT_ATTACKED )
    call TriggerAddAction( t7, function Hive_Under_Attack )
endfunction

endscope
 
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope Ants initializer Init

    globals
        private constant real RED_AREA_MIN_X = 4096
        private constant real RED_AREA_MAX_X = 5120
        private constant real RED_AREA_MIN_Y = -5120
        private constant real RED_AREA_MAX_Y = -4096
       
        private constant real BLACK_AREA_MIN_X = 512
        private constant real BLACK_AREA_MAX_X = 1536
        private constant real BLACK_AREA_MIN_Y = -1536
        private constant real BLACK_AREA_MAX_Y = -512
       
        private constant integer RED_ANT = 'n00I'
        private constant integer BLACK_ANT = 'n00A'
       
        private unit Red_Queen
        private unit Black_Queen
       
        unit array Ants[1]
        integer Ants_N = 1
       
    endglobals
   
private function IsAnt takes nothing returns boolean
    return GetUnitTypeId(GetTriggerUnit()) == RED_ANT or GetUnitTypeId(GetTriggerUnit()) == BLACK_ANT
endfunction

private function IsRedAnt takes unit u returns boolean
    return GetUnitTypeId(u) == RED_ANT
endfunction

private function GetRandomSpawnX takes boolean IsRed returns real
    if IsRed then
        return GetRandomReal(RED_AREA_MIN_X, RED_AREA_MAX_X)
    endif
    return GetRandomReal(BLACK_AREA_MIN_X, BLACK_AREA_MAX_X)
endfunction    

private function GetRandomSpawnY takes boolean IsRed returns real
    if IsRed then
        return GetRandomReal(RED_AREA_MIN_Y, RED_AREA_MAX_Y)
    endif
    return GetRandomReal(BLACK_AREA_MIN_Y, BLACK_AREA_MAX_Y)
endfunction    

private function Ants_Reactivator takes nothing returns nothing
    local integer i
   
    set i = 0
    loop
        exitwhen i > Ants_N - 1

        if GetUnitCurrentOrder(Ants[i]) == 0 then
            if GetUnitY(Ants[i]) < 0 then
                if IsRedAnt(Ants[i]) then
                    call IssuePointOrder(Ants[i], "attack", BLACK_AREA_MIN_X, BLACK_AREA_MAX_Y)
                else
                    call IssuePointOrder(Ants[i], "attack", RED_AREA_MAX_X, RED_AREA_MIN_Y)
                endif
            else
                if IsRedAnt(Ants[i]) then
                    call IssuePointOrder(Ants[i], "attack", GetUnitX(gg_unit_n008_0022), GetUnitY(gg_unit_n008_0022))
                else
                    call IssuePointOrder(Ants[i], "attack", GetUnitX(gg_unit_n008_0017), GetUnitY(gg_unit_n008_0017))
                endif
            endif
        endif
        // call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,5,"Ants["+I2S(i)+"]: "+ GetUnitName(Ants[i])+" order: "+ I2S(GetUnitCurrentOrder(Ants[i])))
       
        set i = i + 1
    endloop

endfunction

private function CreateAnt takes boolean IsRed returns nothing
    local effect e
   
    if IsRed then
        set Ants[Ants_N] = CreateUnit(Player(11), RED_ANT, GetRandomSpawnX(true), GetRandomSpawnY(true), bj_UNIT_FACING)
    else
        set Ants[Ants_N] = CreateUnit(Player(10), BLACK_ANT, GetRandomSpawnX(false), GetRandomSpawnY(false), bj_UNIT_FACING)
    endif
   
    set e = AddSpecialEffect("Objects\\Spawnmodels\\Undead\\ImpaleTargetDust\\ImpaleTargetDust.mdl", GetUnitX(Ants[Ants_N]), GetUnitY(Ants[Ants_N]))
   
    call SetUnitUserData(Ants[Ants_N], Ants_N)
   
    set Ants_N = Ants_N + 1
   
    call DestroyEffect(e)
    set e = null
endfunction

private function SpawnAnts takes nothing returns nothing  
    // Red Ants
    if GetUnitState(Red_Queen, UNIT_STATE_LIFE) > 0 then
        call CreateAnt(true)
        call IssuePointOrder(Ants[Ants_N-1], "attack", BLACK_AREA_MIN_X, BLACK_AREA_MAX_Y)
        call CreateAnt(true)
        call IssuePointOrder(Ants[Ants_N-1], "attack", 3772, -4924)
    endif
   
    // Black Ants
    if GetUnitState(Black_Queen, UNIT_STATE_LIFE) > 0 then
        call CreateAnt(false)
        call IssuePointOrder(Ants[Ants_N-1], "attack", RED_AREA_MAX_X, RED_AREA_MIN_Y)
        call CreateAnt(false)
        call IssuePointOrder(Ants[Ants_N-1], "attack", 701, -1855)
    endif
endfunction

private function An_Ant_dies takes nothing returns nothing
    local integer n = GetUnitUserData(GetDyingUnit())
    // call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,5,"Ant died, id: "+I2S(n))
    if n != 0 then
        set Ants_N = Ants_N - 1
        set Ants[n] = Ants[Ants_N]
        call SetUnitUserData(Ants[n], n)
        set Ants[Ants_N] = null
    endif
endfunction

private function Start takes nothing returns nothing
    set Red_Queen = gg_unit_n00K_0030
    set Black_Queen = gg_unit_n00C_0034
endfunction


// =====================================================
private function Init takes nothing returns nothing
    local trigger t = CreateTrigger()
    local trigger t2 = CreateTrigger()
    local trigger t3 = CreateTrigger()
    local trigger t4 = CreateTrigger()
    call TriggerRegisterTimerEvent(t, 0.01, false)
    call TriggerAddAction(t, function Start)
    call TriggerRegisterTimerEvent(t2, 10.0, true)
    call TriggerAddAction(t2, function SpawnAnts)
    call TriggerRegisterPlayerUnitEvent(t3, Player(10), EVENT_PLAYER_UNIT_DEATH, null)
    call TriggerRegisterPlayerUnitEvent(t3, Player(11), EVENT_PLAYER_UNIT_DEATH, null)
    call TriggerAddCondition( t3, Condition( function IsAnt ) )
    call TriggerAddAction( t3, function An_Ant_dies )
    call TriggerRegisterTimerEvent(t4, 5.00, true)
    call TriggerAddAction(t4, function Ants_Reactivator)
endfunction

endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope FoodRespawn initializer Init

    globals
        private constant integer FOOD_MAX = 8
        private integer Food_Count = 0
        private item array Food[1]
       
        private constant integer FOOD_MAX_UG = 8
        private integer Food_Count_UG = 0
        private item array Food_UG[1]
    endglobals

private function GetFoodX takes nothing returns real
    return GetRandomReal(4000,5000)
endfunction    
private function GetFoodY takes nothing returns real
    return GetRandomReal(3600,4600)
endfunction  


private function GetRandomMushroom takes nothing returns integer
    local integer i = GetRandomInt(0,40)
    if i > 30 then
        return 'I004'
    endif
    if i > 20 then
        return 'I003'
    endif
    if i > 10 then
        return 'I002'
    endif
    return 'I001'
endfunction

private function CreateFood takes nothing returns nothing
   
    // Ground food
    if not IsItemOwned(Food[Food_Count]) then
        call RemoveItem(Food[Food_Count])
    endif
   
    set Food[Food_Count] = CreateItem( 'I000', Get_Random_X(), Get_Random_Y(false) )
    set Food_Count = Food_Count + 1
   
    if Food_Count > FOOD_MAX-1 then
        set Food_Count = 0
    endif
   
   
    // Underground food
    if not IsItemOwned(Food_UG[Food_Count_UG]) then
        call RemoveItem(Food_UG[Food_Count_UG])
    endif
   
    set Food_UG[Food_Count_UG] = CreateItem( GetRandomMushroom(), Get_Random_X(), Get_Random_Y(true) )
    set Food_Count_UG = Food_Count_UG + 1
   
    if Food_Count_UG > FOOD_MAX_UG-1 then
        set Food_Count_UG = 0
    endif
   
endfunction

private function Start takes nothing returns nothing
    local integer i
   
    set i = 0
    loop
        exitwhen i > FOOD_MAX-1
        call CreateFood()
        set i = i + 1
    endloop
   
endfunction

//===========================================================================
private function Init takes nothing returns nothing
    local trigger t = CreateTrigger()
    local trigger t2 = CreateTrigger()
    call TriggerRegisterTimerEvent(t, 5, true)
    call TriggerAddAction(t, function CreateFood)
    call TriggerRegisterTimerEvent(t2, 0.01, false)
    call TriggerAddAction(t2, function Start)
endfunction
endscope
 
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope AIBugsTravel initializer Init

private function Actions takes nothing returns nothing
    local integer id
   
    set id = 0
    loop
        exitwhen id > 11
        // On Ground?
        if Bugs_AI[id] != null then
            if GetUnitY(Bugs_AI[id]) > 0 then
                call IssuePointOrder( Bugs_AI[id], "attack", Get_Random_X(), Get_Random_Y(false))
            // Underground?
            else
                if GetUnitCurrentOrder(Bugs_AI[id]) == 0 then
                    call IssueImmediateOrder(Bugs_AI[id], "fanofknives")
                    call TriggerSleepAction(0.25)
                    call IssuePointOrder( Bugs_AI[id], "attack", Get_Random_X(), Get_Random_Y(true))
                endif
            endif
        endif
        set id = id + 1
    endloop
   
endfunction

//===========================================================================
private function Init takes nothing returns nothing
    local trigger trg = CreateTrigger(  )
    call TriggerRegisterTimerEvent(trg, 3, true)
    call TriggerAddAction( trg, function Actions )
endfunction

endscope
 
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope RandomUndergroundEffects initializer Init

private function Actions takes nothing returns nothing
    local real x = GetRandomReal(-3200, 3200)
    local real y = GetRandomReal(-5000, -100)
    local effect e
    set e = AddSpecialEffect("Objects\\Spawnmodels\\Undead\\ImpaleTargetDust\\ImpaleTargetDust.mdl", x, y)
    call DestroyEffect(e)
    set e = null
endfunction

//===========================================================================
private function Init takes nothing returns nothing
    local trigger trg = CreateTrigger(  )
    call TriggerRegisterTimerEvent(trg, 1.00, true)
    call TriggerAddAction( trg, function Actions )
endfunction

endscope

 
//TESH.scrollpos=22
//TESH.alwaysfold=0
scope Weather initializer Init

    globals
        private constant integer RAIN_CHANCE = 30
        private weathereffect Rain
        boolean IsRaining = false
    endglobals

private function WeatherEffect takes nothing returns nothing
    local integer i = GetRandomInt(1,100)
    local integer j
   
    if i <= RAIN_CHANCE and IsRaining == false then
        set IsRaining = true
        set j = GetRandomInt(0,40)
       
        if j > 30 then
            set Rain = AddWeatherEffect(Ground_Area, 'RAhr')
        elseif j > 20 then
            set Rain = AddWeatherEffect(Ground_Area, 'RAlr')
        elseif j > 10 then
            set Rain = AddWeatherEffect(Ground_Area, 'RLhr')
        else
            set Rain = AddWeatherEffect(Ground_Area, 'RLlr')
        endif        

        call EnableWeatherEffect( Rain, true )
       
    elseif IsRaining and i > RAIN_CHANCE then
        set IsRaining = false
        call RemoveWeatherEffect(Rain)
    endif
   
endfunction

private function Start takes nothing returns nothing
endfunction
   
   
//===========================================================================
private function Init takes nothing returns nothing
    local trigger t = CreateTrigger()
    local trigger t2 = CreateTrigger()
    call TriggerRegisterTimerEvent(t, 0.01, false)
    call TriggerAddAction(t, function Start)
    call TriggerRegisterTimerEvent(t2, 30.00, true)
    call TriggerAddAction(t2, function WeatherEffect)
endfunction

endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope Holes initializer Init
   
    globals
        private constant real HOLE_RANGE = 48
        private constant real HOLE_BUFFER = 96
    endglobals

private function HoleEffect takes boolean IsUnderground returns nothing
    local effect e
   
    set e = AddSpecialEffect("Objects\\Spawnmodels\\Undead\\ImpaleTargetDust\\ImpaleTargetDust.mdl", GetUnitX(GetTriggerUnit()), GetUnitY(GetTriggerUnit()))
   
    // Toggle Fog
    //if GetLocalPlayer() == GetOwningPlayer(GetTriggerUnit()) then
    //    if IsUnderground then
    //        call FFS_Change_Fog( FogUnderground, 0, 0 )
    //    else
    //        call FFS_Change_Fog( FogNoon, 0, 0 )
    //    endif
    //endif
   
    call DestroyEffect(e)
    set e = null
   
endfunction
   
private function Hole_Conditions takes nothing returns boolean
    if IsUnitType(GetTriggerUnit(), UNIT_TYPE_GROUND) == false then
        return false
    endif
    if GetUnitLevel(GetTriggerUnit()) > 40 and not IsUnitType(GetTriggerUnit(), UNIT_TYPE_HERO) then
        return false
    endif
    return true
endfunction
   
private function Hole1a takes nothing returns nothing
    call SetUnitPosition( GetTriggerUnit(), GetUnitX(gg_unit_n008_0021)+HOLE_BUFFER, GetUnitY(gg_unit_n008_0021)+HOLE_BUFFER )
    call HoleEffect(true)
endfunction
private function Hole1b takes nothing returns nothing
    call SetUnitPosition( GetTriggerUnit(), GetUnitX(gg_unit_n008_0016)+HOLE_BUFFER, GetUnitY(gg_unit_n008_0016)+HOLE_BUFFER )
    call HoleEffect(false)
endfunction


private function Hole2a takes nothing returns nothing
    call SetUnitPosition( GetTriggerUnit(), GetUnitX(gg_unit_n008_0018)+HOLE_BUFFER, GetUnitY(gg_unit_n008_0018)+HOLE_BUFFER )
    call HoleEffect(true)
endfunction
private function Hole2b takes nothing returns nothing
    call SetUnitPosition( GetTriggerUnit(), GetUnitX(gg_unit_n008_0017)+HOLE_BUFFER, GetUnitY(gg_unit_n008_0017)+HOLE_BUFFER )
    call HoleEffect(false)
endfunction


private function Hole3a takes nothing returns nothing
    call SetUnitPosition( GetTriggerUnit(), GetUnitX(gg_unit_n008_0023)+HOLE_BUFFER, GetUnitY(gg_unit_n008_0023)+HOLE_BUFFER )
    call HoleEffect(true)
endfunction
private function Hole3b takes nothing returns nothing
    call SetUnitPosition( GetTriggerUnit(), GetUnitX(gg_unit_n008_0022)+HOLE_BUFFER, GetUnitY(gg_unit_n008_0022)+HOLE_BUFFER )
    call HoleEffect(false)
endfunction


private function Hole4a takes nothing returns nothing
    call SetUnitPosition( GetTriggerUnit(), GetUnitX(gg_unit_n008_0025)+HOLE_BUFFER, GetUnitY(gg_unit_n008_0025)+HOLE_BUFFER )
    call HoleEffect(true)
endfunction
private function Hole4b takes nothing returns nothing
    call SetUnitPosition( GetTriggerUnit(), GetUnitX(gg_unit_n008_0024)+HOLE_BUFFER, GetUnitY(gg_unit_n008_0024)+HOLE_BUFFER )
    call HoleEffect(false)
endfunction


   
private function Start takes nothing returns nothing
endfunction

// ======================================
private function Init takes nothing returns nothing
    local trigger t = CreateTrigger()
    local trigger t1a = CreateTrigger()
    local trigger t1b = CreateTrigger()
    local trigger t2a = CreateTrigger()
    local trigger t2b = CreateTrigger()
    local trigger t3a = CreateTrigger()
    local trigger t3b = CreateTrigger()
    local trigger t4a = CreateTrigger()
    local trigger t4b = CreateTrigger()
    call TriggerRegisterTimerEvent(t, 0.01, false)
    call TriggerAddAction( t, function Start )
   
    call TriggerRegisterUnitInRange(t1a, gg_unit_n008_0016, HOLE_RANGE, null)
    call TriggerAddCondition(t1a, Condition(function Hole_Conditions))
    call TriggerAddAction(t1a, function Hole1a)
    call TriggerRegisterUnitInRange(t1b, gg_unit_n008_0021, HOLE_RANGE, null)
    call TriggerAddCondition(t1b, Condition(function Hole_Conditions))
    call TriggerAddAction(t1b, function Hole1b)
   
    call TriggerRegisterUnitInRange(t2a, gg_unit_n008_0017, HOLE_RANGE, null)
    call TriggerAddCondition(t2a, Condition(function Hole_Conditions))
    call TriggerAddAction(t2a, function Hole2a)
    call TriggerRegisterUnitInRange(t2b, gg_unit_n008_0018, HOLE_RANGE, null)
    call TriggerAddCondition(t2b, Condition(function Hole_Conditions))
    call TriggerAddAction(t2b, function Hole2b)
   
    call TriggerRegisterUnitInRange(t3a, gg_unit_n008_0022, HOLE_RANGE, null)
    call TriggerAddCondition(t3a, Condition(function Hole_Conditions))
    call TriggerAddAction(t3a, function Hole3a)
    call TriggerRegisterUnitInRange(t3b, gg_unit_n008_0023, HOLE_RANGE, null)
    call TriggerAddCondition(t3b, Condition(function Hole_Conditions))
    call TriggerAddAction(t3b, function Hole3b)
   
    call TriggerRegisterUnitInRange(t4a, gg_unit_n008_0024, HOLE_RANGE, null)
    call TriggerAddCondition(t4a, Condition(function Hole_Conditions))
    call TriggerAddAction(t4a, function Hole4a)
    call TriggerRegisterUnitInRange(t4b, gg_unit_n008_0025, HOLE_RANGE, null)
    call TriggerAddCondition(t4b, Condition(function Hole_Conditions))
    call TriggerAddAction(t4b, function Hole4b)
   
endfunction

endscope

 
//TESH.scrollpos=0
//TESH.alwaysfold=0
function Trig_Killme_Actions takes nothing returns nothing
    call KillUnit(Bugs[GetPlayerId(GetTriggerPlayer())])
endfunction

//===========================================================================
function InitTrig_Killme takes nothing returns nothing
    set gg_trg_Killme = CreateTrigger(  )
    call TriggerRegisterPlayerChatEvent( gg_trg_Killme, Player(0), "killme", true )
    call TriggerRegisterPlayerChatEvent( gg_trg_Killme, Player(1), "killme", true )
    call TriggerRegisterPlayerChatEvent( gg_trg_Killme, Player(2), "killme", true )
    call TriggerRegisterPlayerChatEvent( gg_trg_Killme, Player(3), "killme", true )
    call TriggerRegisterPlayerChatEvent( gg_trg_Killme, Player(4), "killme", true )
    call TriggerRegisterPlayerChatEvent( gg_trg_Killme, Player(5), "killme", true )
    call TriggerRegisterPlayerChatEvent( gg_trg_Killme, Player(6), "killme", true )
    call TriggerRegisterPlayerChatEvent( gg_trg_Killme, Player(7), "killme", true )
    call TriggerRegisterPlayerChatEvent( gg_trg_Killme, Player(8), "killme", true )
    call TriggerRegisterPlayerChatEvent( gg_trg_Killme, Player(9), "killme", true )
    call TriggerRegisterPlayerChatEvent( gg_trg_Killme, Player(10), "killme", true )
    call TriggerRegisterPlayerChatEvent( gg_trg_Killme, Player(11), "killme", true )
    call TriggerAddAction( gg_trg_Killme, function Trig_Killme_Actions )
endfunction

 
//TESH.scrollpos=0
//TESH.alwaysfold=0
function Trig_Set_Level_Conditions takes nothing returns boolean
    return DEBUG_MODE
endfunction

function Trig_Set_Level_Actions takes nothing returns nothing
    local integer id = GetPlayerId(GetTriggerPlayer())
    local integer level = S2I(SubString(GetEventPlayerChatString(), 8, 4))
    call SetHeroLevelBJ(Bugs[id], level, true)
    call CoreSystem_Set_Size(Bugs[id])
   
    call SetHeroLevelBJ(Bugs[1], level, true)
    call CoreSystem_Set_Size(Bugs[1])
   
endfunction

//===========================================================================
function InitTrig_Set_Level takes nothing returns nothing
    set gg_trg_Set_Level = CreateTrigger(  )
    call TriggerRegisterPlayerChatEvent( gg_trg_Set_Level, Player(0), "setlevel", false )
    call TriggerAddCondition( gg_trg_Set_Level, Condition( function Debug_Mode ) )
    call TriggerAddAction( gg_trg_Set_Level, function Trig_Set_Level_Actions )
endfunction

 
//TESH.scrollpos=0
//TESH.alwaysfold=0
function Trig_Health_Actions takes nothing returns nothing
    local integer id = GetPlayerId(GetTriggerPlayer())
   
    call SetUnitState(Bugs[id], UNIT_STATE_LIFE, GetUnitState(Bugs[id], UNIT_STATE_MAX_LIFE) )
   
    call SetUnitState(Bugs[1], UNIT_STATE_LIFE, GetUnitState(Bugs[id], UNIT_STATE_MAX_LIFE) )
endfunction

//===========================================================================
function InitTrig_Health takes nothing returns nothing
    set gg_trg_Health = CreateTrigger(  )
    call TriggerRegisterPlayerChatEvent( gg_trg_Health, Player(0), "health", false )
    call TriggerAddCondition( gg_trg_Health, Condition( function Debug_Mode ) )
    call TriggerAddAction( gg_trg_Health, function Trig_Health_Actions )
endfunction

 
//TESH.scrollpos=0
//TESH.alwaysfold=0
function Trig_Orders_Actions takes nothing returns nothing

    call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,5, "stop: " + I2S(OrderId("stop")))
    call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,5, "move: " + I2S(OrderId("move")))
    call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,5, "harvest: " + I2S(OrderId("harvest")))
    call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,5, "attack: " + I2S(OrderId("attack")))
    call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,5, "smart: " + I2S(OrderId("smart")))
    call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,5, " ")
    call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,5, "851971: " + OrderId2String(851971))
    call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,5, "852017: " + OrderId2String(852017))
    call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,5, "852018: " + OrderId2String(852018))
    call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,5, "852660: " + OrderId2String(852660))
    call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,5, "851986: " + OrderId2String(851986))
    call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,5, "0: " + OrderId2String(0))
endfunction

//===========================================================================
function InitTrig_Orders takes nothing returns nothing
    set gg_trg_Orders = CreateTrigger(  )
    call TriggerRegisterPlayerChatEvent( gg_trg_Orders, Player(0), "orders", false )
    call TriggerAddCondition( gg_trg_Orders, Condition( function Debug_Mode ) )
    call TriggerAddAction( gg_trg_Orders, function Trig_Orders_Actions )
endfunction

 
//TESH.scrollpos=0
//TESH.alwaysfold=0
function Trig_AI_Actions takes nothing returns nothing
    call PanCameraToTimedLocForPlayer( Player(0), GetUnitLoc(Bugs[1]), 0 )
    call TriggerSleepAction(1.0)
    call ResetToGameCameraForPlayer( Player(0), 0 )
endfunction

//===========================================================================
function InitTrig_AI takes nothing returns nothing
    set gg_trg_AI = CreateTrigger(  )
    call TriggerRegisterPlayerChatEvent( gg_trg_AI, Player(0), "AI", false )
    call TriggerAddCondition( gg_trg_AI, Condition(function Debug_Mode) )
    call TriggerAddAction( gg_trg_AI, function Trig_AI_Actions )
endfunction

 
//TESH.scrollpos=0
//TESH.alwaysfold=0
function Trig_Random_XY_Actions takes nothing returns nothing
    call DisplayTextToPlayer(GetTriggerPlayer(),0,0, "Random XY: " + R2S(Get_Random_X()) + "|" + R2S(Get_Random_Y(false)))
   
endfunction

//===========================================================================
function InitTrig_Random_XY takes nothing returns nothing
    set gg_trg_Random_XY = CreateTrigger(  )
    call TriggerRegisterPlayerChatEvent( gg_trg_Random_XY, Player(0), "random", false )
    call TriggerAddCondition( gg_trg_Random_XY, Condition( function Debug_Mode ) )
    call TriggerAddAction( gg_trg_Random_XY, function Trig_Random_XY_Actions )
endfunction

 
//TESH.scrollpos=0
//TESH.alwaysfold=0
function Trig_Count_Actions takes nothing returns nothing
    local integer i = S2I(SubString(GetEventPlayerChatString(), 5, 4))

    call DisplayTextToPlayer(GetTriggerPlayer(),0,0, "Count: " + I2S(Creep_Count[i]))
   
endfunction

//===========================================================================
function InitTrig_Count takes nothing returns nothing
    set gg_trg_Count = CreateTrigger(  )
    call TriggerRegisterPlayerChatEvent( gg_trg_Count, Player(0), "count", false )
    call TriggerAddCondition( gg_trg_Count, Condition( function Debug_Mode ) )
    call TriggerAddAction( gg_trg_Count, function Trig_Count_Actions )
endfunction

 
//TESH.scrollpos=0
//TESH.alwaysfold=0
function Trig_Creeps_Actions takes nothing returns nothing
    local integer i = 0
    loop
        exitwhen i >= N
        if All_Creeps[i] != null then
            call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,5,"Creep["+I2S(i)+"] : " + GetUnitName(All_Creeps[i]) + " Order: " + I2S(GetUnitCurrentOrder(All_Creeps[i])))
        else
            call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,5,"Creep["+I2S(i)+"] : |cffFF0000EMPTY!!!|r")
        endif
        call TriggerSleepAction(0.05)
        set i = i + 1
    endloop
endfunction

//===========================================================================
function InitTrig_Creeps takes nothing returns nothing
    set gg_trg_Creeps = CreateTrigger(  )
    call TriggerRegisterPlayerChatEvent( gg_trg_Creeps, Player(0), "creeps", true )
    call TriggerAddCondition( gg_trg_Creeps, Condition( function Debug_Mode ) )
    call TriggerAddAction( gg_trg_Creeps, function Trig_Creeps_Actions )
endfunction

 
//TESH.scrollpos=0
//TESH.alwaysfold=0
function Trig_AntsDisp_Actions takes nothing returns nothing
    local integer i = 0
    loop
        exitwhen i > Ants_N-1
        if Ants[i] != null then
            call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,5,"Ants["+I2S(i)+"] : " + GetUnitName(Ants[i]) + " Order: " + I2S(GetUnitCurrentOrder(Ants[i])))
        else
            call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,5,"Ants["+I2S(i)+"] : |cffFF0000EMPTY!!!|r")
        endif
        call TriggerSleepAction(0.05)
        set i = i + 1
    endloop
endfunction

//===========================================================================
function InitTrig_AntsDisp takes nothing returns nothing
    set gg_trg_AntsDisp = CreateTrigger(  )
    call TriggerRegisterPlayerChatEvent( gg_trg_AntsDisp, Player(0), "ants", true )
    call TriggerAddCondition( gg_trg_AntsDisp, Condition( function Debug_Mode ) )
    call TriggerAddAction( gg_trg_AntsDisp, function Trig_AntsDisp_Actions )
endfunction

 
//TESH.scrollpos=0
//TESH.alwaysfold=0
function Trig_BeesDisp_Actions takes nothing returns nothing
    local integer i = 0
    loop
        exitwhen i > Bee_N
        if Bees[i] != null then
            call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,5,"Bees["+I2S(i)+"] : " + GetUnitName(Bees[i]) + " Order: " + I2S(GetUnitCurrentOrder(Bees[i])))
            // call IssuePointOrder(Bees[i], "move", 0, 0)
        else
            call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,5,"Bees["+I2S(i)+"] : |cffFF0000EMPTY!!!|r")
        endif
        call TriggerSleepAction(0.05)
        set i = i + 1
    endloop
endfunction

//===========================================================================
function InitTrig_BeesDisp takes nothing returns nothing
    set gg_trg_BeesDisp = CreateTrigger(  )
    call TriggerRegisterPlayerChatEvent( gg_trg_BeesDisp, Player(0), "bees", true )
    call TriggerAddCondition( gg_trg_BeesDisp, Condition( function Debug_Mode ) )
    call TriggerAddAction( gg_trg_BeesDisp, function Trig_BeesDisp_Actions )
endfunction

 
//TESH.scrollpos=0
//TESH.alwaysfold=0
function Trig_Attack_Actions takes nothing returns nothing
    local integer i = 0
    local integer id = GetPlayerId(GetTriggerPlayer())
    local unit t

    set t = GetClosestUnitInRange(GetUnitX(Bugs[id]), GetUnitY(Bugs[id]), GetUnitAcquireRange(Bugs[id]), null)
    call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,5,"Target: "+GetUnitName(t))
    if t != null then
        call IssueTargetOrder( Bugs[id], "attack", t )
    endif
   
endfunction

//===========================================================================
function InitTrig_attack takes nothing returns nothing
    set gg_trg_attack = CreateTrigger(  )
    call TriggerRegisterPlayerChatEvent( gg_trg_attack, Player(0), "attack", true )
    call TriggerAddCondition( gg_trg_attack, Condition( function Debug_Mode ) )
    call TriggerAddAction( gg_trg_attack, function Trig_Attack_Actions )
endfunction

 
//TESH.scrollpos=0
//TESH.alwaysfold=0
// =======================================================================
// FOG FADING SYSTEM | v1.3 | by MoCo, please give credit if you use this)
// =======================================================================
library FFS13 initializer Init requires TimerUtils

    globals
        // I recommend tu use 1.0 here for final maps
        private constant real TIME_OF_DAY_SPEED = 1.0 // 10 makes a good timelapse for testing
       
        private constant real SECONDS_PER_HOUR = 20.0 // Only change this, if you also change it in the game constants!
        private constant real START_TIME = 6   // Time at game start
       
        private constant integer FOG_STYLE = 0  // 0 = linear, 1 & 2 are expon. functions
       
        // Fog #1: noon time, 12 p.m.
        private constant real NOON_FOG_START = 1050 // Start distance of fog
        private constant real NOON_FOG_END   = 4000 // End distance of fog
        private constant real NOON_DENSITY = 1.0 // Fog density
        // Color values
        private constant real NOON_RED    = 0.74
        private constant real NOON_GREEN  = 0.83
        private constant real NOON_BLUE   = 0.6
       
        // Fog #2: night time, 24 p.m.
        private constant real NIGHT_FOG_START = 1050 // Start distance of fog
        private constant real NIGHT_FOG_END   = 4000 // End distance of fog
        private constant real NIGHT_DENSITY = 1.0 // Fog density
        // Color values
        private constant real NIGHT_RED   = 0.74
        private constant real NIGHT_GREEN = 0.83
        private constant real NIGHT_BLUE  = 1.0
       
        // ============================================================
        // Don't touch the code below unless you know what you're doing
        // ============================================================
       
        // variables used by the system
        private real fog_density
        private real fog_start
        private real fog_end
        private real fog_red
        private real fog_green
        private real fog_blue
        private real fog_fade_ticks
        private real fog_fade_amount_start
        private real fog_fade_amount_end
        private real fog_fade_amount_density
        private real fog_fade_amount_red  
        private real fog_fade_amount_green
        private real fog_fade_amount_blue
        private real time_dif
       
        private timer FogTimer
    endglobals

private function Timer takes nothing returns nothing
    local real time = GetFloatGameState(GAME_STATE_TIME_OF_DAY)
   
    // between noon and midnight
    if time > 12 and time <= 24 then
        set fog_start = fog_start + fog_fade_amount_start
        set fog_end = fog_end + fog_fade_amount_end
        set fog_density = fog_density + fog_fade_amount_density
       
        set fog_red = fog_red + fog_fade_amount_red
        set fog_green = fog_green + fog_fade_amount_green
        set fog_blue = fog_blue + fog_fade_amount_blue
    // after midnight, before noon
    else
        set fog_start = fog_start - fog_fade_amount_start
        set fog_end = fog_end - fog_fade_amount_end
        set fog_density = fog_density - fog_fade_amount_density
       
        set fog_red = fog_red - fog_fade_amount_red
        set fog_green = fog_green - fog_fade_amount_green
        set fog_blue = fog_blue - fog_fade_amount_blue
    endif
   
    // Apply fog values
    call SetTerrainFogEx(FOG_STYLE, fog_start, fog_end, fog_density, fog_red, fog_green, fog_blue)
   
    // Below is a debug display that shows raw values each update tick
    // call DisplayTextToPlayer(GetLocalPlayer(),0,0, "FOG - start: "+R2S(fog_start)+", end: "+R2S(fog_end)+", dens: "+R2S(fog_density)+", R: "+R2S(fog_red)+", G: "+R2S(fog_green)+", B: "+R2S(fog_blue))
endfunction
   
private function Start takes nothing returns nothing
    // Time of day speed
    call SetTimeOfDayScale(TIME_OF_DAY_SPEED)

    // Set Starting Time
    call SetFloatGameState(GAME_STATE_TIME_OF_DAY, START_TIME )
   
    // Fading is processed every second
    // and we got 12 hours to fade between 2 fog colors
    set fog_fade_ticks = ( 12 * SECONDS_PER_HOUR ) / TIME_OF_DAY_SPEED
   
    // Density amounts to be faded every second
    set fog_fade_amount_start = ( NIGHT_FOG_START - NOON_FOG_START ) / fog_fade_ticks
    set fog_fade_amount_end = ( NIGHT_FOG_END - NOON_FOG_END ) / fog_fade_ticks
    set fog_fade_amount_density = ( NIGHT_DENSITY - NOON_DENSITY ) / fog_fade_ticks
   
    // Color amounts to be faded every second
    set fog_fade_amount_red = ( NIGHT_RED - NOON_RED ) / fog_fade_ticks
    set fog_fade_amount_green = ( NIGHT_GREEN - NOON_GREEN ) / fog_fade_ticks
    set fog_fade_amount_blue = ( NIGHT_BLUE - NOON_BLUE ) / fog_fade_ticks
   
    // Calculate Fog Color for starting time
    // between noon and midnight
    if START_TIME > 12 and START_TIME <= 24 then
        set time_dif = ( ( START_TIME - 12 ) * SECONDS_PER_HOUR ) / TIME_OF_DAY_SPEED
        set fog_start = NOON_FOG_START + fog_fade_amount_start * time_dif
        set fog_end = NOON_FOG_END + fog_fade_amount_end * time_dif
        set fog_density = NOON_DENSITY + fog_fade_amount_density * time_dif
        set fog_red = NOON_RED + fog_fade_amount_red * time_dif
        set fog_green = NOON_GREEN + fog_fade_amount_green * time_dif
        set fog_blue = NOON_BLUE + fog_fade_amount_blue * time_dif
    // after midnight, before noon
    else
        set time_dif = ( START_TIME * SECONDS_PER_HOUR ) / TIME_OF_DAY_SPEED
        set fog_start = NIGHT_FOG_START - fog_fade_amount_start * time_dif
        set fog_end = NIGHT_FOG_END - fog_fade_amount_end * time_dif
        set fog_density = NIGHT_DENSITY - fog_fade_amount_density * time_dif
        set fog_red = NIGHT_RED - fog_fade_amount_red * time_dif
        set fog_green = NIGHT_GREEN - fog_fade_amount_green * time_dif
        set fog_blue = NIGHT_BLUE - fog_fade_amount_blue * time_dif
    endif
   
   // call SetTerrainFogEx(FOG_STYLE, fog_start, fog_red, fog_density, fog_red, fog_green, fog_blue)
   
endfunction

function Start_Fog_Timer takes nothing returns nothing
    call SetTerrainFogEx(FOG_STYLE, fog_start, fog_red, fog_density, fog_red, fog_green, fog_blue)
    set FogTimer = NewTimer()
    call TimerStart(FogTimer, 1, true, function Timer)
endfunction

//===========================================================================
private function Init takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterTimerEvent(t, 0.01, false)
    call TriggerAddAction(t, function Start )
endfunction

endlibrary
//TESH.scrollpos=99
//TESH.alwaysfold=0
// ============================================
//   Fog Fading System
//
//   by MoCo  (moco2k@gmx.de)
//   v 2.1  (2009-12-24)
// ============================================
//
// ABOUT:
//  This system gives you an easy to use way for interpolating between two fogs.
//  A possible scenario is the smooth transition between day and night fog for example.  
//
// CHANGELOG:
//  v2.1:  Compatibility with latest patch 1.24
//  v2.0:  The system now uses structures to declarate fog data.
//         It's changed to a function-based system making it more flexible.
//
// REQUIREMENTS:
//   - vJass / JassHelper / Jass New Gen Editor   (See www.wc3campaigns.net)
//   - TimerUtils library [included]  (credits to Vexorian. See http://www.wc3campaigns.net/showthread.php?t=101322 for more information and possible updates)
//
// INSTALLATION:  
//   Just copy the 'Fog Fading System' and the 'TimerUtils' triggers to your map.
//
// USAGE:  
//   Take a look at the example trigger and check out, how things are done there.
//   The system is build around one core function, that creates the fog-transition:
//
//          function FFS_Change_Fog takes fog NewFog, real fading_duration, real period returns nothing
//
//   Paramters:
//      - NewFog:  the structure instance of the new fog to be applied
//      - FdingDuration is the time, to fully blend over to the new fog
//      - Fading Period describes the smoothness.
//        A value of 1 means, that fading is proccessed every second
//        A value of 0.1 means, that 10 fading ticks are proccessed in one single second (-> very smooth)
//        You may want to use smaller values for smaller duration periods
//
//  Give credit if you use this system!
// ============================================
library FFS requires TimerUtils
   
    // fog structure
    struct fog
        string name
        real start
        real end
        real density
        real red
        real green
        real blue
    endstruct
   
    globals      
        private constant integer FOG_STYLE = 0  // 0 = linear, 1 & 2 are expon. functions
       
        // These variables store the current values of the actual active fog
        private real fog_start = 0
        private real fog_end = 9999
        private real fog_density = 0
        private real fog_red = -1
        private real fog_green = -1
        private real fog_blue = -1
       
        // variables used for calculations
        private integer fog_fade_ticks
        private real fog_fade_amount_start
        private real fog_fade_amount_end
        private real fog_fade_amount_density
        private real fog_fade_amount_red  
        private real fog_fade_amount_green
        private real fog_fade_amount_blue
       
    endglobals
   
private function FFS_Change_Fog_Callback takes nothing returns nothing
    local timer t = GetExpiredTimer()
   
    call SetTimerData(t, GetTimerData(t) - 1 )
   
    set fog_start   = fog_start   - fog_fade_amount_start
    set fog_end     = fog_end     - fog_fade_amount_end
    set fog_density = fog_density - fog_fade_amount_density
    set fog_red     = fog_red     - fog_fade_amount_red
    set fog_green   = fog_green   - fog_fade_amount_green
    set fog_blue    = fog_blue    - fog_fade_amount_blue
   
    call SetTerrainFogEx(FOG_STYLE, fog_start, fog_end, fog_density, fog_red, fog_green, fog_blue)

    if GetTimerData(t) <= 0 then
        call ReleaseTimer(t)
    endif

    // Below is a debug display that shows raw values each update tick
    // call DisplayTextToPlayer(GetLocalPlayer(),0,0, "FOG - start: "+R2S(fog_start)+", end: "+R2S(fog_end)+", dens: "+R2S(fog_density)+", R: "+R2S(fog_red)+", G: "+R2S(fog_green)+", B: "+R2S(fog_blue))
   
    set t = null
endfunction

function FFS_Change_Fog takes fog NewFog, real fading_duration, real period returns nothing
    local timer t
   
    // If no fog active, get color values
    if fog_red == -1 and fog_green == -1 and fog_blue == -1 then
        set fog_red = NewFog.red
        set fog_green = NewFog.green
        set fog_blue = NewFog.blue
    endif  

    // if duration 0 or less: instant change
    if fading_duration <= 0 then
        set fog_start   = NewFog.start  // Though, we need to update the variables
        set fog_end     = NewFog.end              
        set fog_density = NewFog.density
        set fog_red     = NewFog.red
        set fog_green   = NewFog.green
        set fog_blue    = NewFog.blue
       
        call SetTerrainFogEx(FOG_STYLE, fog_start, fog_end, fog_density, fog_red, fog_green, fog_blue)
    else    
        set fog_fade_ticks = R2I( fading_duration / period )
       
        set t = NewTimer()
        call SetTimerData(t, fog_fade_ticks)
         
        // Calculate the color amounts to be faded every tick
        set fog_fade_amount_start   = ( fog_start   - NewFog.start   ) / fog_fade_ticks
        set fog_fade_amount_end     = ( fog_end     - NewFog.end     ) / fog_fade_ticks
        set fog_fade_amount_density = ( fog_density - NewFog.density ) / fog_fade_ticks
        set fog_fade_amount_red     = ( fog_red     - NewFog.red     ) / fog_fade_ticks
        set fog_fade_amount_green   = ( fog_green   - NewFog.green   ) / fog_fade_ticks
        set fog_fade_amount_blue    = ( fog_blue    - NewFog.blue    ) / fog_fade_ticks
       
        call TimerStart(t, period, true, function FFS_Change_Fog_Callback)
    endif
   
    set t = null
endfunction

endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
//==============================================================================
//---DiscipleOfLife's-----------------------------------------------------------

// GCU // GetClosestUnit(s) v1.3.1

//------------------------------------------------------------------------------
//
// This library contains the following functions, each of which return the
// unit that is closest to given coordinates and passes a specified filter:
//
// - GetClosestUnit(x, y, filter)
// - GetClosestUnitAlt(x, y, filter)
// - GetClosestUnitInRange(x, y, radius, filter)
// - GetClosestUnitInGroup(x, y, g)
//
// Included are also the following functions, each of which return a
// group consisting of the units closest to given coordinates that
// pass a specified filter:
//
// - GetClosestUnits(x, y, n, filter)
// - GetClosestUnitsInRange(x, y, radius, n, filter)
// - GetClosestUnitsInGroup(x, y, g, n)
//
// Important:
//
// - flying heights and the height of the ground aren't taken into account,
// only the distance in 2D
//
// - these functions can't be used in the boolexpr's passed to them
//
// - all of the functions in this library go through many units to find the
// closest one, meaning that the functions' performance is highly dependant
// on the amount of units they have to go through
//
//------------------------------------------------------------------------------
library GCU

    globals
        private unit CurrentPick
        private real CenterX
        private real CenterY
        private real CurrentDistance
        private group AnyGroup = CreateGroup()
    endglobals

    private function Enum takes nothing returns nothing
        local unit u = GetEnumUnit()
        local real dx = GetUnitX(u) - CenterX
        local real dy = GetUnitY(u) - CenterY
        local real d = (dx*dx + dy*dy) / 10000.
        if d < CurrentDistance then
            set CurrentDistance = d
            set CurrentPick = u
        endif
        set u = null
    endfunction

    //==========================================================================
    // Finds the unit that is closest to (x, y) from all units on the map that
    // pass the filter and do not have the locust ability.
    //
    function GetClosestUnit takes real x, real y, boolexpr filter returns unit
        local real r = 800.
        loop
            call GroupEnumUnitsInRange(AnyGroup, x, y, r, filter)
            exitwhen FirstOfGroup(AnyGroup) != null
            if r >= 3200. then
                call GroupEnumUnitsInRect(AnyGroup, bj_mapInitialPlayableArea, filter)
                exitwhen true
            endif
            set r = 2.00 * r
        endloop
        set CurrentPick = null
        set CenterX = x
        set CenterY = y
        set CurrentDistance = 100000
        call ForGroup(AnyGroup, function Enum)
        return CurrentPick
    endfunction

    //==========================================================================
    // Does the same as above. Faster when there are no units that pass the
    // filter in a 3200 radius, but at other times slower, and most likely a
    // lot slower. How much faster is somewhat directly proportional to the
    // amount of units that do not pass the filter inside that 3200 radius.
    //
    function GetClosestUnitAlt takes real x, real y, boolexpr filter returns unit
        set CurrentPick = null
        set CenterX = x
        set CenterY = y
        set CurrentDistance = 100000
        call GroupEnumUnitsInRect(AnyGroup, bj_mapInitialPlayableArea, filter)
        call ForGroup(AnyGroup, function Enum)
        return CurrentPick
    endfunction


    //==========================================================================
    // Finds the unit that is closest to (x, y) from all units in the specified
    // radius, that pass the filter and do not have the locust ability.
    //
    function GetClosestUnitInRange takes real x, real y, real radius, boolexpr filter returns unit
        set CurrentPick = null
        set CenterX = x
        set CenterY = y
        set CurrentDistance = radius // 100000
        call GroupEnumUnitsInRange(AnyGroup, x, y, radius, filter)
        call ForGroup(AnyGroup, function Enum)
        return CurrentPick
    endfunction

    //==========================================================================
    // Finds the unit that is closest to (x, y) from whichGroup. Unlike the
    // other versions this one considers locusted units also.
    //
    function GetClosestUnitInGroup takes real x, real y, group whichGroup returns unit
        set CurrentPick = null
        set CenterX = x
        set CenterY = y
        set CurrentDistance = 100000
        call ForGroup(whichGroup, function Enum)
        return CurrentPick
endfunction

    //==========================================================================
    // The following three functions do the same as the preceding ones, with //
    // the exception that they return groups consisting of the n closest //
    // units instead of the closest unit //
    //==========================================================================

    globals
        private group ResultGroup
    endglobals

    function GetClosestUnits takes real x, real y, integer n, boolexpr filter returns group
        call GroupEnumUnitsInRect(AnyGroup, bj_mapInitialPlayableArea, filter)
        set ResultGroup = CreateGroup()
        set CenterX = x
        set CenterY = y
        loop
            exitwhen n == 0
            set CurrentPick = null
            set CurrentDistance = 100000
            call ForGroup(AnyGroup, function Enum)
            exitwhen CurrentPick == null
            call GroupRemoveUnit(AnyGroup, CurrentPick)
            call GroupAddUnit(ResultGroup, CurrentPick)
            set n = n - 1
        endloop
        return ResultGroup
    endfunction

    function GetClosestUnitsInRange takes real x, real y, real radius, integer n, boolexpr filter returns group
        call GroupEnumUnitsInRange(AnyGroup, x, y, radius, filter)
        set ResultGroup = CreateGroup()
        set CenterX = x
        set CenterY = y
        loop
            exitwhen n == 0
            set CurrentPick = null
            set CurrentDistance = 100000
            call ForGroup(AnyGroup, function Enum)
            exitwhen CurrentPick == null
            call GroupRemoveUnit(AnyGroup, CurrentPick)
            call GroupAddUnit(ResultGroup, CurrentPick)
            set n = n - 1
        endloop
        return ResultGroup
    endfunction

    private function AnyGroupAddGroupEnum takes nothing returns nothing
        call GroupAddUnit(AnyGroup, GetEnumUnit())
    endfunction

    function GetClosestUnitsInGroup takes real x, real y, group whichGroup, integer n returns group
        call GroupClear(AnyGroup)
        call ForGroup(whichGroup, function AnyGroupAddGroupEnum)
        set ResultGroup = CreateGroup()
        set CenterX = x
        set CenterY = y
        loop
            exitwhen n == 0
            set CurrentPick = null
            set CurrentDistance = 100000
            call ForGroup(AnyGroup, function Enum)
            exitwhen CurrentPick == null
            call GroupRemoveUnit(AnyGroup, CurrentPick)
            call GroupAddUnit(ResultGroup, CurrentPick)
            set n = n - 1
        endloop
        return ResultGroup
    endfunction

endlibrary // End of GetClosestUnit
//==============================================================================a
 
//TESH.scrollpos=0
//TESH.alwaysfold=0
library TimerUtils initializer init
//*********************************************************************
//* TimerUtils (red+blue+orange flavors for 1.24b+)
//* ----------
//*
//*  To implement it , create a custom text trigger called TimerUtils
//* and paste the contents of this script there.
//*
//*  To copy from a map to another, copy the trigger holding this
//* library to your map.
//*
//* (requires vJass)   More scripts: htt://www.wc3c.net
//*
//* For your timer needs:
//*  * Attaching
//*  * Recycling (with double-free protection)
//*
//* set t=NewTimer()      : Get a timer (alternative to CreateTimer)
//* ReleaseTimer(t)       : Relese a timer (alt to DestroyTimer)
//* SetTimerData(t,2)     : Attach value 2 to timer
//* GetTimerData(t)       : Get the timer's value.
//*                         You can assume a timer's value is 0
//*                         after NewTimer.
//*
//* Multi-flavor:
//*    Set USE_HASH_TABLE to true if you don't want to complicate your life.
//*
//* If you like speed and giberish try learning about the other flavors.
//*
//********************************************************************

//================================================================
    globals
        //How to tweak timer utils:
        // USE_HASH_TABLE = true  (new blue)
        //  * SAFEST
        //  * SLOWEST (though hash tables are kind of fast)
        //
        // USE_HASH_TABLE = false, USE_FLEXIBLE_OFFSET = true  (orange)
        //  * kinda safe (except there is a limit in the number of timers)
        //  * ALMOST FAST
        //
        // USE_HASH_TABLE = false, USE_FLEXIBLE_OFFSET = false (red)
        //  * THE FASTEST (though is only  faster than the previous method
        //                  after using the optimizer on the map)
        //  * THE LEAST SAFE ( you may have to tweak OFSSET manually for it to
        //                     work)
        //
        private constant boolean USE_HASH_TABLE      = true
        private constant boolean USE_FLEXIBLE_OFFSET = false

        private constant integer OFFSET     = 0x100000
        private          integer VOFFSET    = OFFSET
             
        //Timers to preload at map init:
        private constant integer QUANTITY   = 256
       
        //Changing this  to something big will allow you to keep recycling
        // timers even when there are already AN INCREDIBLE AMOUNT of timers in
        // the stack. But it will make things far slower so that's probably a bad idea...
        private constant integer ARRAY_SIZE = 8190

    endglobals

    //==================================================================================================
    globals
        private integer array data[ARRAY_SIZE]
        private hashtable     ht
    endglobals

    //It is dependent on jasshelper's recent inlining optimization in order to perform correctly.
    function SetTimerData takes timer t, integer value returns nothing
        static if (USE_HASH_TABLE) then
            // new blue
            call SaveInteger(ht,0,GetHandleId(t), value)
           
        elseif (USE_FLEXIBLE_OFFSET) then
            // orange
            static if (DEBUG_MODE) then
                if (GetHandleId(t)-VOFFSET<0) then
                    call BJDebugMsg("SetTimerData: Wrong handle id, only use SetTimerData on timers created by NewTimer")
                endif
            endif
            set data[GetHandleId(t)-VOFFSET]=value
        else
            // new red
            static if (DEBUG_MODE) then
                if (GetHandleId(t)-OFFSET<0) then
                    call BJDebugMsg("SetTimerData: Wrong handle id, only use SetTimerData on timers created by NewTimer")
                endif
            endif
            set data[GetHandleId(t)-OFFSET]=value
        endif        
    endfunction

    function GetTimerData takes timer t returns integer
        static if(USE_HASH_TABLE) then
            // new blue
            return LoadInteger(ht,0,GetHandleId(t) )
           
        elseif (USE_FLEXIBLE_OFFSET) then
            // orange
            static if (DEBUG_MODE) then
                if(GetHandleId(t)-VOFFSET<0) then
                    call BJDebugMsg("SetTimerData: Wrong handle id, only use SetTimerData on timers created by NewTimer")
                endif
            endif
            return data[GetHandleId(t)-VOFFSET]
        else
            // new red
            static if (DEBUG_MODE) then
                if(GetHandleId(t)-OFFSET<0) then
                    call BJDebugMsg("SetTimerData: Wrong handle id, only use SetTimerData on timers created by NewTimer")
                endif
            endif
            return data[GetHandleId(t)-OFFSET]
        endif        
    endfunction

    //==========================================================================================
    globals
        private timer array tT[ARRAY_SIZE]
        private integer tN = 0
        private constant integer HELD=0x28829022
        //use a totally random number here, the more improbable someone uses it, the better.
    endglobals

    //==========================================================================================
    function NewTimer takes nothing returns timer
        if (tN==0) then
            //If this happens then the QUANTITY rule has already been broken, try to fix the
            // issue, else fail.
            debug call BJDebugMsg("NewTimer: Warning, Exceeding TimerUtils_QUANTITY, make sure all timers are getting recycled correctly")
            static if( not USE_HASH_TABLE) then
                debug call BJDebugMsg("In case of errors, please increase it accordingly, or set TimerUtils_USE_HASH_TABLE to true")
                set tT[0]=CreateTimer()
                static if( USE_FLEXIBLE_OFFSET) then
                    if (GetHandleId(tT[0])-VOFFSET<0) or (GetHandleId(tT[0])-VOFFSET>=ARRAY_SIZE) then
                        //all right, couldn't fix it
                        call BJDebugMsg("NewTimer: Unable to allocate a timer, you should probably set TimerUtils_USE_HASH_TABLE to true or fix timer leaks.")
                        return null
                    endif
                else
                    if (GetHandleId(tT[0])-OFFSET<0) or (GetHandleId(tT[0])-OFFSET>=ARRAY_SIZE) then
                        //all right, couldn't fix it
                        call BJDebugMsg("NewTimer: Unable to allocate a timer, you should probably set TimerUtils_USE_HASH_TABLE to true or fix timer leaks.")
                        return null
                    endif
                endif
            endif
        else
            set tN=tN-1
        endif
        call SetTimerData(tT[tN],0)
     return tT[tN]
    endfunction

    //==========================================================================================
    function ReleaseTimer takes timer t returns nothing
        if(t==null) then
            debug call BJDebugMsg("Warning: attempt to release a null timer")
            return
        endif
        if (tN==ARRAY_SIZE) then
            debug call BJDebugMsg("Warning: Timer stack is full, destroying timer!!")

            //stack is full, the map already has much more troubles than the chance of bug
            call DestroyTimer(t)
        else
            call PauseTimer(t)
            if(GetTimerData(t)==HELD) then
                debug call BJDebugMsg("Warning: ReleaseTimer: Double free!")
                return
            endif
            call SetTimerData(t,HELD)
            set tT[tN]=t
            set tN=tN+1
        endif    
    endfunction

    private function init takes nothing returns nothing
     local integer i=0
     local integer o=-1
     local boolean oops = false
     
        static if( USE_HASH_TABLE ) then
            set ht = InitHashtable()
            loop
                exitwhen(i==QUANTITY)
                set tT[i]=CreateTimer()
                call SetTimerData(tT[i], HELD)
                set i=i+1
            endloop
            set tN = QUANTITY
        else
            loop
                set i=0
                loop
                    exitwhen (i==QUANTITY)
                    set tT[i] = CreateTimer()
                    if(i==0) then
                        set VOFFSET = GetHandleId(tT[i])
                        static if(USE_FLEXIBLE_OFFSET) then
                            set o=VOFFSET
                        else
                            set o=OFFSET
                        endif
                    endif
                    if (GetHandleId(tT[i])-o>=ARRAY_SIZE) then
                        exitwhen true
                    endif
                    if (GetHandleId(tT[i])-o>=0)  then
                        set i=i+1
                    endif
                endloop
                set tN = i
                exitwhen(tN == QUANTITY)
                set oops = true
                exitwhen not USE_FLEXIBLE_OFFSET
                debug call BJDebugMsg("TimerUtils_init: Failed a initialization attempt, will try again")              
            endloop
           
            if(oops) then
                static if ( USE_FLEXIBLE_OFFSET) then
                    debug call BJDebugMsg("The problem has been fixed.")
                    //If this message doesn't appear then there is so much
                    //handle id fragmentation that it was impossible to preload
                    //so many timers and the thread crashed! Therefore this
                    //debug message is useful.
                elseif(DEBUG_MODE) then
                    call BJDebugMsg("There were problems and the new timer limit is "+I2S(i))
                    call BJDebugMsg("This is a rare ocurrence, if the timer limit is too low:")
                    call BJDebugMsg("a) Change USE_FLEXIBLE_OFFSET to true (reduces performance a little)")
                    call BJDebugMsg("b) or try changing OFFSET to "+I2S(VOFFSET) )
                endif
            endif
        endif

    endfunction

endlibrary