//===========================================================================
// 
// |cff540081Crab Slide
// 
//   Warcraft III map script
//   Generated by the Warcraft III World Editor
//   Date: Sat Jul 21 02:30:48 2012
//   Map Author: Inconnu
// 
//===========================================================================

//***************************************************************************
//*
//*  Global Variables
//*
//***************************************************************************

globals
    // User-defined
    boolean array           udg_has_max_name
    boolean                 udg_tripleKillSoundOn      = false
    gamecache               udg_cheatCache             = null
    integer array           udg_used_terrain_types
    integer                 udg_nb_used_terrains       = 0
    boolean                 udg_cheatsUsed             = false
    boolean                 udg_areRedRightsOn         = false
    boolean array           udg_is_circleing_j
    real array              udg_loc_x
    real array              udg_loc_y
    unit array              udg_hero_j
    integer                 udg_terrain_slide          = 0
    handle                  udg_handle                 = null
    real                    udg_x                      = 0

    // Generated
    rect                    gg_rct_departLvl_0         = null
    sound                   gg_snd_noob                = null
    sound                   gg_snd_multisquish         = null
    sound                   gg_snd_questCompleted      = null
    sound                   gg_snd_questFailed         = null
    sound                   gg_snd_goodJob             = null
    sound                   gg_snd_warning             = null
    sound                   gg_snd_start               = null
    trigger                 gg_trg_Constants           = null
    trigger                 gg_trg_Text                = null
    trigger                 gg_trg_Init_terrain_limit_variables = null
    trigger                 gg_trg_Init_colorCodes     = null
    trigger                 gg_trg_Basic_functions     = null
    trigger                 gg_trg_Functions_on_numbers = null
    trigger                 gg_trg_Ascii               = null
    trigger                 gg_trg_Decode_string       = null
    trigger                 gg_trg_View_all_hide_all   = null
    trigger                 gg_trg_Immolation_skills   = null
    trigger                 gg_trg_MonsterType         = null
    trigger                 gg_trg_MonsterTypeArray    = null
    trigger                 gg_trg_Monster_creation_functions = null
    trigger                 gg_trg_Monster             = null
    trigger                 gg_trg____trig_Monsters_clickable_set_life = null
    trigger                 gg_trg_MonsterNoMove       = null
    trigger                 gg_trg_MonsterNoMoveArray  = null
    trigger                 gg_trg_MonsterSimplePatrol = null
    trigger                 gg_trg_MonsterSimplePatrolArray = null
    trigger                 gg_trg_MonsterMultiplePatrols = null
    trigger                 gg_trg_MonsterMultiplePatrolsArray = null
    trigger                 gg_trg_MonsterSpawn        = null
    trigger                 gg_trg_MonsterSpawnArray   = null
    trigger                 gg_trg_Terrain_type_functions = null
    trigger                 gg_trg_TerrainType         = null
    trigger                 gg_trg_TerrainTypeWalk     = null
    trigger                 gg_trg_TerrainTypeDeath_functions = null
    trigger                 gg_trg_TerrainTypeDeath_KillingTimers = null
    trigger                 gg_trg_TerrainTypeDeath    = null
    trigger                 gg_trg_TerrainTypeSlide    = null
    trigger                 gg_trg_TerrainTypeArray    = null
    trigger                 gg_trg_Time_of_game_trigger = null
    trigger                 gg_trg_Lives_and_game_time = null
    trigger                 gg_trg_Meteor              = null
    trigger                 gg_trg_MeteorArray         = null
    trigger                 gg_trg_Meteor_functions    = null
    trigger                 gg_trg_Right_click_on_widget = null
    trigger                 gg_trg_Meteor_being_used   = null
    trigger                 gg_trg_Stop_using_normal_meteor = null
    trigger                 gg_trg_Effect_meteor_on_pick_up = null
    trigger                 gg_trg_VisibilityModifier  = null
    trigger                 gg_trg_VisibilityModifierArray = null
    trigger                 gg_trg_StartAndEnd         = null
    trigger                 gg_trg_Triggers            = null
    trigger                 gg_trg_Level               = null
    trigger                 gg_trg____Level_functions  = null
    trigger                 gg_trg____Trig_checkpoint_revive_heroes = null
    trigger                 gg_trg_LevelArray          = null
    trigger                 gg_trg_EscaperEffect_functions = null
    trigger                 gg_trg_EscaperEffect       = null
    trigger                 gg_trg_EscaperEffectArray  = null
    trigger                 gg_trg_Escaper_functions   = null
    trigger                 gg_trg_Escaper_disco       = null
    trigger                 gg_trg_Escaper             = null
    trigger                 gg_trg_EscaperArray        = null
    trigger                 gg_trg_EscaperSavedCommands = null
    trigger                 gg_trg_Make                = null
    trigger                 gg_trg_Monster_making_no_move_Actions = null
    trigger                 gg_trg_MakeMonsterNoMove   = null
    trigger                 gg_trg_Monster_making_simple_patrol_Actions = null
    trigger                 gg_trg_MakeMonsterSimplePatrol = null
    trigger                 gg_trg_Monster_making_multiple_patrols_Actions = null
    trigger                 gg_trg_MakeMonsterMultiplePatrols = null
    trigger                 gg_trg_Monster_spawn_making_Actions = null
    trigger                 gg_trg_MakeMonsterSpawn    = null
    trigger                 gg_trg_Monster_delete_Actions = null
    trigger                 gg_trg_MakeDeleteMonsters  = null
    trigger                 gg_trg_Meteor_making_Actions = null
    trigger                 gg_trg_MakeMeteor          = null
    trigger                 gg_trg_Meteor_delete_Actions = null
    trigger                 gg_trg_MakeDeleteMeteors   = null
    trigger                 gg_trg_Terrain_making_Actions = null
    trigger                 gg_trg_MakeTerrainCreate   = null
    trigger                 gg_trg_Terrain_copy_paste_Actions = null
    trigger                 gg_trg_MakeTerrainCopyPaste = null
    trigger                 gg_trg_Terrain_vertical_symmetry_Actions = null
    trigger                 gg_trg_MakeTerrainVerticalSymmetry = null
    trigger                 gg_trg_Terrain_horizontal_symmetry_Actions = null
    trigger                 gg_trg_MakeTerrainHorizontalSymmetry = null
    trigger                 gg_trg_Make_exchange_terrains_Actions = null
    trigger                 gg_trg_MakeExchangeTerrains = null
    trigger                 gg_trg_Start_making_Actions = null
    trigger                 gg_trg_MakeStart           = null
    trigger                 gg_trg_End_making_Actions  = null
    trigger                 gg_trg_MakeEnd             = null
    trigger                 gg_trg_VisibilityModifier_making_Actions = null
    trigger                 gg_trg_MakeVisibilityModifier = null
    trigger                 gg_trg_Getting_terrain_type_info_Actions = null
    trigger                 gg_trg_MakeGetTerrainType  = null
    trigger                 gg_trg_MakeAction          = null
    trigger                 gg_trg_MakeMonsterAction   = null
    trigger                 gg_trg_MakeDeleteMonstersAction = null
    trigger                 gg_trg_MakeMeteorAction    = null
    trigger                 gg_trg_MakeDeleteMeteorsAction = null
    trigger                 gg_trg_MakeTerrainCreateAction = null
    trigger                 gg_trg_MakeTerrainCopyPasteAction = null
    trigger                 gg_trg_MakeTerrainVerticalSymmetryAction = null
    trigger                 gg_trg_MakeTerrainHorizontalSymmetryAction = null
    trigger                 gg_trg_MakeVisibilityModifierAction = null
    trigger                 gg_trg_MakeLastActions     = null
    trigger                 gg_trg_Command_functions   = null
    trigger                 gg_trg_Teleport_once_only  = null
    trigger                 gg_trg_Teleport            = null
    trigger                 gg_trg_Autorevive          = null
    trigger                 gg_trg_Command_all         = null
    trigger                 gg_trg_Command_red         = null
    trigger                 gg_trg_Command_cheat       = null
    trigger                 gg_trg_Command_make        = null
    trigger                 gg_trg_Command_max         = null
    trigger                 gg_trg_Command_true_max    = null
    trigger                 gg_trg_Command_execution   = null
    trigger                 gg_trg_Slide               = null
    trigger                 gg_trg_CheckTerrain        = null
    trigger                 gg_trg_All_terrain_functions = null
    trigger                 gg_trg_Terrain_type_ascii_conversion = null
    trigger                 gg_trg_Terrain_type_max    = null
    trigger                 gg_trg_Terrain_type_grass  = null
    trigger                 gg_trg_Terrain_type_names_and_data = null
    trigger                 gg_trg_Terrain_functions   = null
    trigger                 gg_trg_Terrain_data_search = null
    trigger                 gg_trg_Terrain_type_from_string = null
    trigger                 gg_trg_Modify_terrain_functions = null
    trigger                 gg_trg_Terrain_modifying   = null
    trigger                 gg_trg_Change_one_terrain  = null
    trigger                 gg_trg_Change_all_terrains = null
    trigger                 gg_trg_Exchange_terrains   = null
    trigger                 gg_trg_Randomize_terrains  = null
    trigger                 gg_trg_Reinit_terrains     = null
    trigger                 gg_trg_Reinit_terrains_position_Change_variations_and_ut_at_beginning = null
    trigger                 gg_trg_Save_load_terrain_without_name = null
    trigger                 gg_trg_Save_load_terrain_with_name = null
    trigger                 gg_trg_struct_StringArrayForCache = null
    trigger                 gg_trg_Save_terrain_config = null
    trigger                 gg_trg_Save_terrain        = null
    trigger                 gg_trg_Save_monster_types  = null
    trigger                 gg_trg_Save_levels         = null
    trigger                 gg_trg_SAVE_MAP_in_cache   = null
    trigger                 gg_trg_Init_lives          = null
    trigger                 gg_trg_Init_escapers       = null
    trigger                 gg_trg_Init_terrain_types  = null
    trigger                 gg_trg_Init_monster_types  = null
    trigger                 gg_trg_Init_struct_levels  = null
    trigger                 gg_trg_Init_levels         = null
    trigger                 gg_trg_Forces_ally         = null
    trigger                 gg_trg_Camera              = null
    trigger                 gg_trg_No_selection_circle = null
    trigger                 gg_trg_Welcome_message     = null
    trigger                 gg_trg_Allways_day         = null
    trigger                 gg_trg_Start_sound         = null
    trigger                 gg_trg_Heroes              = null
    trigger                 gg_trg_Heroes_for_test     = null
    trigger                 gg_trg_Has_max_name        = null
    trigger                 gg_trg_Ajout_evenement_kan_plein_joueurs = null
    trigger                 gg_trg_Prouve_is_real_max1 = null
    trigger                 gg_trg_Prouve_is_real_max2 = null
    trigger                 gg_trg_Command_shortcuts_functions = null
    trigger                 gg_trg_Using_shortcut      = null
    trigger                 gg_trg_Commands_1          = null
    trigger                 gg_trg_Commands_2          = null
    trigger                 gg_trg_Colors              = null
    trigger                 gg_trg_Effects             = null
    trigger                 gg_trg_Red_commands        = null
    trigger                 gg_trg_Map_description     = null
    trigger                 gg_trg_Contact             = null
    trigger                 gg_trg_Command_shortcuts   = null
    trigger                 gg_trg_Adding_quests       = null
    trigger                 gg_trg_Camera_reset        = null
    trigger                 gg_trg_Apm                 = null
    trigger                 gg_trg_To_turn_to_point    = null
    trigger                 gg_trg_To_turn_to_widget   = null
    trigger                 gg_trg_Auto_continue_after_sliding = null
    trigger                 gg_trg_Afk_mode_init       = null
    trigger                 gg_trg_Afk_mode_ordre_recu = null
    trigger                 gg_trg_A_player_leaves     = null
    trigger                 gg_trg_Antisave            = null
    trigger                 gg_trg_Antisave_warning    = null
    trigger                 gg_trg_InvisUnit_is_getting_damage = null
    trigger                 gg_trg_A_hero_dies_check_if_all_dead_and_sounds = null
    trigger                 gg_trg_Lose_a_life_and_res = null
    trigger                 gg_trg_Sound_monster_dies  = null
endglobals

function InitGlobals takes nothing returns nothing
    local integer i = 0
    set i = 0
    loop
        exitwhen (i > 12)
        set udg_has_max_name[i] = false
        set i = i + 1
    endloop

    set udg_tripleKillSoundOn = true
    set i = 0
    loop
        exitwhen (i > 20)
        set udg_used_terrain_types[i] = 0
        set i = i + 1
    endloop

    set udg_nb_used_terrains = 0
    set udg_cheatsUsed = false
    set udg_areRedRightsOn = true
    set i = 0
    loop
        exitwhen (i > 1)
        set udg_is_circleing_j[i] = false
        set i = i + 1
    endloop

    set i = 0
    loop
        exitwhen (i > 1)
        set udg_loc_x[i] = 0
        set i = i + 1
    endloop

    set i = 0
    loop
        exitwhen (i > 1)
        set udg_loc_y[i] = 0
        set i = i + 1
    endloop

    set udg_terrain_slide = 0
    set udg_x = 0
endfunction

//***************************************************************************
//*
//*  Sounds
//*
//***************************************************************************

function InitSounds takes nothing returns nothing
    set gg_snd_noob = CreateSound( "war3mapImported\\Noob.wav", false, false, false, 10, 10, "DefaultEAXON" )
    call SetSoundDuration( gg_snd_noob, 1022 )
    call SetSoundChannel( gg_snd_noob, 0 )
    call SetSoundVolume( gg_snd_noob, 127 )
    call SetSoundPitch( gg_snd_noob, 1.0 )
    set gg_snd_multisquish = CreateSound( "war3mapImported\\triple_kill.wav", false, false, false, 10, 10, "DefaultEAXON" )
    call SetSoundDuration( gg_snd_multisquish, 1828 )
    call SetSoundChannel( gg_snd_multisquish, 0 )
    call SetSoundVolume( gg_snd_multisquish, 127 )
    call SetSoundPitch( gg_snd_multisquish, 1.0 )
    set gg_snd_questCompleted = CreateSound( "Sound\\Interface\\QuestCompleted.wav", false, false, false, 10, 10, "DefaultEAXON" )
    call SetSoundParamsFromLabel( gg_snd_questCompleted, "QuestCompleted" )
    call SetSoundDuration( gg_snd_questCompleted, 5155 )
    set gg_snd_questFailed = CreateSound( "Sound\\Interface\\QuestFailed.wav", false, false, false, 10, 10, "DefaultEAXON" )
    call SetSoundParamsFromLabel( gg_snd_questFailed, "QuestFailed" )
    call SetSoundDuration( gg_snd_questFailed, 4690 )
    set gg_snd_goodJob = CreateSound( "Sound\\Interface\\GoodJob.wav", false, false, false, 10, 10, "DefaultEAXON" )
    call SetSoundParamsFromLabel( gg_snd_goodJob, "GoodJob" )
    call SetSoundDuration( gg_snd_goodJob, 2548 )
    set gg_snd_warning = CreateSound( "Sound\\Interface\\Warning.wav", false, false, false, 10, 10, "DefaultEAXON" )
    call SetSoundParamsFromLabel( gg_snd_warning, "Warning" )
    call SetSoundDuration( gg_snd_warning, 1904 )
    set gg_snd_start = CreateSound( "Sound\\Interface\\NewTournament.wav", false, false, false, 10, 10, "DefaultEAXON" )
    call SetSoundParamsFromLabel( gg_snd_start, "NewTournament" )
    call SetSoundDuration( gg_snd_start, 7988 )
endfunction

//***************************************************************************
//*
//*  Regions
//*
//***************************************************************************

function CreateRegions takes nothing returns nothing
    local weathereffect we

    set gg_rct_departLvl_0 = Rect( -10784.0, 9888.0, -10112.0, 10688.0 )
endfunction

//***************************************************************************
//*
//*  Custom Script Code
//*
//***************************************************************************
//TESH.scrollpos=0
//TESH.alwaysfold=0

//***************************************************************************
//*
//*  Triggers
//*
//***************************************************************************

//===========================================================================
// Trigger: Constants
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
globals
    real MAP_MIN_X
    real MAP_MAX_X
    real MAP_MIN_Y
    real MAP_MAX_Y

	constant integer INVIS_UNIT_TYPE_ID = 'Einv' 
    constant integer HERO_TYPE_ID = 'E000'
    
	constant integer HERO_WALK_SPEED = 522
    
    constant real MAX_MOVE_SPEED = 522
    
    
    constant integer DEFAULT_MONSTER_SPEED = 400
    
	constant real HERO_SLIDE_SPEED = 550
	constant real SLIDE_PERIOD = 0.015
	constant real CHECK_TERRAIN_PERIOD = 0.05
    constant real LOW_PERIOD_FOR_WORK = 0.0001
    
    
    constant integer CRITICAL_LIVES_LIMIT = 2 //s'il y a au plus ce nombre de vies, on affiche les vies en rouge
    
    constant integer DEFAULT_CAMERA_FIELD = 2500
    
    
    constant integer LIMIT_NB_HERO_EFFECTS = 20
    
    
    constant integer PATROL_DISTANCE_MIN = 100
    
    
    constant integer MAX_NB_MONSTERS_BY_LEVEL = 1000
    
    
    constant real LARGEUR_CASE = 128
    
    
    constant real TERRAIN_DEATH_TIME_TO_KILL = 2
    
    
	constant player ENNEMY_PLAYER = Player(PLAYER_NEUTRAL_AGGRESSIVE)
	constant player NEUTRAL_PLAYER = Player(PLAYER_NEUTRAL_PASSIVE)
    
    
    constant player PLAYER_INVIS_UNIT = Player(12)
    
    
    constant string GM_TOUCH_DEATH_TERRAIN_EFFECT_STR = "Abilities\\Spells\\NightElf\\Blink\\BlinkCaster.mdl"
    constant string GM_KILLING_EFFECT = "Abilities\\Spells\\NightElf\\Blink\\BlinkCaster.mdl"
    constant string TERRAIN_KILL_EFFECT_BODY_PART = "origin"
    
    constant integer NB_MAX_OF_TERRAINS = 16
    constant real TERRAIN_DATA_DISPLAY_TIME = 15
    constant integer NB_MAX_TERRAIN_DATA_DISPLAY = 16
    constant integer NB_MAX_TILES_MODIFIED = 1000
    
    constant integer NB_LIVES_AT_BEGINNING = 5
    
    constant integer RED = 0
    constant integer BLUE = 1
    constant integer TEAL = 2
    constant integer PURPLE = 3
    constant integer YELLOW = 4
    constant integer ORANGE = 5
    constant integer GREEN = 6
    constant integer PINK = 7
    constant integer GREY = 8
    constant integer LIGHTBLUE = 9
    constant integer DARKGREEN = 10
    constant integer BROWN = 11
endglobals
	
	
	
    
//===========================================================================
function InitTrig_Constants takes nothing returns nothing
endfunction//===========================================================================
// Trigger: Text
//
// 58 lignes
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library Text



globals
    private constant string NORMAL_TEXT_COLORCODE = "|c00ffffff" //blanc
    private constant string MAKE_TEXT_COLORCODE = "|c00ffff00" //jaune
    private constant string ERROR_TEXT_COLORCODE = "|c00960000" //sorte de rouge foncé
    
    public boolean enabled = true
    public real posX = 0
    public real posY = 0.4
endglobals


private function ForPlayer_timed_withColorCode takes player p, real duration, string colorcode, string message returns boolean
    if (not enabled) then
        return false
    endif
    if (duration >= 0.) then
        call DisplayTimedTextToPlayer(p, posX, posY, duration, colorcode + message)
    else
        call DisplayTextToPlayer(p, posX, posY, colorcode + message)
    endif
    
    return true
endfunction
    
private function ForAll_timed_withColorCode takes real duration, string colorcode, string message returns boolean
    local integer i 
    if (not enabled) then
        return false
    endif
    set i = 0
    loop
        exitwhen (i > 11)
            call ForPlayer_timed_withColorCode(Player(i), duration, colorcode, message)
        set i = i + 1
    endloop
    
    return true
endfunction


public function P_timed takes player p, real duration, string message returns boolean
    return ForPlayer_timed_withColorCode(p, duration, NORMAL_TEXT_COLORCODE, message)
endfunction

public function P takes player p, string message returns boolean
    return ForPlayer_timed_withColorCode(p, -1., NORMAL_TEXT_COLORCODE, message)
endfunction

public function erP_timed takes player p, real duration, string message returns boolean
    return ForPlayer_timed_withColorCode(p, duration, ERROR_TEXT_COLORCODE, message)
endfunction

public function erP takes player p, string message returns boolean
    return ForPlayer_timed_withColorCode(p, -1., ERROR_TEXT_COLORCODE, message)
endfunction

public function mkP_timed takes player p, real duration, string message returns boolean
    return ForPlayer_timed_withColorCode(p, duration, MAKE_TEXT_COLORCODE, message)
endfunction

public function mkP takes player p, string message returns boolean
    return ForPlayer_timed_withColorCode(p, -1., MAKE_TEXT_COLORCODE, message)
endfunction


public function A_timed takes real duration, string message returns boolean
    return ForAll_timed_withColorCode(duration, NORMAL_TEXT_COLORCODE, message)
endfunction

public function A takes string message returns boolean
    return ForAll_timed_withColorCode(-1., NORMAL_TEXT_COLORCODE, message)
endfunction

public function erA_timed takes real duration, string message returns boolean
    return ForAll_timed_withColorCode(duration, ERROR_TEXT_COLORCODE, message)
endfunction

public function erA takes string message returns boolean
    return ForAll_timed_withColorCode(-1., ERROR_TEXT_COLORCODE, message)
endfunction

public function mkA_timed takes real duration, string message returns boolean
    return ForAll_timed_withColorCode(duration, MAKE_TEXT_COLORCODE, message)
endfunction

public function mkA takes string message returns boolean
    return ForAll_timed_withColorCode(-1., MAKE_TEXT_COLORCODE, message)
endfunction




function DisplayLineToPlayer takes player p returns nothing
    call Text_P(p, " ")
endfunction



endlibrary



//===========================================================================
function InitTrig_Text takes nothing returns nothing
endfunction



//===========================================================================
// Trigger: Init terrain limit variables
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
function InitTrig_Init_terrain_limit_variables takes nothing returns nothing
    set MAP_MIN_X = GetRectMinX(GetWorldBounds())
    set MAP_MAX_X = GetRectMaxX(GetWorldBounds())
    set MAP_MIN_Y = GetRectMinY(GetWorldBounds())
    set MAP_MAX_Y = GetRectMaxY(GetWorldBounds())
endfunction

//===========================================================================
// Trigger: Init colorCodes
//===========================================================================
//TESH.scrollpos=10
//TESH.alwaysfold=0
globals
    string array udg_colorCode
    string array udg_baseColorString
    string COLOR_TERRAIN_SLIDE 
    string COLOR_TERRAIN_WALK
    string COLOR_TERRAIN_DEATH
endglobals



function Trig_init_colorCodes_Actions takes nothing returns nothing

    set udg_colorCode[ 0 ] = "|cffff0303" //red
    set udg_colorCode[ 1 ] = "|cff0042ff" //blue
    set udg_colorCode[ 2 ] = "|cff1ce6b9" //teal
    set udg_colorCode[ 3 ] = "|cff540081" //purple
    set udg_colorCode[ 4 ] = "|cfffffc01" //yellow
    set udg_colorCode[ 5 ] = "|cfffeba0e" //orange
    set udg_colorCode[ 6 ] = "|cff20c000" //green
    set udg_colorCode[ 7 ] = "|cffe55bb0" //pink
    set udg_colorCode[ 8 ] = "|cff959697" //grey
    set udg_colorCode[ 9 ] = "|cff7ebff1" //lightblue
    set udg_colorCode[10 ] = "|cff106246" //darkgreen
    set udg_colorCode[11 ] = "|cFF4A2800" //brown
    set udg_colorCode[12 ] = "|c33333333" //black

    set udg_baseColorString[ 0 ] = udg_colorCode[ 0 ] + "red"
    set udg_baseColorString[ 1 ] = udg_colorCode[ 1 ] + "blue"
    set udg_baseColorString[ 2 ] = udg_colorCode[ 2 ] + "teal"
    set udg_baseColorString[ 3 ] = udg_colorCode[ 3 ] + "purple"
    set udg_baseColorString[ 4 ] = udg_colorCode[ 4 ] + "yellow"
    set udg_baseColorString[ 5 ] = udg_colorCode[ 5 ] + "orange"
    set udg_baseColorString[ 6 ] = udg_colorCode[ 6 ] + "green"
    set udg_baseColorString[ 7 ] = udg_colorCode[ 7 ] + "pink"
    set udg_baseColorString[ 8 ] = udg_colorCode[ 8 ] + "grey"
    set udg_baseColorString[ 9 ] = udg_colorCode[ 9 ] + "lightblue"
    set udg_baseColorString[10 ] = udg_colorCode[10 ] + "darkgreen"
    set udg_baseColorString[11 ] = udg_colorCode[11 ] + "brown"
    set udg_baseColorString[12 ] = udg_colorCode[12 ] + "black"
    
    set COLOR_TERRAIN_SLIDE = udg_colorCode[TEAL]
    set COLOR_TERRAIN_WALK = udg_colorCode[GREEN]
    set COLOR_TERRAIN_DEATH = udg_colorCode[ORANGE]

endfunction

//===========================================================================
function InitTrig_Init_colorCodes takes nothing returns nothing
    set gg_trg_Init_colorCodes = CreateTrigger(  )
    call TriggerAddAction( gg_trg_Init_colorCodes, function Trig_init_colorCodes_Actions )
endfunction

//===========================================================================
// Trigger: Basic functions
//===========================================================================
//TESH.scrollpos=113
//TESH.alwaysfold=0
library BasicFunctions needs Text


globals
    integer udg_currentMonsterPlayerId = 0
endglobals



function IsUnitBetweenLocs takes unit u, real x1, real y1, real x2, real y2 returns boolean
	local real minX = RMinBJ(x1, x2)
	local real maxX = RMaxBJ(x1, x2)
	local real minY = RMinBJ(y1, y2)
	local real maxY = RMaxBJ(y1, y2)
	
	local real x = GetUnitX(u)
	local real y = GetUnitY(u)
	
	return ((minX < x and maxX > x) and (minY < y and maxY > y))
endfunction

function IsItemBetweenLocs takes item i, real x1, real y1, real x2, real y2 returns boolean
	local real minX = RMinBJ(x1, x2)
	local real maxX = RMaxBJ(x1, x2)
	local real minY = RMinBJ(y1, y2)
	local real maxY = RMaxBJ(y1, y2)
	
	local real x = GetItemX(i)
	local real y = GetItemY(i)
	
	return ((minX < x and maxX > x) and (minY < y and maxY > y))
endfunction


function IsPlayerInGame takes player p returns boolean
    return (GetPlayerController(p) == MAP_CONTROL_USER and GetPlayerSlotState(p) == PLAYER_SLOT_STATE_PLAYING)
endfunction


function SpecialIllidan takes unit hero returns nothing
    call SetUnitAnimation(hero, "Morph Alternate")
endfunction


function IsIssuedOrder takes string orderString returns boolean
    return (GetIssuedOrderId() == OrderId(orderString))
endfunction

function IsLastOrderPause takes nothing returns boolean
    return GetIssuedOrderId() == 851973
endfunction

function GetLocDist takes real x1, real y1, real x2, real y2 returns real
    local real diffX = x2 - x1
    local real diffY = y2 - y1
    return SquareRoot(diffX * diffX + diffY * diffY)
endfunction


function GetCurrentMonsterPlayer takes nothing returns player
    if (udg_currentMonsterPlayerId >= 11) then
        set udg_currentMonsterPlayerId = 0
    else
        set udg_currentMonsterPlayerId = udg_currentMonsterPlayerId + 1
    endif
    return Player(udg_currentMonsterPlayerId)
endfunction


function IsUnitInvulnerable takes unit u returns boolean
    local real life = GetUnitState(u, UNIT_STATE_LIFE)
    local real damages
    call UnitDamageTarget(u, u, 0.01, false, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_UNIVERSAL,WEAPON_TYPE_WHOKNOWS)
    set damages=life-GetUnitState(u, UNIT_STATE_LIFE)
    call SetUnitState(u, UNIT_STATE_LIFE, life)
    return (damages == 0)
endfunction 


function StopUnit takes unit U returns nothing
    call PauseUnit(U, true)
    call IssueImmediateOrder(U, "stop")
    call PauseUnit(U, false)
endfunction


function IsHero takes unit U returns boolean
    local integer i = 0
    loop
        exitwhen (i > 11)
            if (udg_escapers.get(i).getHero() == U) then
                return true
            endif
        set i = i + 1
    endloop
    return false
endfunction

function ClearTextForPlayer takes player p returns nothing
    if (GetLocalPlayer() == p) then
        call ClearTextMessages()
    endif
endfunction

function MoveCamExceptForPlayer takes player p, real x, real y returns nothing
    if (GetLocalPlayer() == p) then
         set x = GetCameraTargetPositionX()
         set y = GetCameraTargetPositionY()
    endif
    call SetCameraPosition(x, y)
endfunction


function StringContainsChar takes string str, string char returns boolean
    local integer i
    local integer length
    if (StringLength(char) != 1) then
        return false
    endif
    set length = StringLength(str)
    set i = 1
    loop
        exitwhen (i > length)
            if (SubStringBJ(str, i, i) == char) then
                return true
            endif
        set i = i + 1
    endloop
    return false
endfunction


function IsBoolString takes string S returns boolean
    return (S == "true" or S == "false" or S == "on" or S == "off" or S == "1" or S == "0")
endfunction

function S2B takes string S returns boolean
    return (S == "true" or S == "on" or S == "1")
endfunction

function B2S takes boolean b returns string
    if (b) then
        return "true"
    endif
    return "false"
endfunction
    




//===========================================================================
function InitTrig_Basic_functions takes nothing returns nothing
endfunction



//===========================================================================
// Trigger: Functions on numbers
//===========================================================================
//TESH.scrollpos=15
//TESH.alwaysfold=0
function EstChiffre takes string str returns boolean
    if (str == "0" or str == "1" or str == "2" or str == "3" or str == "4") then
        return true
    endif
    if (str == "5" or str == "6" or str == "7" or str == "8" or str == "9") then
        return true
    endif
    return false
endfunction

function IsInteger takes string str returns boolean
    local integer length = StringLength(str)
    local integer i
    
    if (SubString(str, 0, 1) == "-") then
        set i = 1
    else
        set i = 0
    endif
    
    loop
        exitwhen (i >= length)
            if (not EstChiffre(SubString(str, i, i+1))) then
                return false
            endif
        set i = i + 1
    endloop
    
    return true
endfunction

function IsPositiveInteger takes string str returns boolean
    return (SubString(str, 0, 1) != "-" and IsInteger(str))
endfunction    

function IsPercentage takes string str returns boolean
    local integer n = S2I(str)
    return (IsPositiveInteger(str) and n >= 0 and n <= 100)
endfunction

function PercentageStringOrX2Integer takes string str returns integer
    if (not IsPercentage(str)) then
        if (str == "x") then
            return GetRandomInt(0, 100)
        endif
        return -1
    endif
    return S2I(str)
endfunction


endlibrary



//===========================================================================
function InitTrig_Functions_on_numbers takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: Ascii
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library Ascii

    globals
        private constant string TABLE_ASCII = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
        private constant integer DEBUT_TABLE_ASCII = 32
        private constant integer TAILLE_TABLE_ASCII = StringLength(TABLE_ASCII)
    endglobals
   
    //Permet de convertir un caractère en son nombre Ascii correspondant.
    //@caractere string : Caractère a convertir. Ne doit contenir qu'un seul caractère !
    //@return integer : Code Ascii de caractere.
    //                  Ou -1, si caractere n'est pas conforme.
    private function CaractereVersAscii takes string caractere returns integer
        //Le caractère est recherché dans TABLE_ASCII, et son rang est renvoyé.
       
        local integer curseurSurTableAscii = 0
   
        loop
            exitwhen (curseurSurTableAscii >= TAILLE_TABLE_ASCII) or (SubString(TABLE_ASCII, curseurSurTableAscii, curseurSurTableAscii + 1) == caractere)
            set curseurSurTableAscii = curseurSurTableAscii + 1
        endloop
   
        if (curseurSurTableAscii < TAILLE_TABLE_ASCII) then
            return curseurSurTableAscii + DEBUT_TABLE_ASCII
        endif
       
        //Caractère non reconnue.
        return -1
    endfunction

    //Permet de convertir un code Ascii en son caractère correspondant.
    //@integer source : Code Ascii a convertir. Doit être entre 32 et 126.
    //@return string : Caractère correspondant au code Ascii de source.
    //                 Ou chaine vide, en cas d'erreur.
    private function AsciiVersCaractere takes integer source returns string
        //Le caractère de TABLE_ASCII correspondant au rang est renvoyé.
        if (source >= DEBUT_TABLE_ASCII) and (source <= (StringLength(TABLE_ASCII) - 1 + DEBUT_TABLE_ASCII)) then
            return SubString(TABLE_ASCII, source - DEBUT_TABLE_ASCII, source - (DEBUT_TABLE_ASCII - 1))
        endif
        //Code Ascii non reconnu.
        return ""
    endfunction
   
    function String2Ascii takes string source returns integer
        //La chaine est parcouru de gauche à droite et convertis en même temps.
        //En cas d'erreur, -1 est renvoyé.
   
        local integer resultat = 0
        local integer resultatIntermediaire = 0
        local integer curseurSurSource = 0
        local integer sourceTaille = StringLength(source)
   
        loop
            exitwhen (curseurSurSource >= sourceTaille) or (resultatIntermediaire == -1)
            set resultatIntermediaire = CaractereVersAscii(SubString(source, curseurSurSource, curseurSurSource + 1))
            set resultat = resultat*256 + resultatIntermediaire
            set curseurSurSource = curseurSurSource + 1
        endloop
       
        if (resultatIntermediaire != -1) then
            return resultat
        endif
       
        //Un caractère n'a pas été reconnue dans source.
        return -1
    endfunction
   
    function Ascii2String takes integer source returns string
        //source est divisé successivement par 256 et le reste est utilisé pour retrouver le caractère correspondant.
        //Le résultat est construit en même temps.
        //En cas d'erreur, "" est retourné.
       
        local string resultat = ""
        local string resultatIntermediaire = " "    //Pour éviter une initialisation à "".
        local integer modulo = 1                    //Pour éviter une initialisation à 0.
       
        loop
            exitwhen (resultatIntermediaire == "") or (modulo <= 0)
            set modulo = source - (source/256) * 256
            set resultatIntermediaire = AsciiVersCaractere(modulo)
            set resultat = resultatIntermediaire + resultat
            set source = source/256
        endloop
       
        if (modulo == 0) then
            return resultat
        endif
       
        //Le code n'a pas été reconnue.
        return ""
    endfunction

endlibrary



//===========================================================================
function InitTrig_Ascii takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: Decode string
//===========================================================================
//TESH.scrollpos=47
//TESH.alwaysfold=0
library DecodeString needs Text


private function DecodeChar takes string char returns string    
    //! textmacro DecodeChar takes in, out
    if (char == "$in$") then
        return "$out$"
    endif
    //! endtextmacro
    
    //! runtextmacro DecodeChar("A", "Z")
    //! runtextmacro DecodeChar("B", "A")
    //! runtextmacro DecodeChar("C", "B")
    //! runtextmacro DecodeChar("D", "C")
    //! runtextmacro DecodeChar("E", "D")
    //! runtextmacro DecodeChar("F", "E")
    //! runtextmacro DecodeChar("G", "F")
    //! runtextmacro DecodeChar("H", "G")
    //! runtextmacro DecodeChar("I", "H")
    //! runtextmacro DecodeChar("J", "I")
    //! runtextmacro DecodeChar("K", "J")
    //! runtextmacro DecodeChar("L", "K")
    //! runtextmacro DecodeChar("M", "L")
    //! runtextmacro DecodeChar("N", "M")
    //! runtextmacro DecodeChar("O", "N")
    //! runtextmacro DecodeChar("P", "O")
    //! runtextmacro DecodeChar("Q", "P")
    //! runtextmacro DecodeChar("R", "Q")
    //! runtextmacro DecodeChar("S", "R")
    //! runtextmacro DecodeChar("T", "S")
    //! runtextmacro DecodeChar("U", "T")
    //! runtextmacro DecodeChar("V", "U")
    //! runtextmacro DecodeChar("W", "V")
    //! runtextmacro DecodeChar("X", "W")
    //! runtextmacro DecodeChar("Y", "X")
    //! runtextmacro DecodeChar("Z", "Y")
    
    //! runtextmacro DecodeChar("a", "z")
    //! runtextmacro DecodeChar("b", "a")
    //! runtextmacro DecodeChar("c", "b")
    //! runtextmacro DecodeChar("d", "c")
    //! runtextmacro DecodeChar("e", "d")
    //! runtextmacro DecodeChar("f", "e")
    //! runtextmacro DecodeChar("g", "f")
    //! runtextmacro DecodeChar("h", "g")
    //! runtextmacro DecodeChar("i", "h")
    //! runtextmacro DecodeChar("j", "i")
    //! runtextmacro DecodeChar("k", "j")
    //! runtextmacro DecodeChar("l", "k")
    //! runtextmacro DecodeChar("m", "l")
    //! runtextmacro DecodeChar("n", "m")
    //! runtextmacro DecodeChar("o", "n")
    //! runtextmacro DecodeChar("p", "o")
    //! runtextmacro DecodeChar("q", "p")
    //! runtextmacro DecodeChar("r", "q")
    //! runtextmacro DecodeChar("s", "r")
    //! runtextmacro DecodeChar("t", "s")
    //! runtextmacro DecodeChar("u", "t")
    //! runtextmacro DecodeChar("v", "u")
    //! runtextmacro DecodeChar("w", "v")
    //! runtextmacro DecodeChar("x", "w")
    //! runtextmacro DecodeChar("y", "x")
    //! runtextmacro DecodeChar("z", "y")
    
    return char
endfunction


function DecodeString takes string strIn returns string
    local string strOut = ""
    local integer i = 1
    loop
        exitwhen (i > StringLength(strIn))
            set strOut = strOut + DecodeChar(SubStringBJ(strIn, i, i))
        set i = i + 1
    endloop
    //call Text_A("strIn : " + strIn + ", strOut : " + strOut)
    return strOut
endfunction




endlibrary



//===========================================================================
function InitTrig_Decode_string takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: View all hide all
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library ViewAllHideAll


globals
    fogmodifier udg_hideAll
    fogmodifier udg_viewAll
endglobals


function RefreshHideAllVM takes nothing returns nothing
    call DestroyFogModifier(udg_hideAll)
    set udg_hideAll = CreateFogModifierRect(Player(0), FOG_OF_WAR_MASKED, GetWorldBounds(), true, false )
    call FogModifierStart(udg_hideAll)
endfunction


function InitTrig_View_all_hide_all takes nothing returns nothing
    set udg_viewAll = CreateFogModifierRect(Player(0), FOG_OF_WAR_VISIBLE, GetPlayableMapRect(), true, false )
    set udg_hideAll = CreateFogModifierRect(Player(0), FOG_OF_WAR_MASKED, GetWorldBounds(), true, false )
    call FogModifierStart(udg_hideAll)
endfunction


endlibrary//===========================================================================
// Trigger: Immolation skills
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library ImmolationSkills


globals
    integer array IMMOLATION_SKILLS
endglobals


function InitTrig_Immolation_skills takes nothing returns nothing
    set IMMOLATION_SKILLS[1] = 'I005'
    set IMMOLATION_SKILLS[2] = 'I010'
    set IMMOLATION_SKILLS[3] = 'I015'
    set IMMOLATION_SKILLS[4] = 'I020'
    set IMMOLATION_SKILLS[5] = 'I025'
    set IMMOLATION_SKILLS[6] = 'I030'
    set IMMOLATION_SKILLS[7] = 'I035'
    set IMMOLATION_SKILLS[8] = 'I040'
    set IMMOLATION_SKILLS[9] = 'I045'
    set IMMOLATION_SKILLS[10] = 'I050'
    set IMMOLATION_SKILLS[11] = 'I055'
    set IMMOLATION_SKILLS[12] = 'I060'
    set IMMOLATION_SKILLS[13] = 'I065'
    set IMMOLATION_SKILLS[14] = 'I070'
    set IMMOLATION_SKILLS[15] = 'I075'
    set IMMOLATION_SKILLS[16] = 'I080'
    set IMMOLATION_SKILLS[17] = 'I085'
    set IMMOLATION_SKILLS[18] = 'I090'
    set IMMOLATION_SKILLS[19] = 'I095'
    set IMMOLATION_SKILLS[20] = 'I100'
    set IMMOLATION_SKILLS[21] = 'I105'
    set IMMOLATION_SKILLS[22] = 'I110'
    set IMMOLATION_SKILLS[23] = 'I115'
    set IMMOLATION_SKILLS[24] = 'I120'
    set IMMOLATION_SKILLS[25] = 'I125'
    set IMMOLATION_SKILLS[26] = 'I130'
    set IMMOLATION_SKILLS[27] = 'I135'
    set IMMOLATION_SKILLS[28] = 'I140'
    set IMMOLATION_SKILLS[29] = 'I145'
    set IMMOLATION_SKILLS[30] = 'I150'
    set IMMOLATION_SKILLS[31] = 'I155'
    set IMMOLATION_SKILLS[32] = 'I160'
    set IMMOLATION_SKILLS[33] = 'I165'
    set IMMOLATION_SKILLS[34] = 'I170'
    set IMMOLATION_SKILLS[35] = 'I175'
    set IMMOLATION_SKILLS[36] = 'I180'
    set IMMOLATION_SKILLS[37] = 'I185'
    set IMMOLATION_SKILLS[38] = 'I190'
    set IMMOLATION_SKILLS[39] = 'I195'
    set IMMOLATION_SKILLS[40] = 'I200'
    set IMMOLATION_SKILLS[41] = 'I205'
    set IMMOLATION_SKILLS[42] = 'I210'
    set IMMOLATION_SKILLS[43] = 'I215'
    set IMMOLATION_SKILLS[44] = 'I220'
    set IMMOLATION_SKILLS[45] = 'I225'
    set IMMOLATION_SKILLS[46] = 'I230'
    set IMMOLATION_SKILLS[47] = 'I235'
    set IMMOLATION_SKILLS[48] = 'I240'
    set IMMOLATION_SKILLS[49] = 'I245'
    set IMMOLATION_SKILLS[50] = 'I250'
    set IMMOLATION_SKILLS[51] = 'I255'
    set IMMOLATION_SKILLS[52] = 'I260'
    set IMMOLATION_SKILLS[53] = 'I265'
    set IMMOLATION_SKILLS[54] = 'I270'
    set IMMOLATION_SKILLS[55] = 'I275'
    set IMMOLATION_SKILLS[56] = 'I280'
    set IMMOLATION_SKILLS[57] = 'I285'
    set IMMOLATION_SKILLS[58] = 'I290'
    set IMMOLATION_SKILLS[59] = 'I295'
    set IMMOLATION_SKILLS[60] = 'I300'
    set IMMOLATION_SKILLS[61] = 'I305'
    set IMMOLATION_SKILLS[62] = 'I310'
    set IMMOLATION_SKILLS[63] = 'I315'
    set IMMOLATION_SKILLS[64] = 'I320'
    set IMMOLATION_SKILLS[65] = 'I325'
    set IMMOLATION_SKILLS[66] = 'I330'
    set IMMOLATION_SKILLS[67] = 'I335'
    set IMMOLATION_SKILLS[68] = 'I340'
    set IMMOLATION_SKILLS[69] = 'I345'
    set IMMOLATION_SKILLS[70] = 'I350'
    set IMMOLATION_SKILLS[71] = 'I355'
    set IMMOLATION_SKILLS[72] = 'I360'
    set IMMOLATION_SKILLS[73] = 'I365'
    set IMMOLATION_SKILLS[74] = 'I370'
    set IMMOLATION_SKILLS[75] = 'I375'
    set IMMOLATION_SKILLS[76] = 'I380'
    set IMMOLATION_SKILLS[77] = 'I385'
    set IMMOLATION_SKILLS[78] = 'I390'
    set IMMOLATION_SKILLS[79] = 'I395'
    set IMMOLATION_SKILLS[80] = 'I400'
endfunction




endlibrary//===========================================================================
// Trigger: MonsterType
//===========================================================================
//TESH.scrollpos=187
//TESH.alwaysfold=0
library MonsterType needs ImmolationSkills


struct MonsterType
    string label
    string alias
    private integer unitTypeId
    private real scale //influe sur la taille de l'unité ; 1.0 donne une taille normale
    private integer immolationSkill
    private real speed
    private boolean isClickableB
    private string killingEffectStr
    private integer maxLife
    
    
	method setLabel takes string label returns nothing
		set .label = label
	endmethod
	
	method setAlias takes string alias returns MonsterType
		set .alias = alias
        return this
	endmethod

    static method create takes string label, integer unitTypeId, real scale, real immolationRadius, real speed, boolean isClickable returns MonsterType
        local MonsterType mt
        local unit testMonster
        if (speed <= 0 or speed > MAX_MOVE_SPEED or scale <= 0 or not((immolationRadius/5) == I2R(R2I(immolationRadius/5))) or immolationRadius < 5 or immolationRadius > 400) then
            return 0
        endif
        set testMonster = CreateUnit(NEUTRAL_PLAYER, unitTypeId, 0,0,0)
        if (testMonster == null) then
            return 0
        else
            call RemoveUnit(testMonster)
            set testMonster = null
        endif
        set mt = MonsterType.allocate()
        set mt.label = label
        set mt.alias = null
        set mt.unitTypeId = unitTypeId
        set mt.scale = scale
        set mt.immolationSkill = IMMOLATION_SKILLS[R2I(immolationRadius/5)]
        set mt.speed = speed
        set mt.isClickableB = isClickable
        set mt.killingEffectStr = null
        set mt.maxLife = 10000
        return mt
    endmethod
    
    method refresh takes nothing returns nothing //recrée les monstres correspondant au niveau actuel
        local Level array levelsMaking
        local Escaper escaper
        local integer i
        local integer j
        local boolean levelAlreadyChecked
        local integer nbLevelsMaking = 0
        local Level currentLevel = udg_levels.getCurrentLevel()
        call currentLevel.recreateMonstersOfType(this) 
        set i = 0
        loop
            exitwhen (i > 11)
                set escaper = udg_escapers.get(i)
                if (escaper != 0) then
                    if (escaper.getMakingLevel() != currentLevel) then
                        set levelAlreadyChecked = false
                        set j = 0
                        loop
                            exitwhen (j >= nbLevelsMaking)
                                if (escaper.getMakingLevel() == levelsMaking[j]) then
                                    set levelAlreadyChecked = true
                                endif
                            set j = j + 1
                        endloop
                        if (not levelAlreadyChecked) then
                            set levelsMaking[nbLevelsMaking] = escaper.getMakingLevel()
                            set nbLevelsMaking = nbLevelsMaking + 1
                        endif
                    endif
                endif
            set i = i + 1
        endloop
        set i = 0
        loop
            exitwhen (i >= nbLevelsMaking)
                call levelsMaking[i].recreateMonstersOfType(this)
            set i = i + 1
        endloop
    endmethod
    
    method onDestroy takes nothing returns nothing
        call udg_levels.removeMonstersOfType(this)
    endmethod
    
    method getUnitTypeId takes nothing returns integer
        return .unitTypeId
    endmethod
    
    method setUnitTypeId takes integer unitTypeId returns boolean
        local unit testMonster = CreateUnit(NEUTRAL_PLAYER, unitTypeId, 0,0,0)
        if (testMonster == null) then
            return false
        endif
        call RemoveUnit(testMonster)
        set testMonster = null
        set .unitTypeId = unitTypeId
        call .refresh()
        return true
    endmethod
    
    method getScale takes nothing returns real
        return .scale
    endmethod
    
    method setScale takes real scale returns boolean
        if (scale <= 0) then
            return false
        endif
        set .scale = scale
        call .refresh()
        return true
    endmethod
    
    method getImmolationSkill takes nothing returns integer
        return .immolationSkill
    endmethod
    
    method setImmolation takes real immolationRadius returns boolean
        if (not((immolationRadius/5) == I2R(R2I(immolationRadius/5))) or immolationRadius < 5 or immolationRadius > 400) then
            return false
        endif
        set .immolationSkill = IMMOLATION_SKILLS[R2I(immolationRadius/5)]
        call .refresh()
        return true
    endmethod
    
    method getUnitMoveSpeed takes nothing returns real
        return .speed
    endmethod
    
    method setUnitMoveSpeed takes real speed returns boolean
        if (speed <= 0 or speed > MAX_MOVE_SPEED) then
            return false
        endif
        set .speed = speed
        call .refresh()
        return true
    endmethod
    
    method isClickable takes nothing returns boolean
        return .isClickableB
    endmethod
    
    method setIsClickable takes boolean isClickable returns boolean
        if (.isClickableB == isClickable) then
            return false
        endif
        set .isClickableB = isClickable
        call .refresh()
        return true
    endmethod
    
    method getKillingEffectStr takes nothing returns string
        return .killingEffectStr
    endmethod
    
    method setKillingEffectStr takes string effectStr returns MonsterType
        set .killingEffectStr = effectStr
        return this
    endmethod
    
    method displayForPlayer takes player p returns nothing
        local string space = "   "
        local string display = udg_colorCode[RED] + .label + " " + .alias + " : '"
        set display = display + Ascii2String(.unitTypeId) + "'" + space + "'" + Ascii2String(.immolationSkill) + "'"
        set display = display + space + I2S(R2I(.speed)) + space + R2S(.scale)
        if (.isClickableB) then
            set display = display + space + "clickable" + space + I2S(.maxLife / 10000)
        endif
        call Text_P_timed(p, TERRAIN_DATA_DISPLAY_TIME, display)
    endmethod
    
    method displayTotalForPlayer takes player p returns nothing
        local string space = "   "
        local string display = udg_colorCode[RED] + .label + " " + .alias + " : '"
        set display = display + Ascii2String(.unitTypeId) + "'" + space + "'" + Ascii2String(.immolationSkill) + "'"
        set display = display + space + I2S(R2I(.speed)) + space + R2S(.scale) + space + .killingEffectStr
        if (.isClickableB) then
            set display = display + space + "clickable" + space + I2S(.maxLife / 10000)
        endif
        call Text_P_timed(p, TERRAIN_DATA_DISPLAY_TIME, display)
    endmethod
    
    method setNbMeteorsToKill takes integer nbMeteorsToKill returns MonsterType
        //nombre de météores qu'il faut pour tuer le monstre, sachant qu'une météore fait 10k de dégât
        if (nbMeteorsToKill < 1 or nbMeteorsToKill > 9) then
            return this
        endif
        set .maxLife = nbMeteorsToKill * 10000
        if (.isClickableB) then
            call .refresh()
        endif
        return this
    endmethod
    
    method getMaxLife takes nothing returns integer
        return .maxLife
    endmethod
    
    method getImmolationRadiusStr takes nothing returns string
        local string immoStr = Ascii2String(.immolationSkill)
        set immoStr = SubStringBJ(immoStr, 2, 4)
        return I2S(S2I(immoStr))
    endmethod
    
    method toString takes nothing returns string
        local string str = .label + CACHE_SEPARATEUR_PARAM + .alias + CACHE_SEPARATEUR_PARAM
        set str = str + Ascii2String(.unitTypeId) + CACHE_SEPARATEUR_PARAM + R2S(.scale) + CACHE_SEPARATEUR_PARAM
        set str = str + .getImmolationRadiusStr() + CACHE_SEPARATEUR_PARAM + R2S(.speed) + CACHE_SEPARATEUR_PARAM
        set str = str + B2S(.isClickableB) + CACHE_SEPARATEUR_PARAM + .killingEffectStr + CACHE_SEPARATEUR_PARAM
        set str = str + I2S(.maxLife / 10000)
        return str
    endmethod
endstruct



//===========================================================================
function InitTrig_MonsterType takes nothing returns nothing
endfunction



endlibrary//===========================================================================
// Trigger: MonsterTypeArray
//===========================================================================
//TESH.scrollpos=59
//TESH.alwaysfold=0
library MonsterTypeArray needs MonsterType


struct MonsterTypeArray
    private MonsterType array monsterTypes [1000]
    private integer numberOfMonsterTypes

    static method create takes nothing returns MonsterTypeArray
        local MonsterTypeArray ma = MonsterTypeArray.allocate()
        set ma.numberOfMonsterTypes = 0
        return ma        
    endmethod
    
    method get takes string label returns MonsterType
		local integer i = 0
		loop
			exitwhen (i >= .numberOfMonsterTypes)
				if (.monsterTypes[i].label == label or .monsterTypes[i].alias == label) then
					return .monsterTypes[i]
				endif
			set i = i + 1
		endloop
		return 0
	endmethod

	method isLabelAlreadyUsed takes string label returns boolean
		return (.get(label) != 0)
	endmethod
    
    method new takes string label, integer unitTypeId, real scale, real immolationRadius, real speed, boolean isClickable returns MonsterType
        local integer n = .numberOfMonsterTypes
        if (.isLabelAlreadyUsed(label)) then
            return 0
        endif
        set .monsterTypes[n] = MonsterType.create(label, unitTypeId, scale, immolationRadius, speed, isClickable)
        if (.monsterTypes[n] != 0) then
            set .numberOfMonsterTypes = .numberOfMonsterTypes + 1
        endif
        return .monsterTypes[n]
    endmethod
    
    method remove takes string label returns boolean
        local integer position
        local integer i
        local MonsterType mt = .get(label)
        if (mt == 0) then
            return false
        endif
        set i = 0
        loop
            exitwhen (.monsterTypes[i].label == label or .monsterTypes[i].alias == label or i >= .numberOfMonsterTypes)
            set i = i + 1
        endloop
        if (i < .numberOfMonsterTypes) then
            set position = i
            set i = i + 1
            loop
                exitwhen (i >= .numberOfMonsterTypes)
                    set .monsterTypes[i-1] = .monsterTypes[i]
                set i = i + 1
            endloop
            set .numberOfMonsterTypes = .numberOfMonsterTypes - 1
        endif
        call mt.destroy()
        return true
    endmethod
    
    method displayForPlayer takes player p returns nothing
        local integer i = 0
        loop
            exitwhen (i >= .numberOfMonsterTypes)
                call .monsterTypes[i].displayForPlayer(p)
            set i = i + 1
        endloop
        if (.numberOfMonsterTypes == 0) then
            call Text_erP(p, "no monster type saved")
        endif
    endmethod
    
    method monsterUnit2KillEffectStr takes unit monsterUnit returns string
        local integer monsterUnitTypeId = GetUnitTypeId(monsterUnit)
        local integer i = 0
        loop
            exitwhen i >= numberOfMonsterTypes
                if(.monsterTypes[i].getUnitTypeId() == monsterUnitTypeId)then
                    return .monsterTypes[i].getKillingEffectStr()
                endif
            set i = i + 1
        endloop
        return null
    endmethod
    
    method monsterUnit2MonsterType takes unit monsterUnit returns MonsterType
        local integer monsterUnitTypeId = GetUnitTypeId(monsterUnit)
        local integer i = 0
        loop
            exitwhen i >= numberOfMonsterTypes
                if(.monsterTypes[i].getUnitTypeId() == monsterUnitTypeId)then
                    return .monsterTypes[i]
                endif
            set i = i + 1
        endloop
        return 0
    endmethod
    
    method saveInCache takes nothing returns nothing
        local integer i
        set stringArrayForCache = StringArrayForCache.create("monsterTypes", "monsterTypes", true)
        set i = 0
        loop
            exitwhen (i >= .numberOfMonsterTypes)
                call stringArrayForCache.push(.monsterTypes[i].toString())
            set i = i + 1
        endloop
        call stringArrayForCache.writeInCache()
    endmethod
endstruct


//===========================================================================
function InitTrig_MonsterTypeArray takes nothing returns nothing
endfunction





endlibrary//===========================================================================
// Trigger: Monster creation functions
//===========================================================================
//TESH.scrollpos=60
//TESH.alwaysfold=0
library Monsters needs BasicFunctions, MonsterTypeArray


scope MonsterCreationFunctions


globals
    private unit monster
    private integer ATTACK_SKILL = 'Aatk'
    private constant integer ABILITY_1_LIFE = 'ABV1'
    private constant integer ABILITY_10_LIFE = 'ABV2'
    private constant integer ABILITY_100_LIFE = 'ABV3'
    private constant integer ABILITY_1000_LIFE = 'ABV4'
    private constant integer ABILITY_10000_LIFE = 'ABV5'
    private constant integer ABILITY_ANNULER_VISION = 'A0AV'
endglobals

    
    
private function UnitAddRemoveLifeAbility takes unit u, integer lifeAbility returns nothing
    call UnitAddAbility(u, lifeAbility)
    call SetUnitAbilityLevel(u, lifeAbility, 2)
    call UnitRemoveAbility(u, lifeAbility)
endfunction

function UnitAddMaxLife takes unit u, integer lifeToAdd returns nothing
    loop
        exitwhen (lifeToAdd <= 0)
            if (lifeToAdd >= 10000) then
                call UnitAddRemoveLifeAbility(u, ABILITY_10000_LIFE)
                set lifeToAdd = lifeToAdd - 10000
            else
                if (lifeToAdd >= 1000) then
                    call UnitAddRemoveLifeAbility(u, ABILITY_1000_LIFE)
                    set lifeToAdd = lifeToAdd - 1000
                else
                    if (lifeToAdd >= 100) then
                        call UnitAddRemoveLifeAbility(u, ABILITY_100_LIFE)
                        set lifeToAdd = lifeToAdd - 100
                    else
                        if (lifeToAdd >= 10) then
                            call UnitAddRemoveLifeAbility(u, ABILITY_10_LIFE)
                            set lifeToAdd = lifeToAdd - 10
                        else
                            call UnitAddRemoveLifeAbility(u, ABILITY_1_LIFE)
                            set lifeToAdd = lifeToAdd - 1
                        endif
                    endif
                endif
            endif
    endloop
endfunction

function SetUnitMaxLife takes unit u, integer newMaxLife returns boolean
    local integer maxLife = R2I(GetUnitState(u, UNIT_STATE_MAX_LIFE))
    if (newMaxLife <= maxLife) then
        return false
    endif
    call UnitAddMaxLife(u, newMaxLife - maxLife)
    return true
endfunction


function NewImmobileMonsterForPlayer takes MonsterType mt, player p, real x, real y, real angle returns unit
    local real scale
    if (angle == -1) then
        set monster = CreateUnit(p, mt.getUnitTypeId(), x, y, GetRandomDirectionDeg())
    else
        set monster = CreateUnit(p, mt.getUnitTypeId(), x, y, angle)
    endif
    //if (IsHeroUnitId(mt.getUnitTypeId())) then
    //    call Text_A("hero")
    //else
    //    call Text_A("pas hero")
    //endif
    call SetUnitUseFood(monster, false)
    if (mt.isClickable()) then
        call SetUnitMaxLife(monster, mt.getMaxLife())
    else
        call UnitAddAbility(monster, 'Aloc')
        call UnitAddAbility(monster, ABILITY_ANNULER_VISION)
    endif
    call UnitAddAbility(monster, mt.getImmolationSkill())
    set scale = mt.getScale()
    if (scale != 1) then
        call SetUnitScale(monster, scale, scale, scale)
    endif
    call SetUnitMoveSpeed(monster, mt.getUnitMoveSpeed())
    call SetUnitColor(monster, ConvertPlayerColor(12))
    call UnitRemoveAbility(monster, ATTACK_SKILL)
    return monster
endfunction

function NewImmobileMonster takes MonsterType mt, real x, real y, real angle returns unit
    local player p
    if (mt.isClickable()) then
        set p = ENNEMY_PLAYER
    else
        set p = GetCurrentMonsterPlayer()
    endif
    return NewImmobileMonsterForPlayer(mt, p, x, y, angle)
endfunction


function NewPatrolMonster takes MonsterType mt, real x1, real y1, real x2, real y2 returns unit
    local real angle = bj_RADTODEG * Atan2(y1 - y2, x1 - x2)
    set monster = NewImmobileMonster(mt, x1, y1, angle)
    call IssuePointOrder(monster, "patrol", x2, y2)
    return monster
endfunction


function MonsterTypeString2Id takes string S returns integer


    return 0
endfunction


function IsMonsterTypeString takes string str returns boolean
    return MonsterTypeString2Id( str ) != 0
endfunction




endscope






//===========================================================================
function InitTrig_Monster_creation_functions takes nothing returns nothing
endfunction



//===========================================================================
// Trigger: Monster
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope MonsterInterface


interface Monster [600000] //200 niveaux * 1000 monstres par type * 3 types
    static integer nbInstances = 0
	unit u = null
	MonsterType mt
    Level level
    integer arrayId
    integer life
	//static method count takes nothing returns integer
	method createUnit takes nothing returns nothing
	method removeUnit takes nothing returns nothing
    method killUnit takes nothing returns nothing
    method getMonsterType takes nothing returns MonsterType
    method toString takes nothing returns string
    method getLife takes nothing returns integer
    method setLife takes integer life returns nothing
endinterface


endscope


globals
    constant integer MAX_NB_MONSTERS = 1000 //nombre maximum de monstres pour chacun des trois types et par niveau (no move, simple patrol, multiple patrols)
endglobals



//===========================================================================
function InitTrig_Monster takes nothing returns nothing
endfunction



//===========================================================================
// Trigger:    trig Monsters clickable set life
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope MonstersClickableSetLife


globals
    group monstersClickable
    trigger trigMonstersClickableSetLife
    private constant real PERIOD = 0.1
endglobals


function MonstersClickableSetLifeForEach takes nothing returns nothing
    local unit monsterUnit = GetEnumUnit()
    local real currentLife = GetUnitState(monsterUnit, UNIT_STATE_LIFE)
    local Monster monster = Monster(GetUnitUserData(monsterUnit))
    local real previousLife = I2R(monster.getLife())
    local real diffLife = RMaxBJ(currentLife, previousLife) - RMinBJ(currentLife, previousLife)
    if (diffLife < 100) then
        call SetUnitLifeBJ(GetEnumUnit(), previousLife - 0.5)
    else
        loop
            exitwhen (diffLife <= 0)
                call monster.setLife(R2I(previousLife) - 10000)
            set diffLife = diffLife - 10000
        endloop
    endif
endfunction

function MonstersClickableSetLife_Actions takes nothing returns nothing
    call ForGroup(monstersClickable, function MonstersClickableSetLifeForEach)
endfunction


//===========================================================================
function InitTrig____trig_Monsters_clickable_set_life takes nothing returns nothing
    set monstersClickable = CreateGroup()
    set trigMonstersClickableSetLife = CreateTrigger()
    call TriggerAddAction(trigMonstersClickableSetLife, function MonstersClickableSetLife_Actions)
    call TriggerRegisterTimerEvent(trigMonstersClickableSetLife, PERIOD, true)
endfunction


endscope//===========================================================================
// Trigger: MonsterNoMove
//===========================================================================
//TESH.scrollpos=15
//TESH.alwaysfold=0
scope MonsterNoMove


struct MonsterNoMove extends Monster
    static integer nbInstances = 0
    
    static method count takes nothing returns integer
        return MonsterNoMove.nbInstances
    endmethod
    
    
    unit u
    private MonsterType mt
    
	private real x
	private real y
    private real angle //-1 -> random
    
	method removeUnit takes nothing returns nothing
        if (.u != null) then
            call GroupRemoveUnit(monstersClickable, .u)
            call RemoveUnit(.u)
            set .u = null
        endif
	endmethod
    
    method killUnit takes nothing returns nothing
        if (.u != null and IsUnitAliveBJ(.u)) then
            call KillUnit(.u)
        endif
    endmethod
    
    private method onDestroy takes nothing returns nothing
		if (.u != null) then
			call .removeUnit()
		endif
        call .level.monstersNoMove.setMonsterNull(.arrayId)
        set MonsterNoMove.nbInstances = MonsterNoMove.nbInstances - 1
    endmethod
	
	static method create takes MonsterType mt, real x, real y, real angle returns MonsterNoMove
		local MonsterNoMove m = MonsterNoMove.allocate()
        set MonsterNoMove.nbInstances = MonsterNoMove.nbInstances + 1
        set m.mt = mt
		set m.x = x
		set m.y = y
        set m.angle = angle
        set m.life = 0
		return m
	endmethod
	
	method createUnit takes nothing returns nothing
        if (.u != null) then
            call .removeUnit()
        endif
        set .u = NewImmobileMonster(.mt, .x, .y, .angle)
        call SetUnitUserData(.u, integer(this))
        if (.mt.isClickable()) then
            set .life = .mt.getMaxLife()
            call GroupAddUnit(monstersClickable, .u)
        endif
	endmethod
	
    method getLife takes nothing returns integer
        return .life
    endmethod
    
    method setLife takes integer life returns nothing
        set .life = life
        if (life > 0) then
            call SetUnitLifeBJ(.u, I2R(life) - 0.5)
        else
            call .killUnit()
        endif
    endmethod
    
    method getMonsterType takes nothing returns MonsterType
        return .mt
    endmethod
    
    method toString takes nothing returns string
        local string str
        if (.mt.alias != null and .mt.alias != "") then
            set str = .mt.alias + CACHE_SEPARATEUR_PARAM
        else
            set str = .mt.label + CACHE_SEPARATEUR_PARAM
        endif
        set str = str + I2S(R2I(.x)) + CACHE_SEPARATEUR_PARAM + I2S(R2I(.y))
        set str = str + CACHE_SEPARATEUR_PARAM + I2S(R2I(.angle))
        return str
    endmethod
endstruct


endscope




//===========================================================================
function InitTrig_MonsterNoMove takes nothing returns nothing
endfunction




//===========================================================================
// Trigger: MonsterNoMoveArray
//===========================================================================
//TESH.scrollpos=18
//TESH.alwaysfold=0
globals
    constant real MONSTER_NEAR_DIFF_MAX = 64
endglobals

scope MonsterNoMoveArray


struct MonsterNoMoveArray [200000] //200 niveaux * 1000 monstres
    private MonsterNoMove array monsters [MAX_NB_MONSTERS]
	private integer lastInstance
	
	static method create takes nothing returns MonsterNoMoveArray
		local MonsterNoMoveArray ma = MonsterNoMoveArray.allocate()
		set ma.lastInstance = -1
		return ma
	endmethod
	
	method getFirstEmpty takes nothing returns integer
		local integer i = 0
		loop
			exitwhen (i > .lastInstance or .monsters[i] == 0)
			set i = i + 1
		endloop
		return i
	endmethod	
	
    method get takes integer arrayId returns MonsterNoMove
        if (arrayId < 0 or arrayId > .lastInstance) then
            return 0
        endif
        return .monsters[arrayId]
    endmethod
    
    method getLastInstanceId takes nothing returns integer
        return .lastInstance
    endmethod
	
    method new takes MonsterType mt, real x, real y, real angle, boolean createUnit returns MonsterNoMove //retourne le monstre s'il a pu être créé, 0 sinon
		//local integer n = .getFirstEmpty()
        local integer n = .lastInstance + 1
		if (n >= MAX_NB_MONSTERS) then
			return 0
		endif
		//if (n > .lastInstance) then
			set .lastInstance = n
		//endif
		set .monsters[n] = MonsterNoMove.create(mt, x, y, angle)
		if (createUnit) then
			call .monsters[n].createUnit()
		endif
        set .monsters[n].level = udg_levels.getLevelFromMonsterNoMoveArray(this)
        set .monsters[n].arrayId = n
		return .monsters[n]   
    endmethod
	
	method count takes nothing returns integer
		local integer n = 0
		local integer i = 0
		loop
			exitwhen (i > .lastInstance)
				if (.monsters[i] != 0) then
					set n = n + 1
				endif
			set i = i + 1
		endloop
		return n
	endmethod
    
    method onDestroy takes nothing returns nothing
        local integer i = 0
        loop
            exitwhen (i > .lastInstance)
                if (.monsters[i] != 0) then
                    call .monsters[i].destroy()
                endif
            set i = i + 1
        endloop
        set .lastInstance = -1
    endmethod
    
    method setMonsterNull takes integer monsterArrayId returns nothing
        set .monsters[monsterArrayId] = 0
    endmethod
    
    method clearMonster takes integer monsterId returns boolean
        local integer i = 0
        loop
            exitwhen (.monsters[i] == MonsterNoMove(monsterId) or i > .lastInstance)
            set i = i + 1
        endloop
        if (i > .lastInstance) then
            return false
        endif
        call .monsters[i].destroy()
        return true
    endmethod
    
    method getMonsterNear takes real x, real y returns MonsterNoMove
        local real xMob
        local real yMob
        local integer i = 0
        loop
            exitwhen (i > .lastInstance)
                if (.monsters[i] != 0 and .monsters[i].u != null) then
                    set xMob = GetUnitX(.monsters[i].u)
                    set yMob = GetUnitY(.monsters[i].u)
                    if (RAbsBJ(x - xMob) < MONSTER_NEAR_DIFF_MAX and RAbsBJ(y - yMob) < MONSTER_NEAR_DIFF_MAX) then
                        return .monsters[i]
                    endif
                endif
            set i = i + 1
        endloop
        return 0    
    endmethod
    
    method createMonsters takes nothing returns nothing
        local integer i = 0
        loop
            exitwhen (i > .lastInstance)
                if (.monsters[i] != 0) then
                    call .monsters[i].createUnit()
                endif
            set i = i + 1
        endloop
    endmethod
    
    method removeMonsters takes nothing returns nothing
        local integer i = 0
        loop
            exitwhen (i > .lastInstance)
                if (.monsters[i] != 0) then
                    call .monsters[i].removeUnit()
                endif
            set i = i + 1
        endloop
    endmethod
    
    method recreateMonstersOfType takes MonsterType mt returns nothing
        local integer i = 0
        loop
            exitwhen (i > .lastInstance)
                if (.monsters[i] != 0 and .monsters[i].getMonsterType() == mt and .monsters[i].u != null) then
                    call .monsters[i].createUnit()
                endif
            set i = i + 1
        endloop
    endmethod
    
    method removeMonstersOfType takes MonsterType mt returns nothing
        local integer i = 0
        loop
            exitwhen (i > .lastInstance)
                if (.monsters[i] != 0 and .monsters[i].getMonsterType() == mt) then
                    call .monsters[i].destroy()
                endif
            set i = i + 1
        endloop
    endmethod
endstruct


endscope



//===========================================================================
function InitTrig_MonsterNoMoveArray takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: MonsterSimplePatrol
//===========================================================================
//TESH.scrollpos=93
//TESH.alwaysfold=0
scope MonsterSimplePatrol


//vérification que les monstres multi-patrouilles patrouillent bien
globals
    private group simplePatrolMobs = CreateGroup()
    private constant real checkSimplePatrolMobsPeriod = 5.
endglobals

private function CheckSimplePatrolMobsEnum takes nothing returns nothing
    if (GetUnitCurrentOrder(GetEnumUnit()) == 0) then //le mob s'est arrêté
        call MonsterSimplePatrol(GetUnitUserData(GetEnumUnit())).createUnit()
    endif        
endfunction 

private function CheckSimplePatrolMobs_Actions takes nothing returns nothing
    call ForGroup(simplePatrolMobs, function CheckSimplePatrolMobsEnum)
endfunction

private function InitTrig_CheckSimplePatrolMobs takes nothing returns nothing
    local trigger trigCheckSimplePatrolMobs = CreateTrigger()
    call TriggerAddAction(trigCheckSimplePatrolMobs, function CheckSimplePatrolMobs_Actions)
    call TriggerRegisterTimerEvent(trigCheckSimplePatrolMobs, checkSimplePatrolMobsPeriod, true)
    set trigCheckSimplePatrolMobs = null
endfunction

function InitTrig_MonsterSimplePatrol takes nothing returns nothing
    call InitTrig_CheckSimplePatrolMobs()
endfunction
/////////////////////////////////////////////////////////////////////////


struct MonsterSimplePatrol extends Monster
    static integer nbInstances = 0    
    
    static method count takes nothing returns integer
        return MonsterSimplePatrol.nbInstances
    endmethod
    
    
    unit u
    private MonsterType mt
    
	private real x1
	private real y1
	private real x2
	private real y2
	
	method removeUnit takes nothing returns nothing
        if (.u != null) then
            call GroupRemoveUnit(monstersClickable, .u)
            call GroupRemoveUnit(simplePatrolMobs, .u)
            call RemoveUnit(.u)
            set .u = null
        endif
	endmethod
    
    method killUnit takes nothing returns nothing
        if (.u != null and IsUnitAliveBJ(.u)) then
            call GroupRemoveUnit(simplePatrolMobs, .u)
            call KillUnit(.u)
        endif
    endmethod
    
    private method onDestroy takes nothing returns nothing
		if (.u != null) then
			call .removeUnit()
		endif
        call .level.monstersSimplePatrol.setMonsterNull(.arrayId)
        set MonsterSimplePatrol.nbInstances = MonsterSimplePatrol.nbInstances - 1
    endmethod
	
	static method create takes MonsterType mt, real x1, real y1, real x2, real y2 returns MonsterSimplePatrol
		local MonsterSimplePatrol m = MonsterSimplePatrol.allocate()
        set MonsterSimplePatrol.nbInstances = MonsterSimplePatrol.nbInstances + 1
        set m.mt = mt
		set m.x1 = x1
		set m.y1 = y1
		set m.x2 = x2
		set m.y2 = y2
        set m.life = 0
		return m
	endmethod
	
	method createUnit takes nothing returns nothing
        if (.u != null) then
            call .removeUnit()
        endif
        set .u = NewPatrolMonster(.mt, .x1, .y1, .x2, .y2)
        call SetUnitUserData(.u, integer(this))
        call GroupAddUnit(simplePatrolMobs, .u)
        if (.mt.isClickable()) then
            set .life = .mt.getMaxLife()
            call GroupAddUnit(monstersClickable, .u)
        endif
	endmethod   
	
    method getLife takes nothing returns integer
        return .life
    endmethod	
    
    method setLife takes integer life returns nothing
        set .life = life
        if (life > 0) then
            call SetUnitLifeBJ(.u, I2R(life) - 0.5)
        else
            call .killUnit()
        endif
    endmethod
    
    method getMonsterType takes nothing returns MonsterType
        return .mt
    endmethod 
    
    method toString takes nothing returns string
        local string str
        if (.mt.alias != null and .mt.alias != "") then
            set str = .mt.alias + CACHE_SEPARATEUR_PARAM
        else
            set str = .mt.label + CACHE_SEPARATEUR_PARAM
        endif
        set str = str + I2S(R2I(.x1)) + CACHE_SEPARATEUR_PARAM + I2S(R2I(.y1)) + CACHE_SEPARATEUR_PARAM
        set str = str + I2S(R2I(.x2)) + CACHE_SEPARATEUR_PARAM + I2S(R2I(.y2))
        return str
    endmethod
endstruct


endscope


//===========================================================================
// Trigger: MonsterSimplePatrolArray
//===========================================================================
//TESH.scrollpos=18
//TESH.alwaysfold=0
scope MonsterSimplePatrolArray



struct MonsterSimplePatrolArray [200000] //200 niveaux * 1000 monstres
    private MonsterSimplePatrol array monsters [MAX_NB_MONSTERS]
	private integer lastInstance
    	
	static method create takes nothing returns MonsterSimplePatrolArray
		local MonsterSimplePatrolArray ma = MonsterSimplePatrolArray.allocate()
		set ma.lastInstance = -1
		return ma
	endmethod
	
	method getFirstEmpty takes nothing returns integer
		local integer i = 0
		loop
			exitwhen (i > .lastInstance or .monsters[i] == 0)
			set i = i + 1
		endloop
		return i
	endmethod	
	
    method get takes integer arrayId returns MonsterSimplePatrol
        if (arrayId < 0 or arrayId > .lastInstance) then
            return 0
        endif
        return .monsters[arrayId]
    endmethod	
    
    method getLastInstanceId takes nothing returns integer
        return .lastInstance
    endmethod
	
    method new takes MonsterType mt, real x1, real y1, real x2, real y2, boolean createUnit returns MonsterSimplePatrol
		//local integer n = .getFirstEmpty()
        local integer n = .lastInstance + 1
		if (n >= MAX_NB_MONSTERS) then
			return 0
		endif
		//if (n > .lastInstance) then
			set .lastInstance = n
		//endif
		set .monsters[n] = MonsterSimplePatrol.create(mt, x1, y1, x2, y2)
		if (createUnit) then
			call .monsters[n].createUnit()
		endif
        set .monsters[n].level = udg_levels.getLevelFromMonsterSimplePatrolArray(this)
        set .monsters[n].arrayId = n
		return .monsters[n]  
    endmethod
	
	method count takes nothing returns integer
		local integer n = 0
		local integer i = 0
		loop
			exitwhen (i > .lastInstance)
				if (.monsters[i] != 0) then
					set n = n + 1
				endif
			set i = i + 1
		endloop
		return n
	endmethod
    
    method onDestroy takes nothing returns nothing
        local integer i = 0
        loop
            exitwhen (i > .lastInstance)
                if (.monsters[i] != 0) then
                    call .monsters[i].destroy()
                endif
            set i = i + 1
        endloop
        set .lastInstance = -1
    endmethod
    
    method setMonsterNull takes integer monsterArrayId returns nothing
        set .monsters[monsterArrayId] = 0
    endmethod
    
    method clearMonster takes integer monsterId returns boolean
        local integer i = 0
        loop
            exitwhen (.monsters[i] == MonsterSimplePatrol(monsterId) or i > .lastInstance)
            set i = i + 1
        endloop
        if (i > .lastInstance) then
            return false
        endif
        call .monsters[i].destroy()
        return true
    endmethod
    
    method getMonsterNear takes real x, real y returns MonsterSimplePatrol
        local real xMob
        local real yMob
        local integer i = 0
        loop
            exitwhen (i > .lastInstance)
                if (.monsters[i] != 0 and .monsters[i].u != null) then
                    set xMob = GetUnitX(.monsters[i].u)
                    set yMob = GetUnitY(.monsters[i].u)
                    if (RAbsBJ(x - xMob) < MONSTER_NEAR_DIFF_MAX and RAbsBJ(y - yMob) < MONSTER_NEAR_DIFF_MAX) then
                        return .monsters[i]
                    endif
                endif
            set i = i + 1
        endloop
        return 0    
    endmethod
    
    method createMonsters takes nothing returns nothing
        local integer i = 0
        loop
            exitwhen (i > .lastInstance)
                if (.monsters[i] != 0) then
                    call .monsters[i].createUnit()
                endif
            set i = i + 1
        endloop
    endmethod
    
    method removeMonsters takes nothing returns nothing
        local integer i = 0
        loop
            exitwhen (i > .lastInstance)
                if (.monsters[i] != 0) then
                    call .monsters[i].removeUnit()
                endif
            set i = i + 1
        endloop
    endmethod
    
    method recreateMonstersOfType takes MonsterType mt returns nothing
        local integer i = 0
        loop
            exitwhen (i > .lastInstance)
                if (.monsters[i] != 0 and .monsters[i].getMonsterType() == mt and .monsters[i].u != null) then
                    call .monsters[i].createUnit()
                endif
            set i = i + 1
        endloop
    endmethod
    
    method removeMonstersOfType takes MonsterType mt returns nothing
        local integer i = 0
        loop
            exitwhen (i > .lastInstance)
                if (.monsters[i] != 0 and .monsters[i].getMonsterType() == mt) then
                    call .monsters[i].destroy()
                endif
            set i = i + 1
        endloop
    endmethod
endstruct


endscope




//===========================================================================
function InitTrig_MonsterSimplePatrolArray takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: MonsterMultiplePatrols
//===========================================================================
//TESH.scrollpos=215
//TESH.alwaysfold=0
scope MonsterMultiplePatrols //extends Monster [8000]



private function NewRegion takes real x, real y returns region
    local rect r = Rect(x-16, y-16, x+16, y+16)
    local region R = CreateRegion()
    call RegionAddRect(R, r)
    call RemoveRect(r)
    set r = null
    return R
endfunction

function MonsterMultiplePatrols_move_Actions takes nothing returns nothing 
    local Monster monster
    local MonsterMultiplePatrols MMP
    if (IsHero(GetTriggerUnit())) then
        return
    endif
    set monster = Monster(GetUnitUserData(GetTriggerUnit()))
    if (monster.getType() == MonsterMultiplePatrols.typeid) then
        set MMP = MonsterMultiplePatrols(integer(monster))
        if (MMP.getCurrentTrigger() == GetTriggeringTrigger()) then
            call MMP.nextMove()
        endif
    endif
endfunction
//===========================================================


struct MonsterMultiplePatrols extends Monster
	static integer NB_MAX_LOC = 20  
    static integer nbInstances = 0 
	static real array X [20]
	static real array Y [20]
	static integer staticLastLocInd = -1
    
    static method count takes nothing returns integer
        return MonsterMultiplePatrols.nbInstances
    endmethod
	
	static method storeNewLoc takes real x, real y returns boolean //retourne true si le nouveau point a pu être stocké
		if (MonsterMultiplePatrols.staticLastLocInd >= MonsterMultiplePatrols.NB_MAX_LOC - 1) then
			return false
		endif
		set MonsterMultiplePatrols.staticLastLocInd = MonsterMultiplePatrols.staticLastLocInd + 1
		set MonsterMultiplePatrols.X[MonsterMultiplePatrols.staticLastLocInd] = x
		set MonsterMultiplePatrols.Y[MonsterMultiplePatrols.staticLastLocInd] = y	
		return true
	endmethod
    
    static method destroyLocs takes nothing returns nothing
        set MonsterMultiplePatrols.staticLastLocInd = -1
    endmethod
    
    
    
    unit u
    private MonsterType mt
    
	private integer lastLocInd
	private integer currentMove
    private integer sens //0 : normal toujours positif, 1 : sens normal avec changement, 2 : sens inversé avec changement
    
    //! textmacro MMP_Variables takes N
	private real x$N$
	private real y$N$
	private region r$N$
	trigger t$N$
	//! endtextmacro
	//! runtextmacro MMP_Variables( "0"  )
	//! runtextmacro MMP_Variables( "1"  )
	//! runtextmacro MMP_Variables( "2"  )
	//! runtextmacro MMP_Variables( "3"  )
	//! runtextmacro MMP_Variables( "4"  )
	//! runtextmacro MMP_Variables( "5"  )
	//! runtextmacro MMP_Variables( "6"  )
	//! runtextmacro MMP_Variables( "7"  )
	//! runtextmacro MMP_Variables( "8"  )
	//! runtextmacro MMP_Variables( "9"  )
	//! runtextmacro MMP_Variables( "10" )
	//! runtextmacro MMP_Variables( "11" )
	//! runtextmacro MMP_Variables( "12" )
	//! runtextmacro MMP_Variables( "13" )
	//! runtextmacro MMP_Variables( "14" )
	//! runtextmacro MMP_Variables( "15" )
	//! runtextmacro MMP_Variables( "16" )
	//! runtextmacro MMP_Variables( "17" )
	//! runtextmacro MMP_Variables( "18" )
	//! runtextmacro MMP_Variables( "19" )
    trigger currentTrigger
    
    method getCurrentTrigger takes nothing returns trigger
        return .currentTrigger
    endmethod
	
	method removeUnit takes nothing returns nothing
        if (.u != null) then
            call GroupRemoveUnit(monstersClickable, .u)
            call RemoveUnit(.u)
            set .u = null
        endif
	endmethod
    
    method killUnit takes nothing returns nothing
        if (.u != null and IsUnitAliveBJ(.u)) then
            call KillUnit(.u)
        endif
    endmethod
    
    private method onDestroy takes nothing returns nothing
        loop
            exitwhen (not .destroyLastLoc())
        endloop
		if (.u != null) then
			call .removeUnit()
		endif
        call .level.monstersMultiplePatrols.setMonsterNull(.arrayId)
        set MonsterMultiplePatrols.nbInstances = MonsterMultiplePatrols.nbInstances - 1
    endmethod
	
	method disableTrigger takes integer id returns nothing
	//! textmacro MMP_disableTrigger takes N
	if (id == $N$) then
		call DisableTrigger(.t$N$)
		return
	endif
	//! endtextmacro
	//! runtextmacro MMP_disableTrigger( "0"  )
	//! runtextmacro MMP_disableTrigger( "1"  )
	//! runtextmacro MMP_disableTrigger( "2"  )
	//! runtextmacro MMP_disableTrigger( "3"  )
	//! runtextmacro MMP_disableTrigger( "4"  )
	//! runtextmacro MMP_disableTrigger( "5"  )
	//! runtextmacro MMP_disableTrigger( "6"  )
	//! runtextmacro MMP_disableTrigger( "7"  )
	//! runtextmacro MMP_disableTrigger( "8"  )
	//! runtextmacro MMP_disableTrigger( "9"  )
	//! runtextmacro MMP_disableTrigger( "10" )
	//! runtextmacro MMP_disableTrigger( "11" )
	//! runtextmacro MMP_disableTrigger( "12" )
	//! runtextmacro MMP_disableTrigger( "13" )
	//! runtextmacro MMP_disableTrigger( "14" )
	//! runtextmacro MMP_disableTrigger( "15" )
	//! runtextmacro MMP_disableTrigger( "16" )
	//! runtextmacro MMP_disableTrigger( "17" )
	//! runtextmacro MMP_disableTrigger( "18" )
	//! runtextmacro MMP_disableTrigger( "19" )
	endmethod
	
	method activateMove takes integer id returns nothing
	//! textmacro MMP_activateMove takes N
	if (id == $N$) then
		call EnableTrigger(.t$N$)
        set .currentTrigger = .t$N$
		call IssuePointOrder(.u, "move", .x$N$, .y$N$)
		return
	endif
	//! endtextmacro
	//! runtextmacro MMP_activateMove( "0"  )
	//! runtextmacro MMP_activateMove( "1"  )
	//! runtextmacro MMP_activateMove( "2"  )
	//! runtextmacro MMP_activateMove( "3"  )
	//! runtextmacro MMP_activateMove( "4"  )
	//! runtextmacro MMP_activateMove( "5"  )
	//! runtextmacro MMP_activateMove( "6"  )
	//! runtextmacro MMP_activateMove( "7"  )
	//! runtextmacro MMP_activateMove( "8"  )
	//! runtextmacro MMP_activateMove( "9"  )
	//! runtextmacro MMP_activateMove( "10" )
	//! runtextmacro MMP_activateMove( "11" )
	//! runtextmacro MMP_activateMove( "12" )
	//! runtextmacro MMP_activateMove( "13" )
	//! runtextmacro MMP_activateMove( "14" )
	//! runtextmacro MMP_activateMove( "15" )
	//! runtextmacro MMP_activateMove( "16" )
	//! runtextmacro MMP_activateMove( "17" )
	//! runtextmacro MMP_activateMove( "18" )
	//! runtextmacro MMP_activateMove( "19" )
	endmethod
	
	method nextMove takes nothing returns nothing
		call .disableTrigger(.currentMove)
        if (.sens == 0 or .sens == 1) then
       		if (.currentMove >= .lastLocInd) then
                if (.sens == 0) then
                    set .currentMove = 0
                else
                    set .sens = 2
                    set .currentMove = .currentMove - 1
                endif
            else
                set .currentMove = .currentMove + 1
            endif
        else //sens == 2
            if (.currentMove <= 0) then
                set .sens = 1
                set .currentMove = 1
            else
                set .currentMove = .currentMove - 1
            endif
        endif   
		call .activateMove(.currentMove)
	endmethod
	
	static method create takes MonsterType mt, string mode returns MonsterMultiplePatrols
        //mode == "normal" (0, 1, 2, 3, 0 , 1...) ou mode == "string" (0, 1, 2, 3, 2, 1...)
		local MonsterMultiplePatrols m
		local integer i
		
        if (mode != "normal" and mode != "string") then
            return 0
        endif
        
        set m = MonsterMultiplePatrols.allocate()
        set MonsterMultiplePatrols.nbInstances = MonsterMultiplePatrols.nbInstances + 1	
        set m.mt = mt
        if (mode == "normal") then
            set m.sens = 0
        else
            set m.sens = 1
        endif
		
		//! textmacro MMP_create takes N
		if ($N$ <= MonsterMultiplePatrols.staticLastLocInd) then
			set m.x$N$ = MonsterMultiplePatrols.X[$N$]
			set m.y$N$ = MonsterMultiplePatrols.Y[$N$]
			set m.r$N$ = NewRegion(m.x$N$, m.y$N$)
			set m.t$N$ = CreateTrigger()
			call DisableTrigger(m.t$N$)
			call TriggerAddAction(m.t$N$, function MonsterMultiplePatrols_move_Actions)
			call TriggerRegisterEnterRegionSimple(m.t$N$, m.r$N$)
		endif
		//! endtextmacro
		//! runtextmacro MMP_create( "0"  )
		//! runtextmacro MMP_create( "1"  )
		//! runtextmacro MMP_create( "2"  )
		//! runtextmacro MMP_create( "3"  )
		//! runtextmacro MMP_create( "4"  )
		//! runtextmacro MMP_create( "5"  )
		//! runtextmacro MMP_create( "6"  )
		//! runtextmacro MMP_create( "7"  )
		//! runtextmacro MMP_create( "8"  )
		//! runtextmacro MMP_create( "9"  )
		//! runtextmacro MMP_create( "10" )
		//! runtextmacro MMP_create( "11" )
		//! runtextmacro MMP_create( "12" )
		//! runtextmacro MMP_create( "13" )
		//! runtextmacro MMP_create( "14" )
		//! runtextmacro MMP_create( "15" )
		//! runtextmacro MMP_create( "16" )
		//! runtextmacro MMP_create( "17" )
		//! runtextmacro MMP_create( "18" )
		//! runtextmacro MMP_create( "19" )
		
		set m.lastLocInd = MonsterMultiplePatrols.staticLastLocInd
        //call Text_A("test, lastLocInd == " + I2S(m.lastLocInd))
		set m.currentMove = -1
		call MonsterMultiplePatrols.destroyLocs()
        set m.life = 0
		return m
	endmethod
	
	method createUnit takes nothing returns nothing
        if (.u != null) then
            call .removeUnit()
        endif
		if (.lastLocInd <= 0) then
			return
		endif
		set .u = NewPatrolMonster(.mt, .x0, .y0, .x1, .y1)
        call SetUnitUserData(.u, integer(this))
        set .currentMove = 1
        if (.sens == 2) then
            set .sens = 1
        endif
        call EnableTrigger(.t1)
        set .currentTrigger = .t1
        if (.mt.isClickable()) then
            set .life = .mt.getMaxLife()
            call GroupAddUnit(monstersClickable, .u)
        endif
	endmethod
	
    method getLife takes nothing returns integer
        return .life
    endmethod
    
    method setLife takes integer life returns nothing
        set .life = life
        if (life > 0) then
            call SetUnitLifeBJ(.u, I2R(life) - 0.5)
        else
            call .killUnit()
        endif
    endmethod
    
    method getX takes integer id returns real
        //! textmacro MMP_getX takes N
        if (id == $N$) then
            return .x$N$
        endif
        //! endtextmacro
		//! runtextmacro MMP_getX( "0"  )
		//! runtextmacro MMP_getX( "1"  )
		//! runtextmacro MMP_getX( "2"  )
		//! runtextmacro MMP_getX( "3"  )
		//! runtextmacro MMP_getX( "4"  )
		//! runtextmacro MMP_getX( "5"  )
		//! runtextmacro MMP_getX( "6"  )
		//! runtextmacro MMP_getX( "7"  )
		//! runtextmacro MMP_getX( "8"  )
		//! runtextmacro MMP_getX( "9"  )
		//! runtextmacro MMP_getX( "10" )
		//! runtextmacro MMP_getX( "11" )
		//! runtextmacro MMP_getX( "12" )
		//! runtextmacro MMP_getX( "13" )
		//! runtextmacro MMP_getX( "14" )
		//! runtextmacro MMP_getX( "15" )
		//! runtextmacro MMP_getX( "16" )
		//! runtextmacro MMP_getX( "17" )
		//! runtextmacro MMP_getX( "18" )
		//! runtextmacro MMP_getX( "19" )
        return 0.    
    endmethod
    
    method getY takes integer id returns real
        //! textmacro MMP_getY takes N
        if (id == $N$) then
            return .y$N$
        endif
        //! endtextmacro
		//! runtextmacro MMP_getY( "0"  )
		//! runtextmacro MMP_getY( "1"  )
		//! runtextmacro MMP_getY( "2"  )
		//! runtextmacro MMP_getY( "3"  )
		//! runtextmacro MMP_getY( "4"  )
		//! runtextmacro MMP_getY( "5"  )
		//! runtextmacro MMP_getY( "6"  )
		//! runtextmacro MMP_getY( "7"  )
		//! runtextmacro MMP_getY( "8"  )
		//! runtextmacro MMP_getY( "9"  )
		//! runtextmacro MMP_getY( "10" )
		//! runtextmacro MMP_getY( "11" )
		//! runtextmacro MMP_getY( "12" )
		//! runtextmacro MMP_getY( "13" )
		//! runtextmacro MMP_getY( "14" )
		//! runtextmacro MMP_getY( "15" )
		//! runtextmacro MMP_getY( "16" )
		//! runtextmacro MMP_getY( "17" )
		//! runtextmacro MMP_getY( "18" )
		//! runtextmacro MMP_getY( "19" )
        return 0.    
    endmethod
    
    method destroyLastLoc takes nothing returns boolean
		if (.lastLocInd == 1) then
            call DisableTrigger(.t0)
			call DestroyTrigger(.t1)
			set .t1 = null
			call RemoveRegion(.r1)
			set .r1 = null
			call RemoveUnit(.u)
			set .u = null
		endif
        //! textmacro MMP_destroyLastLoc takes N
        if (.lastLocInd == $N$) then
            call DestroyTrigger(.t$N$)
            set .t$N$ = null
            call RemoveRegion(.r$N$)
            set .r$N$ = null
            if ($N$ == .currentMove) then
                set .currentMove = .currentMove - 1
                call .activateMove(.currentMove)
            endif
        endif
        //! endtextmacro
		//! runtextmacro MMP_destroyLastLoc( "0"  )
		//! runtextmacro MMP_destroyLastLoc( "2"  )
		//! runtextmacro MMP_destroyLastLoc( "3"  )
		//! runtextmacro MMP_destroyLastLoc( "4"  )
		//! runtextmacro MMP_destroyLastLoc( "5"  )
		//! runtextmacro MMP_destroyLastLoc( "6"  )
		//! runtextmacro MMP_destroyLastLoc( "7"  )
		//! runtextmacro MMP_destroyLastLoc( "8"  )
		//! runtextmacro MMP_destroyLastLoc( "9"  )
		//! runtextmacro MMP_destroyLastLoc( "10" )
		//! runtextmacro MMP_destroyLastLoc( "11" )
		//! runtextmacro MMP_destroyLastLoc( "12" )
		//! runtextmacro MMP_destroyLastLoc( "13" )
		//! runtextmacro MMP_destroyLastLoc( "14" )
		//! runtextmacro MMP_destroyLastLoc( "15" )
		//! runtextmacro MMP_destroyLastLoc( "16" )
		//! runtextmacro MMP_destroyLastLoc( "17" )
		//! runtextmacro MMP_destroyLastLoc( "18" )
		//! runtextmacro MMP_destroyLastLoc( "19" )
        if (.lastLocInd < 0) then
            return false
        endif
        set .lastLocInd = .lastLocInd - 1
        return true
    endmethod
	
	method addNewLocAt takes integer id, real x, real y returns nothing
		//! textmacro MMP_addNewLocAt takes N
		if (id == $N$) then
			set .x$N$ = x
			set .y$N$ = y
			set .r$N$ = NewRegion(x, y)
			set .t$N$ = CreateTrigger()
			call DisableTrigger(.t$N$)
			call TriggerAddAction(.t$N$, function MonsterMultiplePatrols_move_Actions)
			call TriggerRegisterEnterRegionSimple(.t$N$, .r$N$)
			return
		endif
		//! endtextmacro
		//! runtextmacro MMP_addNewLocAt( "0"  )
		//! runtextmacro MMP_addNewLocAt( "1"  )
		//! runtextmacro MMP_addNewLocAt( "2"  )
		//! runtextmacro MMP_addNewLocAt( "3"  )
		//! runtextmacro MMP_addNewLocAt( "4"  )
		//! runtextmacro MMP_addNewLocAt( "5"  )
		//! runtextmacro MMP_addNewLocAt( "6"  )
		//! runtextmacro MMP_addNewLocAt( "7"  )
		//! runtextmacro MMP_addNewLocAt( "8"  )
		//! runtextmacro MMP_addNewLocAt( "9"  )
		//! runtextmacro MMP_addNewLocAt( "10" )
		//! runtextmacro MMP_addNewLocAt( "11" )
		//! runtextmacro MMP_addNewLocAt( "12" )
		//! runtextmacro MMP_addNewLocAt( "13" )
		//! runtextmacro MMP_addNewLocAt( "14" )
		//! runtextmacro MMP_addNewLocAt( "15" )
		//! runtextmacro MMP_addNewLocAt( "16" )
		//! runtextmacro MMP_addNewLocAt( "17" )
		//! runtextmacro MMP_addNewLocAt( "18" )
		//! runtextmacro MMP_addNewLocAt( "19" )
	endmethod
	
	method addNewLoc takes real x, real y returns integer
        if (.lastLocInd >= MonsterMultiplePatrols.NB_MAX_LOC - 1) then //nombre limite de points atteint
			return 3 //erreur 3
		endif
        if (GetLocDist(.getX(.lastLocInd), .getY(.lastLocInd), x, y) <= PATROL_DISTANCE_MIN) then
            return 2 //erreur 2
        endif
        if (.sens == 0 and GetLocDist(.x0, .y0, x, y) <= PATROL_DISTANCE_MIN) then
            return 1 //erreur 1
        endif
		set .lastLocInd = .lastLocInd + 1
		call .addNewLocAt(.lastLocInd, x, y)
		if (.lastLocInd == 1) then
            call .createUnit()
		endif
		return 0 //c'est bon, pas d'erreur
	endmethod   	
    
    method getMonsterType takes nothing returns MonsterType
        return .mt
    endmethod
    
    method toString takes nothing returns string
        local string str
        if (.mt.alias != null and .mt.alias != "") then
            set str = .mt.alias + CACHE_SEPARATEUR_PARAM
        else
            set str = .mt.label + CACHE_SEPARATEUR_PARAM
        endif
        if (.sens > 0) then
            set str = str + "string"
        else
            set str = str + "normal"
        endif
        //! textmacro MMP_loc_toString takes N
        if (.lastLocInd < $N$) then
            return str
        endif
        set str = str + CACHE_SEPARATEUR_PARAM + I2S(R2I(.x$N$)) + CACHE_SEPARATEUR_PARAM + I2S(R2I(.y$N$))
        //! endtextmacro
		//! runtextmacro MMP_loc_toString( "0"  )
		//! runtextmacro MMP_loc_toString( "1"  )
		//! runtextmacro MMP_loc_toString( "2"  )
		//! runtextmacro MMP_loc_toString( "3"  )
		//! runtextmacro MMP_loc_toString( "4"  )
		//! runtextmacro MMP_loc_toString( "5"  )
		//! runtextmacro MMP_loc_toString( "6"  )
		//! runtextmacro MMP_loc_toString( "7"  )
		//! runtextmacro MMP_loc_toString( "8"  )
		//! runtextmacro MMP_loc_toString( "9"  )
		//! runtextmacro MMP_loc_toString( "10" )
		//! runtextmacro MMP_loc_toString( "11" )
		//! runtextmacro MMP_loc_toString( "12" )
		//! runtextmacro MMP_loc_toString( "13" )
		//! runtextmacro MMP_loc_toString( "14" )
		//! runtextmacro MMP_loc_toString( "15" )
		//! runtextmacro MMP_loc_toString( "16" )
		//! runtextmacro MMP_loc_toString( "17" )
		//! runtextmacro MMP_loc_toString( "18" )
		//! runtextmacro MMP_loc_toString( "19" )
        return str
    endmethod
endstruct



endscope





//===========================================================================
function InitTrig_MonsterMultiplePatrols takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: MonsterMultiplePatrolsArray
//===========================================================================
//TESH.scrollpos=15
//TESH.alwaysfold=0
scope MonsterMultiplePatrolsArray


struct MonsterMultiplePatrolsArray [200000] //200 niveaux * 1000 monstres
    private MonsterMultiplePatrols array monsters [MAX_NB_MONSTERS]
	private integer lastInstance
	
	static method create takes nothing returns MonsterMultiplePatrolsArray
		local MonsterMultiplePatrolsArray ma = MonsterMultiplePatrolsArray.allocate()
		set ma.lastInstance = -1
		return ma
	endmethod
	
	method getFirstEmpty takes nothing returns integer
		local integer i = 0
		loop
			exitwhen (i > .lastInstance or .monsters[i] == 0)
			set i = i + 1
		endloop
		return i
	endmethod	
	
    method get takes integer arrayId returns MonsterMultiplePatrols
        if (arrayId < 0 or arrayId > .lastInstance) then
            return 0
        endif
        return .monsters[arrayId]
    endmethod
    
    method getLastInstanceId takes nothing returns integer
        return .lastInstance
    endmethod	
	
    method new takes MonsterType mt, string mode, boolean createUnit returns MonsterMultiplePatrols
		local integer n
        if (mode != "normal" and mode != "string") then
            return 0
        endif
        //set n = .getFirstEmpty()
        set n = .lastInstance + 1
		if (n >= MAX_NB_MONSTERS) then
			return 0
		endif
		//if (n > .lastInstance) then
			set .lastInstance = n
		//endif
		set .monsters[n] = MonsterMultiplePatrols.create(mt, mode)
        if (createUnit) then
            call .monsters[n].createUnit()
        endif
        set .monsters[n].level = udg_levels.getLevelFromMonsterMultiplePatrolsArray(this)
        set .monsters[n].arrayId = n
		return .monsters[n]   
    endmethod	
	
	method count takes nothing returns integer
		local integer n = 0
		local integer i = 0
		loop
			exitwhen (i > .lastInstance)
				if (.monsters[i] != 0) then
					set n = n + 1
				endif
			set i = i + 1
		endloop
		return n
	endmethod
    
    method onDestroy takes nothing returns nothing
        local integer i = 0
        loop
            exitwhen (i > .lastInstance)
                if (.monsters[i] != 0) then
                    call .monsters[i].destroy()
                endif
            set i = i + 1
        endloop
        set .lastInstance = -1
    endmethod
    
    method setMonsterNull takes integer monsterArrayId returns nothing
        set .monsters[monsterArrayId] = 0
    endmethod

    method clearMonster takes integer monsterId returns boolean
        local integer i = 0
        loop
            exitwhen (.monsters[i] == MonsterMultiplePatrols(monsterId) or i > .lastInstance)
            set i = i + 1
        endloop
        if (i > .lastInstance) then
            return false
        endif
        call .monsters[i].destroy()
        return true
    endmethod
    
    method getMonsterNear takes real x, real y returns MonsterMultiplePatrols
        local real xMob
        local real yMob
        local integer i = 0
        loop
            exitwhen (i > .lastInstance)
                if (.monsters[i] != 0 and .monsters[i].u != null) then
                    set xMob = GetUnitX(.monsters[i].u)
                    set yMob = GetUnitY(.monsters[i].u)
                    if (RAbsBJ(x - xMob) < MONSTER_NEAR_DIFF_MAX and RAbsBJ(y - yMob) < MONSTER_NEAR_DIFF_MAX) then
                        return .monsters[i]
                    endif
                endif
            set i = i + 1
        endloop
        return 0    
    endmethod
    
    method createMonsters takes nothing returns nothing
        local integer i = 0
        loop
            exitwhen (i > .lastInstance)
                if (.monsters[i] != 0) then
                    call .monsters[i].createUnit()
                endif
            set i = i + 1
        endloop
    endmethod
    
    method removeMonsters takes nothing returns nothing
        local integer i = 0
        loop
            exitwhen (i > .lastInstance)
                if (.monsters[i] != 0) then
                    call .monsters[i].removeUnit()
                endif
            set i = i + 1
        endloop
    endmethod
    
    method recreateMonstersOfType takes MonsterType mt returns nothing
        local integer i = 0
        loop
            exitwhen (i > .lastInstance)
                if (.monsters[i] != 0 and .monsters[i].getMonsterType() == mt and .monsters[i].u != null) then
                    call .monsters[i].createUnit()
                endif
            set i = i + 1
        endloop
    endmethod
    
    method removeMonstersOfType takes MonsterType mt returns nothing
        local integer i = 0
        loop
            exitwhen (i > .lastInstance)
                if (.monsters[i] != 0 and .monsters[i].getMonsterType() == mt) then
                    call .monsters[i].destroy()
                endif
            set i = i + 1
        endloop
    endmethod
endstruct


endscope




//===========================================================================
function InitTrig_MonsterMultiplePatrolsArray takes nothing returns nothing
endfunction



endlibrary//===========================================================================
// Trigger: MonsterSpawn
//===========================================================================
//TESH.scrollpos=177
//TESH.alwaysfold=0
scope MonsterSpawn


private function RemoveEnumMonster takes nothing returns nothing
    call RemoveUnit(GetEnumUnit())
endfunction

globals
    private hashtable ht //pour retrouver les MonsterSpawn correspondant aux triggers et régions
    private constant real DECALAGE_UNSPAWN = 200 //décalage de l'ordre de déplacement au delà de la région d'unspawn
    private constant real DELAY_BETWEEN_SPAWN_AND_MOVEMENT = 0.5
endglobals

private function MonsterStartMovement takes nothing returns nothing
    local timer mobTimer = GetExpiredTimer()
    local MonsterSpawn ms = MonsterSpawn(LoadInteger(ht, 1, GetHandleId(mobTimer)))
    local unit mobUnit = LoadUnitHandle(ht, 2, GetHandleId(mobTimer))
    call ms.startMobMovement(mobUnit)
    call UnitAddAbility(mobUnit, 'Aloc')
    call DestroyTimer(mobTimer)
    set mobUnit = null
    set mobTimer = null
endfunction    

private function MonsterSpawn_Actions takes nothing returns nothing
    local MonsterSpawn ms = MonsterSpawn(LoadInteger(ht, 0, GetHandleId(GetTriggeringTrigger())))
    local unit mobUnit = ms.createMob()
    local timer mobTimer = CreateTimer()
    call SaveInteger(ht, 1, GetHandleId(mobTimer), integer(ms))
    call SaveUnitHandle(ht, 2, GetHandleId(mobTimer), mobUnit)
    call TimerStart(mobTimer, DELAY_BETWEEN_SPAWN_AND_MOVEMENT, false, function MonsterStartMovement)
    call SetUnitOwner(mobUnit, ENNEMY_PLAYER, false)
    call ShowUnit(mobUnit, false)
    call UnitRemoveAbility(mobUnit, 'Aloc')
    call GroupAddUnit(ms.monsters, mobUnit)
    set mobUnit = null
    set mobTimer = null
endfunction

private function UnspawMonster_Actions takes nothing returns nothing
    local MonsterSpawn ms = MonsterSpawn(LoadInteger(ht, 0, GetHandleId(GetTriggeringTrigger())))
    if(IsUnitInGroup(GetTriggerUnit(), ms.monsters))then
        call GroupRemoveUnit(ms.monsters, GetTriggerUnit())
        call RemoveUnit(GetTriggerUnit())
    endif
endfunction
    


struct MonsterSpawn
    private static method onInit takes nothing returns nothing
        set ht = InitHashtable()
        //0, tSpawn --> MonsterSpawn
        //0, tUnspawn --> MonsterSpawn
        //1, timer --> MonsterSpawn
        //2, timer --> unité mob
    endmethod
    
    private string label
    private MonsterType mt
    private string sens //leftToRight, upToDown, rightToLeft, downToUp
    private real frequence
    private real minX
    private real minY
    private real maxX
    private real maxY
    private trigger tSpawn
    private trigger tUnspawn
    private region unspawnReg
    group monsters
    
    Level level
    integer arrayId
    
    
    public method getLabel takes nothing returns string
        return .label
    endmethod
    
    
    method desactivate takes nothing returns nothing
		if(.unspawnReg != null)then
            call RemoveRegion(.unspawnReg)
            set .unspawnReg = null
        endif
        if(.tSpawn != null)then
            call DestroyTrigger(.tSpawn)
            set .tSpawn = null
        endif
        if(.tUnspawn != null)then
            call DestroyTrigger(.tUnspawn)
            set .tUnspawn = null
        endif
        if(.monsters != null)then
            call ForGroup(.monsters, function RemoveEnumMonster)
            call DestroyGroup(.monsters)
            set .monsters = null
        endif
    endmethod
    
    private method createUnspawnReg takes nothing returns nothing
        local rect r
        local real x1
        local real y1
        local real x2
        local real y2
        //leftToRight, upToDown, rightToLeft, downToUp
        if(.sens == "leftToRight")then
            set x1 = .maxX
            set x2 = .maxX
            set y1 = .minY - DECALAGE_UNSPAWN
            set y2 = .maxY + DECALAGE_UNSPAWN
        elseif(.sens == "upToDown")then
            set x1 = .minX - DECALAGE_UNSPAWN
            set x2 = .maxX + DECALAGE_UNSPAWN
            set y1 = .minY
            set y2 = .minY
        elseif(.sens == "rightToLeft")then
            set x1 = .minX
            set x2 = .minX
            set y1 = .minY - DECALAGE_UNSPAWN
            set y2 = .maxY + DECALAGE_UNSPAWN
        else //downToUp
            set x1 = .minX - DECALAGE_UNSPAWN
            set x2 = .maxX + DECALAGE_UNSPAWN
            set y1 = .maxY
            set y2 = .maxY
        endif
        set r = Rect(x1, y1, x2, y2)
        set .unspawnReg = CreateRegion()
        call RegionAddRect(.unspawnReg, r)
        call RemoveRect(r)
    endmethod
    
    method activate takes nothing returns nothing
        set .monsters = CreateGroup()
        set .tSpawn = CreateTrigger()
        call SaveInteger(ht, 0, GetHandleId(.tSpawn), integer(this))
        call TriggerRegisterTimerEvent(.tSpawn, 1/.frequence, true)
        call TriggerAddAction(.tSpawn, function MonsterSpawn_Actions)
        call .createUnspawnReg()
        set .tUnspawn = CreateTrigger()
        call SaveInteger(ht, 0, GetHandleId(.tUnspawn), integer(this))
        call TriggerRegisterEnterRegion(.tUnspawn, .unspawnReg, null)
        call TriggerAddAction(.tUnspawn, function UnspawMonster_Actions)
    endmethod
    
    private method onDestroy takes nothing returns nothing
        call .desactivate()
        call .level.monsterSpawns.setMonsterSpawnNull(.arrayId)
    endmethod
	
	static method create takes string label, MonsterType mt, string sens, real frequence, real x1, real y1, real x2, real y2 returns MonsterSpawn
		local MonsterSpawn ms = MonsterSpawn.allocate()
        set ms.label = label
        set ms.mt = mt
        set ms.sens = sens
        set ms.frequence = frequence
        set ms.minX = RMinBJ(x1, x2)
        set ms.minY = RMinBJ(y1, y2)
        set ms.maxX = RMaxBJ(x1, x2)
        set ms.maxY = RMaxBJ(y1, y2)
		return ms
	endmethod
    
    method startMobMovement takes unit mobUnit returns nothing
        local player p
        local real x1
        local real y1
        local real x2
        local real y2
        //leftToRight, upToDown, rightToLeft, downToUp
        if(.sens == "leftToRight")then
            set x1 = .minX
            set x2 = .maxX + DECALAGE_UNSPAWN
            set y1 = GetRandomReal(.minY, .maxY)
            set y2 = y1
        elseif(.sens == "upToDown")then
            set x1 = GetRandomReal(.minX, .maxX)
            set x2 = x1
            set y1 = .maxY
            set y2 = .minY - DECALAGE_UNSPAWN
        elseif(.sens == "rightToLeft")then
            set x1 = .maxX
            set x2 = .minX - DECALAGE_UNSPAWN
            set y1 = GetRandomReal(.minY, .maxY)
            set y2 = y1
        else //downToUp
            set x1 = GetRandomReal(.minX, .maxX)
            set x2 = x1
            set y1 = .minY
            set y2 = .maxY + DECALAGE_UNSPAWN
        endif
        call SetUnitX(mobUnit, x1)
        call SetUnitY(mobUnit, y1)
        if (udg_monsterTypes.monsterUnit2MonsterType(mobUnit).isClickable()) then
            set p = ENNEMY_PLAYER
        else
            set p = GetCurrentMonsterPlayer()
        endif
        call SetUnitOwner(mobUnit, p, false)
        call ShowUnit(mobUnit, true)
        call IssuePointOrder(mobUnit, "move", x2, y2)
    endmethod
    
    public method createMob takes nothing returns unit
        local real angle
        //leftToRight, upToDown, rightToLeft, downToUp
        if(.sens == "leftToRight")then
            set angle = 180
        elseif(.sens == "upToDown")then
            set angle = 90
        elseif(.sens == "rightToLeft")then
            set angle = 0
        else //downToUp
            set angle = -90
        endif
        return NewImmobileMonsterForPlayer(.mt, ENNEMY_PLAYER, (.minX + .maxX)/2, (minY + .maxY)/2, angle)
    endmethod
    
    public method setLabel takes string newLabel returns nothing
        set .label = newLabel
    endmethod

    public method setMonsterType takes MonsterType mt returns nothing
        set .mt = mt
    endmethod
    
    public method setSens takes string sens returns nothing
        set .sens = sens
        call .desactivate()
        call .activate()
    endmethod
    
    public method setFrequence takes real frequence returns nothing
        set .frequence = frequence
        call DestroyTrigger(.tSpawn)
        set .tSpawn = CreateTrigger()
        call SaveInteger(ht, 0, GetHandleId(.tSpawn), integer(this))
        call TriggerRegisterTimerEvent(.tSpawn, 1/.frequence, true)
        call TriggerAddAction(.tSpawn, function MonsterSpawn_Actions)
    endmethod
    
    public method displayForPlayer takes player p returns nothing
        local string display = udg_colorCode[GREY] + .label + " : " + .mt.label + "   " + sens + "   " + R2S(frequence)
        call Text_P_timed(p, TERRAIN_DATA_DISPLAY_TIME, display)
    endmethod

    public method toString takes nothing returns string
        local string str = .label + CACHE_SEPARATEUR_PARAM
        if (.mt.alias != null and .mt.alias != "") then
            set str = str + .mt.alias + CACHE_SEPARATEUR_PARAM
        else
            set str = str + .mt.label + CACHE_SEPARATEUR_PARAM
        endif
        set str = str + .sens + CACHE_SEPARATEUR_PARAM + R2S(.frequence) + CACHE_SEPARATEUR_PARAM
        set str = str + I2S(R2I(.minX)) + CACHE_SEPARATEUR_PARAM + I2S(R2I(minY)) + CACHE_SEPARATEUR_PARAM + I2S(R2I(.maxX)) + CACHE_SEPARATEUR_PARAM + I2S(R2I(.maxY))
        return str
    endmethod

endstruct


endscope//===========================================================================
// Trigger: MonsterSpawnArray
//===========================================================================
//TESH.scrollpos=39
//TESH.alwaysfold=0
scope MonsterSpawnArray


struct MonsterSpawnArray [20000] //200 levels * 100 monster spawns
    private MonsterSpawn array monsterSpawns[100]
	private integer lastInstance
	
	static method create takes nothing returns MonsterSpawnArray
		local MonsterSpawnArray msa = MonsterSpawnArray.allocate()
		set msa.lastInstance = -1
		return msa
	endmethod
	
	method getFirstEmpty takes nothing returns integer
		local integer i = 0
		loop
			exitwhen (i > .lastInstance or .monsterSpawns[i] == 0)
			set i = i + 1
		endloop
		return i
	endmethod	
	
    method get takes integer arrayId returns MonsterSpawn
        if (arrayId < 0 or arrayId > .lastInstance) then
            return 0
        endif
        return .monsterSpawns[arrayId]
    endmethod
    
    method getFromLabel takes string label returns MonsterSpawn
		local integer i = 0
		loop
			exitwhen (i > .lastInstance)
				if (.monsterSpawns[i].getLabel() == label) then
					return .monsterSpawns[i]
				endif
			set i = i + 1
		endloop
		return 0
	endmethod
    
    method getLastInstanceId takes nothing returns integer
        return .lastInstance
    endmethod
	
    method new takes string label, MonsterType mt, string sens, real frequence, real x1, real y1, real x2, real y2, boolean activate returns MonsterSpawn //retourne le monsterSpawn s'il a pu être créé, 0 sinon
		//local integer n = .getFirstEmpty()
        local integer n = .lastInstance + 1
		if (n >= MAX_NB_MONSTERS) then
			return 0
		endif
        if(.getFromLabel(label) != 0)then
            return 0
        endif
		//if (n > .lastInstance) then
			set .lastInstance = n
		//endif
        set .monsterSpawns[n] = MonsterSpawn.create(label, mt, sens, frequence, x1, y1, x2, y2)
        if(activate)then
            call .monsterSpawns[n].activate()
        endif
        set .monsterSpawns[n].level = udg_levels.getLevelFromMonsterSpawnArray(this)
        set .monsterSpawns[n].arrayId = n
		return .monsterSpawns[n]   
    endmethod
    
    method count takes nothing returns integer
		local integer n = 0
		local integer i = 0
		loop
			exitwhen (i > .lastInstance)
				if (.monsterSpawns[i] != 0) then
					set n = n + 1
				endif
			set i = i + 1
		endloop
		return n
	endmethod
    
    method onDestroy takes nothing returns nothing
        local integer i = 0
        loop
            exitwhen (i > .lastInstance)
                if (.monsterSpawns[i] != 0) then
                    call .monsterSpawns[i].destroy()
                endif
            set i = i + 1
        endloop
        set .lastInstance = -1
    endmethod
    
    method setMonsterSpawnNull takes integer monsterSpawnArrayId returns nothing
        set .monsterSpawns[monsterSpawnArrayId] = 0
    endmethod
    
    method clearMonsterSpawn takes string label returns boolean
        local MonsterSpawn ms = .getFromLabel(label)
        if(ms != 0)then
            call ms.destroy()
            set ms = 0
            return true
        else
            return false
        endif
    endmethod
    
    public method setMonsterType takes string label, MonsterType mt returns boolean
        local MonsterSpawn ms = .getFromLabel(label)
        if(ms == 0)then
            return false
        endif
        call ms.setMonsterType(mt)
        return true
    endmethod
    
    public method setSens takes string label, string sens returns boolean
        local MonsterSpawn ms = .getFromLabel(label)
        if(ms == 0)then
            return false
        endif
        call ms.setSens(sens)
        return true
    endmethod
    
    public method setFrequence takes string label, real frequence returns boolean
        local MonsterSpawn ms = .getFromLabel(label)
        if(ms == 0)then
            return false
        endif
        call ms.setFrequence(frequence)
        return true
    endmethod
    
    public method activate takes nothing returns nothing
        local integer i = 0
        loop
            exitwhen i > .lastInstance
                if(.monsterSpawns[i] != 0)then
                    call .monsterSpawns[i].activate()
                endif
            set i = i + 1
        endloop
    endmethod
    
    public method desactivate takes nothing returns nothing
        local integer i = 0
        loop
            exitwhen i > .lastInstance
                if(.monsterSpawns[i] != 0)then
                    call .monsterSpawns[i].desactivate()
                endif
            set i = i + 1
        endloop
    endmethod
    
    method displayForPlayer takes player p returns nothing
        local integer nbMs = 0
        local integer i = 0
        loop
            exitwhen (i > .lastInstance)
                if(.monsterSpawns[i] != 0)then
                    call .monsterSpawns[i].displayForPlayer(p)
                    set nbMs = nbMs + 1
                endif
            set i = i + 1
        endloop
        if (nbMs == 0) then
            call Text_erP(p, "no monster spawn for this level")
        endif
    endmethod
    
    method changeLabel takes string oldLabel, string newLabel returns boolean
        if(.getFromLabel(oldLabel) == 0 or .getFromLabel(newLabel) != 0)then
            return false
        endif
        call .getFromLabel(oldLabel).setLabel(newLabel)
        return true
    endmethod
endstruct


endscope
//===========================================================================
// Trigger: Terrain type functions
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library TerrainTypeFunctions


function TerrainTypeId2TerrainType takes integer terrainTypeId returns TerrainType
    local integer i = 0
    loop
        exitwhen (i >= udg_terrainTypes.numberOfWalk)
            if (udg_terrainTypes.getWalk(i).getTerrainTypeId() == terrainTypeId) then
                return udg_terrainTypes.getWalk(i)
            endif
        set i = i + 1
    endloop
    set i = 0
    loop
        exitwhen (i >= udg_terrainTypes.numberOfDeath)
            if (udg_terrainTypes.getDeath(i).getTerrainTypeId() == terrainTypeId) then
                return udg_terrainTypes.getDeath(i)
            endif
        set i = i + 1
    endloop
    set i = 0
    loop
        exitwhen (i >= udg_terrainTypes.numberOfSlide)
            if (udg_terrainTypes.getSlide(i).getTerrainTypeId() == terrainTypeId) then
                return udg_terrainTypes.getSlide(i)
            endif
        set i = i + 1
    endloop
    return 0
endfunction



function IsTerrainTypeOfKind takes integer terrainTypeId, string terrainTypeKind returns boolean
    local TerrainType terrainType = TerrainTypeId2TerrainType(terrainTypeId)
    if (terrainType == 0) then
        return false
    endif
    return (terrainTypeKind == terrainType.getKind())
endfunction




//===========================================================================
function InitTrig_Terrain_type_functions takes nothing returns nothing
endfunction


endlibrary//===========================================================================
// Trigger: TerrainType
//===========================================================================
//TESH.scrollpos=21
//TESH.alwaysfold=0
library TerrainType needs TerrainTypeFunctions, TerrainFunctions


struct TerrainType 
    string label
    string alias
    string kind
	integer terrainTypeId
	
	method setType takes integer terrainTypeId returns nothing
		set .terrainTypeId = terrainTypeId
	endmethod
    
	method setLabel takes string label returns nothing
		set .label = label
	endmethod
	
	method setAlias takes string alias returns nothing
		set .alias = alias
	endmethod
	
	method getTerrainTypeId takes nothing returns integer
		return .terrainTypeId
	endmethod
	
	method setTerrainTypeId takes integer terrainTypeId returns boolean
        if (not CanUseTerrain(terrainTypeId)) then
            return false
        endif 
		set .terrainTypeId = terrainTypeId
        return true
	endmethod
	
	method getKind takes nothing returns string
		return .kind
	endmethod
    
    method onDestroy takes nothing returns nothing
        set .label = null
        set .alias = null
        set .kind = null
        set .terrainTypeId = 0
    endmethod
    
    method displayForPlayer takes player p returns nothing
        local string space = "   "
        local TerrainTypeSlide slide
        local TerrainTypeWalk walk
        local TerrainTypeDeath death
        local string display
        if (.kind == "slide") then
            set slide = TerrainTypeSlide(integer(this))
            set display = COLOR_TERRAIN_SLIDE + .label + " " + .alias + " : '" + Ascii2String(.terrainTypeId) + "'" + space
            set display = display + I2S(R2I(slide.getSlideSpeed()/SLIDE_PERIOD))
        else
        if (.kind == "walk") then
            set walk = TerrainTypeWalk(integer(this))
            set display = COLOR_TERRAIN_WALK + .label + " " + .alias + " : '" + Ascii2String(.terrainTypeId) + "'" + space
            set display = display + I2S(R2I(walk.getWalkSpeed()))
        else
        if (.kind == "death") then
            set death = TerrainTypeDeath(integer(this))
            set display = COLOR_TERRAIN_DEATH + .label + " " + .alias + " : '" + Ascii2String(.terrainTypeId) + "'" + space
            set display = display + R2S(death.getTimeToKill()) + space + death.getKillingEffectStr()
        endif
        endif
        endif
        call Text_P_timed(p, TERRAIN_DATA_DISPLAY_TIME, display)
    endmethod
    
    method toString takes nothing returns string
        local TerrainTypeSlide slide
        local TerrainTypeWalk walk
        local TerrainTypeDeath death
        local string str = .label + CACHE_SEPARATEUR_PARAM + .alias + CACHE_SEPARATEUR_PARAM
        set str = str + .kind + CACHE_SEPARATEUR_PARAM + Ascii2String(.terrainTypeId) + CACHE_SEPARATEUR_PARAM
        if (.kind == "slide") then
            set slide = TerrainTypeSlide(integer(this))
            set str = str + I2S(R2I(slide.getSlideSpeed() / SLIDE_PERIOD))
        else
        if (.kind == "walk") then
            set walk = TerrainTypeWalk(integer(this))
            set str = str + I2S(R2I(walk.getWalkSpeed()))
        else
        if (.kind == "death") then
            set death = TerrainTypeDeath(integer(this))
            set str = str + death.getKillingEffectStr() + CACHE_SEPARATEUR_PARAM
            set str = str + R2S(death.getTimeToKill())
        endif
        endif
        endif
        return str
    endmethod
endstruct




//===========================================================================
function InitTrig_TerrainType takes nothing returns nothing
endfunction



endlibrary//===========================================================================
// Trigger: TerrainTypeWalk
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library TerrainTypeWalk needs TerrainType


struct TerrainTypeWalk extends TerrainType
	private real walkSpeed
	
	static method create takes string label, integer terrainTypeId, real walkSpeed returns TerrainTypeWalk
		local TerrainTypeWalk tt 
        if (not CanUseTerrain(terrainTypeId)) then
            return 0
        endif        
        set tt = TerrainTypeWalk.allocate()
		set tt.label = label
        set tt.alias = null
		set tt.terrainTypeId = terrainTypeId
        set tt.walkSpeed = walkSpeed
        set tt.kind = "walk"
        return tt
	endmethod
	
	method getWalkSpeed takes nothing returns real
		return .walkSpeed
	endmethod
	
	method setWalkSpeed takes real walkSpeed returns nothing
		set .walkSpeed = walkSpeed
	endmethod
endstruct




//===========================================================================
function InitTrig_TerrainTypeWalk takes nothing returns nothing
endfunction



endlibrary//===========================================================================
// Trigger: TerrainTypeDeath functions
//===========================================================================
//TESH.scrollpos=6
//TESH.alwaysfold=0
library TerrainTypeDeath needs TerrainType



scope TerrainTypeDeathFunctions


function TerrainKillTimer2Escaper takes timer theTimer returns Escaper
	local trigger terrainKillTrigger = GetTriggeringTrigger()
	local integer terrainTypeDeathMaxId = udg_terrainTypes.numberOfDeath - 1
	local integer terrainTypeDeathId 
	local integer escaperId = 0
	
	set terrainTypeDeathId = 0
	loop
		exitwhen (terrainTypeDeathId > terrainTypeDeathMaxId)
			set escaperId = 0
			loop
				exitwhen (escaperId > 11)
					if (theTimer == udg_terrainTypes.getDeath(terrainTypeDeathId).getTimer(escaperId)) then
                        return udg_escapers.get(escaperId)
                    endif
				set escaperId = escaperId + 1
			endloop
		set terrainTypeDeathId = terrainTypeDeathId + 1
	endloop
    
	return 0
endfunction


function DeathTerrainKillEscaper_Actions takes nothing returns nothing
	local Escaper escaper = TerrainKillTimer2Escaper(GetExpiredTimer())
    if (escaper == 0) then
        return
    endif
	call escaper.pause(false)
	call escaper.destroyTerrainKillEffect()	
	if (escaper.currentLevelTouchTerrainDeath == udg_levels.getCurrentLevel()) then
		call escaper.kill()
    else
        if(escaper.isAlive())then
            call escaper.enableCheckTerrain(true)
        endif
	endif
endfunction


endscope



//===========================================================================
function InitTrig_TerrainTypeDeath_functions takes nothing returns nothing
endfunction//===========================================================================
// Trigger: TerrainTypeDeath KillingTimers
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope TerrainTypeDeathKillingTimers


struct KillingTimers
	private timer array timers [12]
    
	private method onDestroy takes nothing returns nothing
        local integer i = 0
		loop
			exitwhen (i > 11)
				call DestroyTimer(.timers[i])
				set .timers[i] = null
            set i = i + 1
		endloop
	endmethod
    
    static method create takes nothing returns KillingTimers
        local KillingTimers kt = KillingTimers.allocate()
        local integer i
        set i = 0
        loop
            exitwhen (i > 11)
                //if (udg_escapers.get(i) != 0) then //si l'escaper existe
                //si on laisse le filtre if les escapers apparus après le début (via un -createHero) ne meurent plus avec les terrains
                    set kt.timers[i] = CreateTimer()
                //endif
            set i = i + 1
        endloop
        return kt
    endmethod
	
	method start takes integer timerId, real time returns nothing
		call TimerStart(.timers[timerId], time, false, function DeathTerrainKillEscaper_Actions)
		set udg_escapers.get(timerId).currentLevelTouchTerrainDeath = udg_levels.getCurrentLevel()
	endmethod
    
    method get takes integer id returns timer
        return .timers[id]
    endmethod    
endstruct


endscope



//===========================================================================
function InitTrig_TerrainTypeDeath_KillingTimers takes nothing returns nothing
endfunction//===========================================================================
// Trigger: TerrainTypeDeath
//===========================================================================
//TESH.scrollpos=9
//TESH.alwaysfold=0
scope TerrainTypeDeathStruct


struct TerrainTypeDeath extends TerrainType
	private string killingEffectStr
	private real timeToKill  //en secondes
	private KillingTimers killingTimers
	
	static method create takes string label, integer terrainTypeId, string killingEffectStr, real timeToKill returns TerrainTypeDeath
		local integer i
		local TerrainTypeDeath tt
        if (not CanUseTerrain(terrainTypeId)) then
            return 0
        endif      
        set tt = TerrainTypeDeath.allocate()
		set tt.label = label
        set tt.alias = null
		set tt.terrainTypeId = terrainTypeId
		set tt.killingEffectStr = killingEffectStr
		set tt.timeToKill = timeToKill
		set tt.killingTimers = KillingTimers.create()
		set tt.kind = "death"
		return tt
	endmethod
	
	private method onDestroy takes nothing returns nothing
		call .killingTimers.destroy()			
	endmethod
	
	method setKillingEffectStr takes string killingEffectStr returns nothing
		set .killingEffectStr = killingEffectStr
	endmethod
	
	method getKillingEffectStr takes nothing returns string
		return .killingEffectStr
	endmethod
	
	method setTimeToKill takes real newTimeToKill returns boolean
        if (newTimeToKill < 0) then
            return false
        endif
		set .timeToKill = newTimeToKill
        return true
	endmethod
    
    method getTimeToKill takes nothing returns real
        return .timeToKill
    endmethod
	
	method killEscaper takes Escaper escaper returns nothing
		call escaper.enableCheckTerrain(false)
        call escaper.enableSlide(false)
        call escaper.pause(true)
		call escaper.createTerrainKillEffect(.killingEffectStr)
		call .killingTimers.start(escaper.getId(), .timeToKill)
	endmethod
    
    method getTimer takes integer escaperId returns timer
        return .killingTimers.get(escaperId)
    endmethod		
endstruct


endscope


//===========================================================================
function InitTrig_TerrainTypeDeath takes nothing returns nothing
endfunction


endlibrary//===========================================================================
// Trigger: TerrainTypeSlide
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library TerrainTypeSlide needs TerrainType


struct TerrainTypeSlide extends TerrainType
	private real slideSpeed
	
	
	static method create takes string label, integer terrainTypeId, real slideSpeed returns TerrainTypeSlide
		local TerrainTypeSlide tt
        if (not CanUseTerrain(terrainTypeId)) then
            return 0
        endif   
        set tt = TerrainTypeSlide.allocate()
		set tt.label = label
        set tt.alias = null
		set tt.terrainTypeId = terrainTypeId
        set tt.kind = "slide"
		set tt.slideSpeed = slideSpeed * SLIDE_PERIOD
        return tt
	endmethod
    
    method getSlideSpeed takes nothing returns real
        return .slideSpeed
    endmethod
    
    method setSlideSpeed takes real slideSpeed returns nothing
        set .slideSpeed = slideSpeed * SLIDE_PERIOD
    endmethod
endstruct










//===========================================================================
function InitTrig_TerrainTypeSlide takes nothing returns nothing
endfunction


endlibrary//===========================================================================
// Trigger: TerrainTypeArray
//===========================================================================
//TESH.scrollpos=209
//TESH.alwaysfold=0
library TerrainTypeArray needs TerrainTypeWalk, TerrainTypeDeath, TerrainTypeSlide


struct TerrainTypeArray
    private TerrainTypeWalk array ttWalk [177] //le nombre de terrains du jeu est de 177
    private TerrainTypeDeath array ttDeath [177]
    private TerrainTypeSlide array ttSlide [177]
    integer numberOfWalk
    integer numberOfDeath
    integer numberOfSlide
    
    static method create takes nothing returns TerrainTypeArray
        local TerrainTypeArray tta = TerrainTypeArray.allocate()
        set tta.numberOfWalk = 0
        set tta.numberOfDeath = 0
        set tta.numberOfSlide = 0
        return tta
    endmethod    
    
    method get takes string label returns TerrainType
		local integer i = 0
		loop
			exitwhen (i >= .numberOfWalk)
				if (.ttWalk[i].label == label or .ttWalk[i].alias == label) then
					return .ttWalk[i]
				endif
			set i = i + 1
		endloop
		set i = 0
		loop
			exitwhen (i >= .numberOfDeath)
				if (.ttDeath[i].label == label or .ttDeath[i].alias == label) then
					return .ttDeath[i]
				endif
			set i = i + 1
		endloop
		set i = 0
		loop
			exitwhen (i >= .numberOfSlide)
				if (.ttSlide[i].label == label or .ttSlide[i].alias == label) then
					return .ttSlide[i]
				endif
			set i = i + 1
		endloop
		return 0
	endmethod
	
	method getTerrainType takes real x, real y returns TerrainType
		local integer terrainTypeId = GetTerrainType(x, y)
		local integer i = 0
		loop
			exitwhen (i >= .numberOfWalk)
				if (.ttWalk[i].getTerrainTypeId() == terrainTypeId) then
					return .ttWalk[i]
				endif
			set i = i + 1
		endloop
		set i = 0
		loop
			exitwhen (i >= .numberOfDeath)
				if (.ttDeath[i].getTerrainTypeId() == terrainTypeId) then
					return .ttDeath[i]
				endif
			set i = i + 1
		endloop
		set i = 0
		loop
			exitwhen (i >= .numberOfSlide)
				if (.ttSlide[i].getTerrainTypeId() == terrainTypeId) then
					return .ttSlide[i]
				endif
			set i = i + 1
		endloop
		return 0
	endmethod
    
    method isTerrainTypeIdAlreadyUsed takes integer terrainTypeId returns boolean
        local integer i = 0
        loop
            exitwhen (i >= .numberOfWalk)
                if (terrainTypeId == .ttWalk[i].getTerrainTypeId()) then
                    return true
                endif
            set i = i + 1
        endloop
        set i = 0
        loop
            exitwhen (i >= .numberOfDeath)
                if (terrainTypeId == .ttDeath[i].getTerrainTypeId()) then
                    return true
                endif
            set i = i + 1
        endloop
        set i = 0
        loop
            exitwhen (i >= .numberOfSlide)
                if (terrainTypeId == .ttSlide[i].getTerrainTypeId()) then
                    return true
                endif
            set i = i + 1
        endloop
        return false
    endmethod
	
	method isLabelAlreadyUsed takes string label returns boolean
		return (.get(label) != 0)
	endmethod
    
    method newWalk takes string label, integer terrainTypeId, real walkspeed returns TerrainTypeWalk
        local integer n = .numberOfWalk
        if (.isLabelAlreadyUsed(label) or .isTerrainTypeIdAlreadyUsed(terrainTypeId) or terrainTypeId == 0) then
            return 0
        endif
        set .ttWalk[n] = TerrainTypeWalk.create(label, terrainTypeId, walkspeed)
        if (.ttWalk[n] != 0) then
            set .numberOfWalk = .numberOfWalk + 1
        endif
        return .ttWalk[n]
    endmethod
    
    method newDeath takes string label, integer terrainTypeId, string killingEffectStr, real timeToKill returns TerrainTypeDeath
        local integer n = .numberOfDeath
        if (.isLabelAlreadyUsed(label) or .isTerrainTypeIdAlreadyUsed(terrainTypeId) or terrainTypeId == 0) then
            return 0
        endif
        set .ttDeath[n] = TerrainTypeDeath.create(label, terrainTypeId, killingEffectStr, timeToKill)
        if (.ttDeath[n] != 0) then
            set .numberOfDeath = .numberOfDeath + 1
        endif
        return .ttDeath[n]
    endmethod
    
    method newSlide takes string label, integer terrainTypeId, real slideSpeed returns TerrainTypeSlide
        local integer n = .numberOfSlide
        if (.isLabelAlreadyUsed(label) or .isTerrainTypeIdAlreadyUsed(terrainTypeId) or terrainTypeId == 0) then
            return 0
        endif
        set .ttSlide[n] = TerrainTypeSlide.create(label, terrainTypeId, slideSpeed)
        if (.ttSlide[n] != 0) then
            set .numberOfSlide = .numberOfSlide + 1
        endif
        return .ttSlide[n]
    endmethod
    
    method remove takes string label returns boolean
        local integer position
        local integer i
        local TerrainType tt = .get(label)
        if (tt == 0) then
            return false
        endif
        if (tt.kind == "walk") then
            set i = 0
            loop
                exitwhen (.ttWalk[i].label == label or .ttWalk[i].alias == label or i >= .numberOfWalk)
                set i = i + 1
            endloop
            if (i < .numberOfWalk) then
                set position = i
                set i = i + 1
                loop
                    exitwhen (i >= .numberOfWalk)
                        set .ttWalk[i-1] = .ttWalk[i]
                    set i = i + 1
                endloop
                set .numberOfWalk = .numberOfWalk - 1
            endif
        endif
        if (tt.kind == "death") then
            set i = 0
            loop
                exitwhen (.ttDeath[i].label == label or .ttDeath[i].alias == label or i >= .numberOfDeath)
                set i = i + 1
            endloop
            if (i < .numberOfDeath) then
                set position = i
                set i = i + 1
                loop
                    exitwhen (i >= .numberOfDeath)
                        set .ttDeath[i-1] = .ttDeath[i]
                    set i = i + 1
                endloop
                set .numberOfDeath = .numberOfDeath - 1
            endif
        endif
        if (tt.kind == "slide") then
            set i = 0
            loop
                exitwhen (.ttSlide[i].label == label or .ttSlide[i].alias == label or i >= .numberOfSlide)
                set i = i + 1
            endloop
            if (i < .numberOfSlide) then
                set position = i
                set i = i + 1
                loop
                    exitwhen (i >= .numberOfSlide)
                        set .ttSlide[i-1] = .ttSlide[i]
                    set i = i + 1
                endloop
                set .numberOfSlide = .numberOfSlide - 1
            endif
        endif
        call tt.destroy()
        return true
    endmethod
    
    method getWalk takes integer id returns TerrainTypeWalk
        return .ttWalk[id]
    endmethod
    
    method getDeath takes integer id returns TerrainTypeDeath
        return .ttDeath[id]
    endmethod
    
    method getSlide takes integer id returns TerrainTypeSlide
        return .ttSlide[id]
    endmethod
    
    method displayForPlayer takes player p returns nothing
        local integer i = 0
        loop
            exitwhen (i >= .numberOfSlide)
                call .ttSlide[i].displayForPlayer(p)
            set i = i + 1
        endloop
        set i = 0
        loop
            exitwhen (i >= .numberOfWalk)
                call .ttWalk[i].displayForPlayer(p)
            set i = i + 1
        endloop
        set i = 0
        loop
            exitwhen (i >= .numberOfDeath)
                call .ttDeath[i].displayForPlayer(p)
            set i = i + 1
        endloop
        if (.numberOfSlide + .numberOfWalk + .numberOfDeath == 0) then
            call Text_erP(p, "no terrain saved")
        endif
    endmethod
    
    method saveInCache takes nothing returns nothing
        local integer i
        set stringArrayForCache = StringArrayForCache.create("terrain", "terrainConfig", true)
        set i = 0
        loop
            exitwhen (i >= .numberOfSlide)
                call stringArrayForCache.push(.ttSlide[i].toString())
            set i = i + 1
        endloop
        set i = 0
        loop
            exitwhen (i >= .numberOfWalk)
                call stringArrayForCache.push(.ttWalk[i].toString())
            set i = i + 1
        endloop
        set i = 0
        loop
            exitwhen (i >= .numberOfDeath)
                call stringArrayForCache.push(.ttDeath[i].toString())
            set i = i + 1
        endloop
        call stringArrayForCache.writeInCache()
    endmethod
endstruct
    
    

	


//===========================================================================
function InitTrig_TerrainTypeArray takes nothing returns nothing
endfunction



endlibrary//===========================================================================
// Trigger: Time of game trigger
//===========================================================================
//TESH.scrollpos=27
//TESH.alwaysfold=0
library GameTime

globals    
    private integer hours = 0
    private integer minuts = 0
    private integer seconds = 0
    player TIME_PLAYER = Player(0)
endglobals




function Trig_time_of_game_Actions takes nothing returns nothing
    local string timeStr
    local string hourStr
    local string minStr
    local string secStr
    
    //set integers
    if (seconds >= 59) then
        set seconds = 0
        if (minuts >= 59) then
            set minuts = 0
            set hours = hours + 1
        else
            set minuts = minuts + 1
        endif
    else
        set seconds = seconds + 1
    endif
    
    
    //set strings
    set hourStr = I2S(hours)
    
    if (minuts < 10) then
        set minStr = "0" + I2S(minuts)
    else
        set minStr = I2S(minuts)
    endif
    
    if (seconds < 10) then
        set secStr = "0" + I2S(seconds)
    else
        set secStr = I2S(seconds)
    endif
    
    set timeStr = "|Cfffed312 Game time :  " + hourStr + " h  " + minStr + " min  " + secStr + " s" 
    call LeaderboardSetPlayerItemLabelBJ(TIME_PLAYER, udg_lives.getLeaderboard(), timeStr)
endfunction



//===========================================================================
function InitTrig_Time_of_game_trigger takes nothing returns nothing
    set gg_trg_Time_of_game_trigger = CreateTrigger(  )
    call TriggerAddAction( gg_trg_Time_of_game_trigger, function Trig_time_of_game_Actions )
    call TriggerRegisterTimerEvent( gg_trg_Time_of_game_trigger, 1., true)
endfunction


endlibrary
//===========================================================================
// Trigger: Lives and game time
//===========================================================================
//TESH.scrollpos=6
//TESH.alwaysfold=0
library Lives needs BasicFunctions


globals
    private player LIVES_PLAYER = Player(6) //GREEN
endglobals


struct Lives
	private integer nb
    private leaderboard lb
    
	
//leaderboard methods
    method display takes boolean show returns nothing
        call LeaderboardDisplay(.lb, show)
    endmethod
    
    method refresh takes nothing returns nothing
		call LeaderboardSetPlayerItemValueBJ(LIVES_PLAYER, .lb, .nb)
	endmethod
    
    method getLeaderboard takes nothing returns leaderboard
        return .lb
    endmethod
	

//creation methods
	static method create takes nothing returns Lives
        local Lives l = Lives.allocate()
        if (udg_levels.get(0) != 0) then
            set l.nb = udg_levels.get(0).getNbLives()
        else
            set l.nb = NB_LIVES_AT_BEGINNING
        endif
        set l.lb = CreateLeaderboardBJ(GetPlayersAll(), "")
        call LeaderboardAddItemBJ(Player(0), l.lb, "Game time", 0)
        call LeaderboardSetPlayerItemStyleBJ(Player(0), l.lb, true, false, false )
        call LeaderboardAddItemBJ(LIVES_PLAYER, l.lb, "Lives :", l.nb)
        call l.display(true)
        return l
    endmethod
    
    
	private method onDestroy takes nothing returns nothing
		call DestroyLeaderboard(.lb)
		set .lb = null
	endmethod

	
//lives methods
    method get takes nothing returns integer
        return .nb
    endmethod
	
	method setNb takes integer nbLives returns boolean
        local string wordLives
		if (nbLives < 0) then
			return false
		endif
		set .nb = nbLives
		call .refresh()
		if (nbLives > 1) then
            set wordLives = " lives."
        else
            set wordLives = " life."
        endif
		call Text_A(udg_colorCode[GetPlayerId(LIVES_PLAYER)] + "You have now " + I2S(nbLives) + wordLives)
        return true
	endmethod
    
    method add takes integer n returns nothing
        local string wordLives
        if (n > 1) then
            set wordLives = " lives !"
        else
            set wordLives = " life."
        endif
        set .nb = .nb + n
        call Text_A(udg_colorCode[1] + "You have earned " + I2S(n) + wordLives)
        call .refresh()
    endmethod
    
    method loseALife takes nothing returns nothing
        set .nb = .nb - 1
        if (.nb >= 0) then
            call .refresh()
        endif
    endmethod
endstruct





//===========================================================================
function InitTrig_Lives_and_game_time takes nothing returns nothing
endfunction



endlibrary



//===========================================================================
// Trigger: Meteor
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library Meteor


globals
    constant integer METEOR_NORMAL = 'MND1'
    constant integer METEOR_CHEAT = 'MCD1'
endglobals



struct Meteor [20000] //100 météores * 200 niveaux
    private real x
    private real y
    private item meteor
    Level level
    integer arrayId
    
    method getItem takes nothing returns item
        return .meteor
    endmethod
    
    static method create takes real x, real y returns Meteor
        local Meteor m = Meteor.allocate()
        set m.x = x
        set m.y = y
        return m
    endmethod
    
    method removeMeteor takes nothing returns nothing
        if (.meteor != null) then
            call RemoveItem(.meteor)
            set .meteor = null
        endif
    endmethod
    
    method createMeteor takes nothing returns nothing
        if (.meteor != null) then
            call .removeMeteor()
        endif
        set .meteor = CreateItem(METEOR_NORMAL, .x, .y)
        if (udg_terrainTypes.getTerrainType(.x, .y).getKind() == "slide") then
            call SetItemDroppable(.meteor, false)
        endif
        call SetItemUserData(.meteor, integer(this))
    endmethod
    
    private method onDestroy takes nothing returns nothing
        if (.meteor != null) then
            call .removeMeteor()
            set .meteor = null
        endif
        call .level.meteors.setMeteorNull(.arrayId)
    endmethod
    
    method replace takes nothing returns nothing
        call SetItemPosition(.meteor, .x, .y)
    endmethod
    
    method toString takes nothing returns string
        return (I2S(R2I(.x)) + CACHE_SEPARATEUR_PARAM + I2S(R2I(.y)))
    endmethod
endstruct



endlibrary



//===========================================================================
function InitTrig_Meteor takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: MeteorArray
//===========================================================================
//TESH.scrollpos=21
//TESH.alwaysfold=0
library MeteorArray needs Meteor

globals
    private constant integer MAX_NB_METEORS = 100 //par niveau
endglobals



struct MeteorArray [20000] //200 niveaux * 100 météores
    private Meteor array meteors [MAX_NB_METEORS]
    private integer lastInstance
    
	static method create takes nothing returns MeteorArray
		local MeteorArray ma = MeteorArray.allocate()
		set ma.lastInstance = -1
		return ma
	endmethod
	
	method getFirstEmpty takes nothing returns integer
		local integer i = 0
		loop
			exitwhen (i > .lastInstance or .meteors[i] == 0)
			set i = i + 1
		endloop
		return i
	endmethod	
	
    method get takes integer arrayId returns Meteor
        if (arrayId < 0 or arrayId > .lastInstance) then
            return 0
        endif
        return .meteors[arrayId]
    endmethod
	
    method new takes real x, real y, boolean createMeteor returns Meteor //retourne la météore si elle a pu être créée, 0 sinon
		//local integer n = .getFirstEmpty()
        local integer n = .lastInstance + 1
		if (n >= MAX_NB_METEORS) then
			return 0
		endif
		//if (n > .lastInstance) then
			set .lastInstance = n
		//endif
		set .meteors[n] = Meteor.create(x, y)
		if (createMeteor) then
			call .meteors[n].createMeteor()
		endif
        set .meteors[n].level = udg_levels.getLevelFromMeteorArray(this)
        set .meteors[n].arrayId = n
		return .meteors[n]   
    endmethod
    
    method setMeteorNull takes integer arrayId returns nothing
        set .meteors[arrayId] = 0
    endmethod
	
	method count takes nothing returns integer
		local integer n = 0
		local integer i = 0
		loop
			exitwhen (i > .lastInstance)
				if (.meteors[i] != 0) then
					set n = n + 1
				endif
			set i = i + 1
		endloop
		return n
	endmethod
    
    method onDestroy takes nothing returns nothing
        local integer i = 0
        loop
            exitwhen (i > .lastInstance)
                if (.meteors[i] != 0) then
                    call .meteors[i].destroy()
                endif
            set i = i + 1
        endloop
        set .lastInstance = -1
    endmethod
    
    method clearMeteor takes integer meteorId returns boolean
        local integer i = 0
        loop
            exitwhen (.meteors[i] == Meteor(meteorId) or i > .lastInstance)
            set i = i + 1
        endloop
        if (i > .lastInstance) then
            return false
        endif
        call .meteors[i].destroy()
        set .meteors[i] = 0
        return true
    endmethod
    
    method createMeteors takes nothing returns nothing
        local integer i = 0
        loop
            exitwhen (i > .lastInstance)
                if (.meteors[i] != 0) then
                    call .meteors[i].createMeteor()
                endif
            set i = i + 1
        endloop
    endmethod
    
    method removeMeteors takes nothing returns nothing
        local integer i = 0
        loop
            exitwhen (i > .lastInstance)
                if (.meteors[i] != 0) then
                    call .meteors[i].removeMeteor()
                endif
            set i = i + 1
        endloop
    endmethod
    
    method getMeteorNear takes real x, real y returns Meteor
        local real xMeteor
        local real yMeteor
        local integer i = 0
        loop
            exitwhen (i > .lastInstance)
                if (.meteors[i] != 0 and .meteors[i].getItem() != null) then
                    set xMeteor = GetItemX(.meteors[i].getItem())
                    set yMeteor = GetItemY(.meteors[i].getItem())
                    if (RAbsBJ(x - xMeteor) < MONSTER_NEAR_DIFF_MAX and RAbsBJ(y - yMeteor) < MONSTER_NEAR_DIFF_MAX) then
                        return .meteors[i]
                    endif
                endif
            set i = i + 1
        endloop
        return 0    
    endmethod
    
    method getLastInstanceId takes nothing returns integer
        return .lastInstance
    endmethod
endstruct




endlibrary




//===========================================================================
function InitTrig_MeteorArray takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: Meteor functions
//===========================================================================
//TESH.scrollpos=18
//TESH.alwaysfold=0
library MeteorFunctions needs Meteor


globals
    private item meteor
endglobals



function HeroAddCheatMeteor takes unit hero returns item
    set meteor = UnitAddItemById(hero, METEOR_CHEAT)
    if (udg_terrainTypes.getTerrainType(GetUnitX(hero), GetUnitY(hero)).getKind() == "slide") then
        call SetItemDroppable(meteor, false)
    endif
    return meteor
endfunction


function HeroComingToSlide_CheckItem takes unit hero returns nothing
    set meteor = UnitItemInSlot(hero, 0)
    if (meteor != null) then
        call SetItemDroppable(meteor, false)
    endif
endfunction


function HeroComingOutFromSlide_CheckItem takes unit hero returns nothing
    set meteor = UnitItemInSlot(hero, 0)
    if (meteor != null) then
        call SetItemDroppable(meteor, true)
    endif
endfunction


function ExecuteRightClicOnUnit takes unit hero, unit u returns nothing
    local item itemCarried = UnitItemInSlot(hero, 0)
    local integer itemCarriedType = GetItemTypeId(itemCarried)
    if ((itemCarriedType == METEOR_NORMAL or itemCarriedType == METEOR_CHEAT) and GetWidgetLife(u) > 0.) then
        call UnitUseItemTarget(hero, itemCarried, u)
    else
        call StopUnit(hero)
    endif 
    set itemCarried = null    
endfunction



endlibrary


//===========================================================================
function InitTrig_Meteor_functions takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: Right click on widget
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
function Trig_right_click_on_widget_Conditions takes nothing returns boolean
    return (IsHero(GetTriggerUnit()) and IsIssuedOrder("smart"))
endfunction


function Trig_right_click_on_widget_Actions takes nothing returns nothing
    if (GetOrderTargetUnit() != null) then
        call ExecuteRightClicOnUnit(GetTriggerUnit(), GetOrderTargetUnit())  
    endif
endfunction


//===========================================================================
function InitTrig_Right_click_on_widget takes nothing returns nothing
    set gg_trg_Right_click_on_widget = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ(gg_trg_Right_click_on_widget, EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER)
    call TriggerAddAction(gg_trg_Right_click_on_widget, function Trig_right_click_on_widget_Actions)
    call TriggerAddCondition(gg_trg_Right_click_on_widget, Condition(function Trig_right_click_on_widget_Conditions))
endfunction

//===========================================================================
// Trigger: Meteor being used
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
function Trig_meteor_being_used_Actions takes nothing returns nothing
    call SetUnitAnimation(GetTriggerUnit(), "attack")
    if (GetItemTypeId(GetManipulatedItem()) == METEOR_NORMAL) then
        call DisableTrigger(GetTriggeringTrigger())
        call EnableTrigger(gg_trg_Stop_using_normal_meteor)
        call Meteor(GetItemUserData(GetManipulatedItem())).removeMeteor()
        call Hero2Escaper(GetTriggerUnit()).removeEffectMeteor()
        call TriggerSleepAction(1.)
        call EnableTrigger(GetTriggeringTrigger())
        call DisableTrigger(gg_trg_Stop_using_normal_meteor)
    endif
endfunction

//===========================================================================
function InitTrig_Meteor_being_used takes nothing returns nothing
    set gg_trg_Meteor_being_used = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Meteor_being_used, EVENT_PLAYER_UNIT_USE_ITEM )
    call TriggerAddAction( gg_trg_Meteor_being_used, function Trig_meteor_being_used_Actions )
endfunction

//===========================================================================
// Trigger: Stop using normal meteor
//===========================================================================
function Trig_Stop_using_normal_meteor_Conditions takes nothing returns boolean
    if ( not ( GetSpellAbilityId() == 'A002' ) ) then
        return false
    endif
    return true
endfunction

function Trig_Stop_using_normal_meteor_Actions takes nothing returns nothing
    call IssueImmediateOrderBJ( GetTriggerUnit(), "stop" )
endfunction

//===========================================================================
function InitTrig_Stop_using_normal_meteor takes nothing returns nothing
    set gg_trg_Stop_using_normal_meteor = CreateTrigger(  )
    call DisableTrigger( gg_trg_Stop_using_normal_meteor )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Stop_using_normal_meteor, EVENT_PLAYER_UNIT_SPELL_CAST )
    call TriggerAddCondition( gg_trg_Stop_using_normal_meteor, Condition( function Trig_Stop_using_normal_meteor_Conditions ) )
    call TriggerAddAction( gg_trg_Stop_using_normal_meteor, function Trig_Stop_using_normal_meteor_Actions )
endfunction

//===========================================================================
// Trigger: Effect meteor on pick up
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
function Trig_Effect_meteor_on_pick_up_Conditions takes nothing returns boolean
    return GetItemTypeId(UnitItemInSlotBJ(GetTriggerUnit(), 1)) == METEOR_NORMAL
endfunction

function Trig_Effect_meteor_on_pick_up_Actions takes nothing returns nothing
    call Hero2Escaper(GetTriggerUnit()).addEffectMeteor()
endfunction

//===========================================================================
function InitTrig_Effect_meteor_on_pick_up takes nothing returns nothing
    set gg_trg_Effect_meteor_on_pick_up = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Effect_meteor_on_pick_up, EVENT_PLAYER_UNIT_PICKUP_ITEM )
    call TriggerAddCondition( gg_trg_Effect_meteor_on_pick_up, Condition( function Trig_Effect_meteor_on_pick_up_Conditions ) )
    call TriggerAddAction( gg_trg_Effect_meteor_on_pick_up, function Trig_Effect_meteor_on_pick_up_Actions )
endfunction

//===========================================================================
// Trigger: VisibilityModifier
//===========================================================================
//TESH.scrollpos=3
//TESH.alwaysfold=0
library VisibilityModifier


struct VisibilityModifier [20000]
	private real x1
	private real y1
	private real x2
	private real y2
	private fogmodifier fm
    Level level
    integer arrayId
	
	static method create takes real x1, real y1, real x2, real y2 returns VisibilityModifier
		local VisibilityModifier vm = VisibilityModifier.allocate()
		local rect visionRect = Rect(x1, y1, x2, y2)
		set vm.x1 = x1
		set vm.y1 = y1
		set vm.x2 = x2
		set vm.y2 = y2
        set vm.fm = CreateFogModifierRect(Player(0), FOG_OF_WAR_VISIBLE, visionRect, true, false)
		call RemoveRect(visionRect)
		set visionRect = null
        call RefreshHideAllVM()
		return vm
	endmethod
	
	private method onDestroy takes nothing returns nothing
		call DestroyFogModifier(.fm)
		set .fm = null
        call .level.visibilities.setNull(.arrayId)
	endmethod
	
	method activate takes boolean activ returns nothing
		if (activ) then
			call FogModifierStart(.fm)
		else
			call FogModifierStop(.fm)
		endif
	endmethod
    
    method copy takes nothing returns VisibilityModifier
        return VisibilityModifier.create(.x1, .y1, .x2, .y2) 
    endmethod
    
    method toString takes nothing returns string
        local string x1 = I2S(R2I(.x1))
        local string y1 = I2S(R2I(.y1))
        local string x2 = I2S(R2I(.x2))
        local string y2 = I2S(R2I(.y2))
        return (x1 + CACHE_SEPARATEUR_PARAM + y1 + CACHE_SEPARATEUR_PARAM + x2 + CACHE_SEPARATEUR_PARAM + y2)
    endmethod
endstruct


	
	


//===========================================================================
function InitTrig_VisibilityModifier takes nothing returns nothing
endfunction



endlibrary//===========================================================================
// Trigger: VisibilityModifierArray
//===========================================================================
//TESH.scrollpos=26
//TESH.alwaysfold=0
library VisibilityModifierArray needs VisibilityModifier


struct VisibilityModifierArray [20000]
	private VisibilityModifier array vms [200] 
	private integer lastInstance
	
	
	static method create takes nothing returns VisibilityModifierArray
		local VisibilityModifierArray v = VisibilityModifierArray.allocate()
		set v.lastInstance = -1
		return v
	endmethod
    
	private method onDestroy takes nothing returns nothing
		local integer i = 0
		loop
			exitwhen (i > .lastInstance)
				call .vms[i].destroy()
			set i = i + 1
		endloop
		set .lastInstance = -1
	endmethod
    
	method new takes real x1, real y1, real x2, real y2 returns VisibilityModifier
		if (.lastInstance >= 199) then
			return 0
		endif
        set .lastInstance = .lastInstance + 1
        set .vms[.lastInstance] = VisibilityModifier.create(x1, y1, x2, y2)
        set .vms[.lastInstance].level = udg_levels.getLevelFromVisibilityModifierArray(this)
        set .vms[.lastInstance].arrayId = .lastInstance
		return .vms[.lastInstance]
	endmethod
    
    method newFromExisting takes VisibilityModifier vm returns VisibilityModifier
        if (.lastInstance >= 199) then
            return 0
        endif
        set .lastInstance = .lastInstance + 1
        set .vms[.lastInstance] = vm
        return vm
    endmethod
	
	method count takes nothing returns integer
        local integer n = 0
        local integer i = 0
        loop
            exitwhen (i > .lastInstance)
                if (.vms[i] != 0) then
                    set n = n + 1
                endif
            set i = i + 1
        endloop
		return n
	endmethod
    
    method get takes integer visibilityId returns VisibilityModifier
        if (visibilityId < 0 or visibilityId > .lastInstance) then
            return 0
        endif
        return .vms[visibilityId]
    endmethod
    
    method getLastInstanceId takes nothing returns integer
        return .lastInstance
    endmethod
    
    method setNull takes integer arrayId returns nothing
        if (arrayId >= 0 and arrayId <= .lastInstance) then
            set .vms[arrayId] = 0
        endif
    endmethod
    
    method removeAllVisibilityModifiers takes nothing returns nothing
        loop
            exitwhen (.lastInstance < 0)
                call .vms[.lastInstance].destroy()
            set .lastInstance = .lastInstance - 1
        endloop
    endmethod
	
	method removeLasts takes integer numberOfVMToRemove returns boolean //renvoie true si tous sont supprimés
		local integer i = numberOfVMToRemove
		loop
			exitwhen (i <= 0 or .lastInstance < 0)
				call .vms[.lastInstance].destroy()
				set .lastInstance = .lastInstance - 1
			set i = i - 1
		endloop	
        return (i == 0)
	endmethod
	
	method activate takes boolean activ returns nothing
		local integer i = 0
		loop
			exitwhen (i > .lastInstance)
				call .vms[i].activate(activ)
			set i = i + 1
		endloop
	endmethod
endstruct





//===========================================================================
function InitTrig_VisibilityModifierArray takes nothing returns nothing
endfunction



endlibrary

			//===========================================================================
// Trigger: StartAndEnd
//===========================================================================
//TESH.scrollpos=94
//TESH.alwaysfold=0
library StartAndEnd needs BasicFunctions, Escaper


interface RectInterface
    real minX
    real minY
    real maxX
    real maxY
    rect r
    method toString takes nothing returns string
endinterface


globals
    Start DEPART_PAR_DEFAUT
endglobals


struct Start extends RectInterface
    static method create takes real x1, real y1, real x2, real y2 returns Start
        local Start s = Start.allocate()
        set s.minX = RMinBJ(x1, x2)
        set s.minY = RMinBJ(y1, y2)
        set s.maxX = RMaxBJ(x1, x2)
        set s.maxY = RMaxBJ(y1, y2)
        set s.r  = Rect(s.minX, s.minY, s.maxX, s.maxY)
        return s
    endmethod
	
	private method onDestroy takes nothing returns nothing
		call RemoveRect(.r)
		set .r = null
	endmethod
	
	method getRandomX takes nothing returns real
		return GetRandomReal(.minX, .maxX)
    endmethod
    
	method getRandomY takes nothing returns real
		return GetRandomReal(.minY, .maxY )
    endmethod
	
	method getCenterX takes nothing returns real
		return GetRectCenterX(.r)
    endmethod
    
	method getCenterY takes nothing returns real
		return GetRectCenterY(.r)
    endmethod
    
    method toString takes nothing returns string
        local string minX = I2S(R2I(.minX))
        local string minY = I2S(R2I(.minY))
        local string maxX = I2S(R2I(.maxX))
        local string maxY = I2S(R2I(.maxY))
        return (minX + CACHE_SEPARATEUR_PARAM + minY + CACHE_SEPARATEUR_PARAM + maxX + CACHE_SEPARATEUR_PARAM + maxY)
    endmethod
endstruct





function EndReaching_Actions takes nothing returns nothing
    local Escaper finisher = Hero2Escaper(GetTriggerUnit())
    if (finisher == 0) then
        return
    endif
    if (not udg_levels.goToNextLevel(finisher)) then
        call Text_A("Good job ! You have finished the game.")
        call TriggerSleepAction(2)
        call Text_A("restart in 10 seconds")
        call TriggerSleepAction(10)
        call udg_levels.restartTheGame()
    endif
endfunction


struct End extends RectInterface
    private trigger endReaching

    static method create takes real x1, real y1, real x2, real y2 returns End
        local End e = End.allocate()
        set e.minX = RMinBJ(x1, x2)
        set e.minY = RMinBJ(y1, y2)
        set e.maxX = RMaxBJ(x1, x2)
        set e.maxY = RMaxBJ(y1, y2)
        set e.r  = Rect(e.minX, e.minY, e.maxX, e.maxY)
        set e.endReaching = CreateTrigger()
        call TriggerAddAction(e.endReaching, function EndReaching_Actions)
        call TriggerRegisterEnterRectSimple(e.endReaching, e.r)
        call DisableTrigger(e.endReaching)
        return e
    endmethod
    
    method activate takes boolean activ returns nothing
        if activ then
            call EnableTrigger(.endReaching)
        else
            call DisableTrigger(.endReaching)
        endif
    endmethod
    
    private method onDestroy takes nothing returns nothing
		call RemoveRect(.r)
		set .r = null
        call DestroyTrigger(.endReaching)
        set .endReaching = null
    endmethod   
    
    method toString takes nothing returns string
        local string minX = I2S(R2I(.minX))
        local string minY = I2S(R2I(.minY))
        local string maxX = I2S(R2I(.maxX))
        local string maxY = I2S(R2I(.maxY))
        return (minX + CACHE_SEPARATEUR_PARAM + minY + CACHE_SEPARATEUR_PARAM + maxX + CACHE_SEPARATEUR_PARAM + maxY)
    endmethod     
endstruct





//===========================================================================
function InitTrig_StartAndEnd takes nothing returns nothing
    set DEPART_PAR_DEFAUT = Start.create(-500, -500, 500, 500)
endfunction



endlibrary
//===========================================================================
// Trigger: Triggers
//===========================================================================
//TESH.scrollpos=27
//TESH.alwaysfold=0
library Triggers


struct Trigger
    private trigger t
    
    
    private method onDestroy takes nothing returns nothing
        call DestroyTrigger(.t)
        set .t = null
    endmethod
    
    static method create takes nothing returns Trigger
        local Trigger t = Trigger.allocate()
        set t.t = CreateTrigger()
        return t
    endmethod
    
    method activate takes boolean activ returns nothing
        if (activ) then
            call EnableTrigger(.t)
        else
            call DisableTrigger(.t)
        endif
    endmethod
endstruct


struct TriggerArray
    private Trigger array triggers [200]
    private integer lastInstance
    
    
    static method create takes nothing returns TriggerArray
        local TriggerArray ta = TriggerArray.allocate()
        set ta.lastInstance = -1
        return ta
    endmethod
    
    private method onDestroy takes nothing returns nothing
        local integer i = 0
        loop
            exitwhen (i > .lastInstance)
                call .triggers[i].destroy()
            set i = i + 1
        endloop
        set .lastInstance = -1
    endmethod
    
    method activate takes boolean activ returns nothing
        local integer i = 0
        loop
            exitwhen (i > .lastInstance)
                if (.triggers[i] != 0) then
                    call .triggers[i].activate(activ)
                endif
            set i = i + 1
        endloop
    endmethod
endstruct



//===========================================================================
function InitTrig_Triggers takes nothing returns nothing
endfunction




endlibrary//===========================================================================
// Trigger: Level
//===========================================================================
//TESH.scrollpos=42
//TESH.alwaysfold=0
library Level needs VisibilityModifierArray, StartAndEnd, Triggers, Lives

//nombre maximum de niveaux : 200. Nombre maximum de monstres de chaque type par niveau : 1000.


globals
    public boolean earningLivesActivated = true
endglobals


struct Level
    private boolean isActivatedB
    private string startMessage
    private integer livesEarnedAtBeginning
	private Start start
	private End end
	VisibilityModifierArray visibilities
	MonsterNoMoveArray monstersNoMove
	MonsterSimplePatrolArray monstersSimplePatrol
	MonsterMultiplePatrolsArray monstersMultiplePatrols
    MonsterSpawnArray monsterSpawns
    MeteorArray meteors
	private TriggerArray triggers
    
    static method create takes nothing returns Level
        local Level l = Level.allocate()
        set l.visibilities = VisibilityModifierArray.create()
        set l.triggers = TriggerArray.create()
        set l.monstersNoMove = MonsterNoMoveArray.create()
        set l.monstersSimplePatrol = MonsterSimplePatrolArray.create()
        set l.monstersMultiplePatrols = MonsterMultiplePatrolsArray.create()
        set l.monsterSpawns = MonsterSpawnArray.create()
        set l.meteors = MeteorArray.create()
        set l.livesEarnedAtBeginning = 1
        set l.isActivatedB = false
        return l
    endmethod
	
	method activate takes boolean activ returns nothing
        if (.isActivatedB == activ) then
            return
        endif
        call .end.activate(activ)
        call .triggers.activate(activ)
        if (activ) then
            if (.startMessage != null and .startMessage != "" and earningLivesActivated) then
                call Text_A(.startMessage)
            endif
            call .visibilities.activate(true)
            call .monstersNoMove.createMonsters()
            call .monstersSimplePatrol.createMonsters()
            call .monstersMultiplePatrols.createMonsters()
            call .monsterSpawns.activate()
            call .meteors.createMeteors()
            if (earningLivesActivated and .getId() > 0) then
                call udg_lives.add(.livesEarnedAtBeginning)
            endif
        else
            call .monstersNoMove.removeMonsters()
            call .monstersSimplePatrol.removeMonsters()
            call .monstersMultiplePatrols.removeMonsters()
            call .monsterSpawns.desactivate()
            call .meteors.removeMeteors()
            call udg_escapers.deleteSpecificActionsForLevel(this)
        endif
        set .isActivatedB = activ
    endmethod
    
    method checkpointReviveHeroes takes Escaper finisher returns nothing
        set TrigCheckpointReviveHeroes_levelForReviving = this
        set TrigCheckpointReviveHeroes_revivingFinisher = finisher
        call TriggerExecute(gg_trg____Trig_checkpoint_revive_heroes)    
    endmethod
    
    method getStart takes nothing returns Start
        return .start
    endmethod
    
    method getStartRandomX takes nothing returns real
        return .start.getRandomX()
    endmethod
    
    method getStartRandomY takes nothing returns real
        return .start.getRandomY()
    endmethod
    
    method newStart takes real x1, real y1, real x2, real y2 returns nothing
        call .start.destroy()
        set .start = Start.create(x1, y1, x2, y2)
    endmethod
    
    method newEnd takes real x1, real y1, real x2, real y2 returns nothing
        call .end.destroy()
        set .end = End.create(x1, y1, x2, y2)
        if (.isActivatedB) then
            call .end.activate(true)
        endif
    endmethod
    
    method getEnd takes nothing returns End
        return .end
    endmethod
	
	method getNbMonstersNoMove takes nothing returns integer
		return .monstersNoMove.count()
	endmethod
	
	method getNbMonstersSimplePatrol takes nothing returns integer
		return .monstersSimplePatrol.count()
	endmethod
	
	method getNbMonstersMultiplePatrols takes nothing returns integer
		return .monstersMultiplePatrols.count()
	endmethod
    
    method onDestroy takes nothing returns nothing
        call .start.destroy()
        call .end.destroy()
        call .visibilities.destroy()
        call .triggers.destroy()
        call .monstersNoMove.destroy()
        call .monstersSimplePatrol.destroy()
        call .monstersMultiplePatrols.destroy()
    endmethod
    
    method recreateMonstersOfType takes MonsterType mt returns nothing
        call .monstersNoMove.recreateMonstersOfType(mt)
        call .monstersSimplePatrol.recreateMonstersOfType(mt)
        call .monstersMultiplePatrols.recreateMonstersOfType(mt)
    endmethod
    
    method removeMonstersOfType takes MonsterType mt returns nothing
        call .monstersNoMove.removeMonstersOfType(mt)
        call .monstersSimplePatrol.removeMonstersOfType(mt)
        call .monstersMultiplePatrols.removeMonstersOfType(mt)
    endmethod
    
    method getId takes nothing returns integer
        local integer i = 0
        loop
            exitwhen (udg_levels.get(i) == 0)
                if (udg_levels.get(i) == this) then
                    return i
                endif
            set i = i + 1
        endloop
        return -1
    endmethod
    
    method isActivated takes nothing returns boolean
        return .isActivatedB
    endmethod
    
    method setIsActivated takes boolean activated returns nothing
        set .isActivatedB = activated
    endmethod
    
    method setNbLivesEarned takes integer nbLives returns boolean
        if (nbLives < 0) then
            return false
        endif
        set .livesEarnedAtBeginning = nbLives
        return true
    endmethod
    
    method getNbLives takes nothing returns integer
        return .livesEarnedAtBeginning
    endmethod
    
    method newVisibilityModifier takes real x1, real y1, real x2, real y2 returns VisibilityModifier
        return .visibilities.new(x1, y1, x2, y2)
    endmethod
    
    method newVisibilityModifierFromExisting takes VisibilityModifier vm returns VisibilityModifier
        return .visibilities.newFromExisting(vm)
    endmethod
    
    method removeVisibilities takes nothing returns nothing
        call .visibilities.removeAllVisibilityModifiers()
    endmethod
    
    method activateVisibilities takes boolean activate returns nothing
        call .visibilities.activate(activate)
    endmethod
    
    method setStartMessage takes string str returns nothing
        if (str == "") then
            set str = null
        endif
        set .startMessage = str
    endmethod
    
    method getStartMessage takes nothing returns string
        return .startMessage
    endmethod
endstruct
    




//===========================================================================
function InitTrig_Level takes nothing returns nothing
endfunction


endlibrary
//===========================================================================
// Trigger:    Level functions
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library LevelFunctions


function IsLevelBeingMade takes Level level returns boolean
    local integer i = 0
    loop
        exitwhen (i > 11)
            if (udg_escapers.get(i) != 0) then
                if (udg_escapers.get(i).getMakingLevel() == level) then
                    return true
                endif
            endif
        set i = i + 1
    endloop
    return (udg_levels.getCurrentLevel() == level)
endfunction


endlibrary



//===========================================================================
function InitTrig____Level_functions takes nothing returns nothing
endfunction

//===========================================================================
// Trigger:    Trig checkpoint revive heroes
//===========================================================================
//TESH.scrollpos=3
//TESH.alwaysfold=0
library TrigCheckpointReviveHeroes needs ChangeAllTerrains


globals
    public Level levelForReviving
    public Escaper revivingFinisher
endglobals



function Trig_Trig_checkpoint_revive_heroes_Actions takes nothing returns nothing
    local Level l = levelForReviving
    local Escaper finisher = revivingFinisher
    local Escaper escaper
    local integer i = 0
    loop
        exitwhen (i > 11)
            set escaper = udg_escapers.get(i)
            if (escaper != 0 and escaper != finisher) then
                if (not escaper.reviveAtStart()) then
                    call escaper.moveHero(l.getStartRandomX(), l.getStartRandomY())
                    call StopUnit(escaper.getHero())
                    call escaper.pause(true)
                endif
            endif
        set i = i + 1
    endloop    
    call Text_A(udg_colorCode[GetPlayerId(finisher.getPlayer())] + "Good job " + GetPlayerName(finisher.getPlayer()) + " !")
    call TriggerSleepAction(1)
    set i = 0
    loop
        exitwhen (i > 11)
            set escaper = udg_escapers.get(i)
            if (escaper != 0 and escaper != finisher) then
                call escaper.pause(false)
            endif
        set i = i + 1
    endloop 
    if (udg_changeAllTerrainsAtRevive) then
        call TriggerSleepAction(1.00)
        call ChangeAllTerrains("normal")
    endif
endfunction

//===========================================================================
function InitTrig____Trig_checkpoint_revive_heroes takes nothing returns nothing
    set gg_trg____Trig_checkpoint_revive_heroes = CreateTrigger(  )
    call TriggerAddAction( gg_trg____Trig_checkpoint_revive_heroes, function Trig_Trig_checkpoint_revive_heroes_Actions )
endfunction


endlibrary

//===========================================================================
// Trigger: LevelArray
//===========================================================================
//TESH.scrollpos=147
//TESH.alwaysfold=0
library LevelArray needs Level


globals
    constant integer NB_MAX_LEVELS = 200
endglobals


struct LevelArray
	private Level array levels [NB_MAX_LEVELS]
	private integer currentLevel
	private integer lastInstance
	
	
	static method create takes nothing returns LevelArray
		local real x1 = GetRectMinX(gg_rct_departLvl_0)
		local real y1 = GetRectMinY(gg_rct_departLvl_0)
		local real x2 = GetRectMaxX(gg_rct_departLvl_0)
		local real y2 = GetRectMaxY(gg_rct_departLvl_0)
		local LevelArray la = LevelArray.allocate()
        set la.levels[0] = Level.create()
		call la.levels[0].newStart(x1, y1, x2, y2)
        call la.levels[0].setNbLivesEarned(NB_LIVES_AT_BEGINNING)
        set la.currentLevel = 0
        set la.lastInstance = 0
		return la
	endmethod	
	
	method goToLevel takes Escaper finisher, integer levelId returns boolean
        local real xCam
        local real yCam
        local integer i
        local integer previousLevelId = .currentLevel
		if (levelId < 0 or levelId > .lastInstance or levelId == .currentLevel) then
			return false
		endif
		set .currentLevel = levelId
        if (previousLevelId != NB_MAX_LEVELS) then //cas spécial restart de la game
            if (not IsLevelBeingMade(.levels[previousLevelId])) then
                call udg_escapers.destroyMakesIfForSpecificLevel_currentLevel()
                call .levels[previousLevelId].activate(false)
            endif
        endif
		call .levels[.currentLevel].activate(true)
        call .levels[.currentLevel].checkpointReviveHeroes(finisher)
        if (previousLevelId != NB_MAX_LEVELS) then
            if (levelId > previousLevelId + 1) then
                set i = previousLevelId + 1
                loop
                    exitwhen (i >= levelId)
                        call .levels[i].activateVisibilities(true)
                    set i = i + 1
                endloop
            else
                if (levelId < previousLevelId) then
                    set i = levelId + 1
                    loop
                        exitwhen (i > previousLevelId)
                            call .levels[i].activateVisibilities(false)
                        set i = i + 1
                    endloop
                endif
            endif
        endif
        set xCam = .levels[levelId].getStart().getCenterX()
        set yCam = .levels[levelId].getStart().getCenterY()
        if (finisher != 0) then
            call MoveCamExceptForPlayer(finisher.getPlayer(), xCam, yCam)
        else
            call SetCameraPosition(xCam, yCam)
        endif
		return true
	endmethod
	
	method goToNextLevel takes Escaper finisher returns boolean //retourne false s'il n'y a pas de niveau suivant
        local real xCam
        local real yCam
        if (.currentLevel >= .lastInstance) then
			return false
		endif
		set .currentLevel = .currentLevel + 1
        if (not IsLevelBeingMade(.levels[.currentLevel - 1])) then
            call udg_escapers.destroyMakesIfForSpecificLevel_currentLevel()
            call .levels[.currentLevel - 1].activate(false)
        endif
		call .levels[.currentLevel].activate(true)
        call .levels[.currentLevel].checkpointReviveHeroes(finisher)
        set xCam = .levels[.currentLevel].getStart().getCenterX()
        set yCam = .levels[.currentLevel].getStart().getCenterY()
        if (finisher != 0) then
            call MoveCamExceptForPlayer(finisher.getPlayer(), xCam, yCam)
        else
            call SetCameraPosition(xCam, yCam)
        endif
        return true
	endmethod
    
    method restartTheGame takes nothing returns nothing
        if (.currentLevel == 0) then
            set .currentLevel = NB_MAX_LEVELS //pour assurer le changement de niveau
            call .levels[0].activate(false)
        endif
        call .goToLevel(0, 0)
        call udg_lives.setNb(.levels[0].getNbLives())
        call SetCameraPosition(.levels[0].getStart().getCenterX(), .levels[0].getStart().getCenterY())
    endmethod
	
	method new takes nothing returns boolean //retourne false si le nombre maximum de niveaux est déja atteint
		if (.lastInstance >= NB_MAX_LEVELS - 1) then
			return false
		endif
		set .lastInstance = .lastInstance + 1
		set .levels[.lastInstance] = Level.create()
        return true
	endmethod
    
    method destroyLastLevel takes nothing returns boolean
        if (.lastInstance <= 0) then
            return false
        endif
        call .levels[.lastInstance].destroy()
        set .lastInstance = .lastInstance - 1
        return true
    endmethod
	
	method count takes nothing returns integer
		return .lastInstance + 1
	endmethod
	
	method getCurrentLevel takes nothing returns Level
		return .levels[.currentLevel]
	endmethod
    
    method get takes integer levelId returns Level
        if (levelId > .lastInstance or levelId < 0) then
            return 0
        endif
        return .levels[levelId]
    endmethod
    
    method getLevelFromMonsterNoMoveArray takes MonsterNoMoveArray ma returns Level
        local integer i = 0
        loop
            exitwhen (i > .lastInstance or .levels[i].monstersNoMove == ma)
            set i = i + 1
        endloop
        if (i > .lastInstance) then
            return 0
        endif
        return .levels[i]
    endmethod
    method getLevelFromMonsterSimplePatrolArray takes MonsterSimplePatrolArray ma returns Level
        local integer i = 0
        loop
            exitwhen (i > .lastInstance or .levels[i].monstersSimplePatrol == ma)
            set i = i + 1
        endloop
        if (i > .lastInstance) then
            return 0
        endif
        return .levels[i]
    endmethod
    method getLevelFromMonsterMultiplePatrolsArray takes MonsterMultiplePatrolsArray ma returns Level
        local integer i = 0
        loop
            exitwhen (i > .lastInstance or .levels[i].monstersMultiplePatrols == ma)
            set i = i + 1
        endloop
        if (i > .lastInstance) then
            return 0
        endif
        return .levels[i]
    endmethod
    method getLevelFromMonsterSpawnArray takes MonsterSpawnArray msa returns Level
        local integer i = 0
        loop
            exitwhen (i > .lastInstance or .levels[i].monsterSpawns == msa)
            set i = i + 1
        endloop
        if (i > .lastInstance) then
            return 0
        endif
        return .levels[i]
    endmethod
    method getLevelFromMeteorArray takes MeteorArray ma returns Level
        local integer i = 0
        loop
            exitwhen (i > .lastInstance or .levels[i].meteors == ma)
            set i = i + 1
        endloop
        if (i > .lastInstance) then
            return 0
        endif
        return .levels[i]
    endmethod
    method getLevelFromVisibilityModifierArray takes VisibilityModifierArray vma returns Level
        local integer i = 0
        loop
            exitwhen (i > .lastInstance or .levels[i].visibilities == vma)
            set i = i + 1
        endloop
        if (i > .lastInstance) then
            return 0
        endif
        return .levels[i]
    endmethod
    
    method removeMonstersOfType takes MonsterType mt returns nothing
        local integer i = 0
        loop
            exitwhen (i > .lastInstance)
                call .levels[i].removeMonstersOfType(mt)
            set i = i + 1
        endloop
    endmethod
    
    method getLastLevelId takes nothing returns integer
        return .lastInstance
    endmethod
endstruct



function ForceGetLevel takes integer levelId returns Level
    local integer i
    local integer lastInstance
    if (levelId < 0 or levelId >= NB_MAX_LEVELS) then
        return 0
    endif
    if (udg_levels == 0) then
        set udg_levels = LevelArray.create()
    endif
    set lastInstance = udg_levels.getLastLevelId()
    loop
        exitwhen (lastInstance >= levelId)
            call udg_levels.new()
        set lastInstance = udg_levels.getLastLevelId()
    endloop
    return udg_levels.get(levelId)
endfunction



//===========================================================================
function InitTrig_LevelArray takes nothing returns nothing
endfunction



endlibrary//===========================================================================
// Trigger: EscaperEffect functions
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library Escaper needs SlideTrigger, CheckTerrainTrigger, LevelFunctions


scope EscaperEffectFunctions


function String2BodyPartStr takes string S returns string 
    if (S == "leftHand" or S == "lh") then
        return "hand left"
    endif
    if (S == "rightHand" or S == "rh") then
        return "hand right"
    endif
    if (S == "leftFoot" or S == "lf") then
        return "foot left"
    endif
    if (S == "rightFoot" or S == "rf") then
        return "foot right"
    endif
    if (S == "overhead" or S == "oh") then
        return "overhead"
    endif
    if (S == "head" or S == "h") then
        return "head"
    endif
    if (S == "origin" or S == "o") then
        return "origin"
    endif
    if (S == "chest" or S == "c") then
        return "chest"
    endif
    return null
endfunction


function IsBodyPartStr takes string s returns boolean
    return String2BodyPartStr(s) != null
endfunction


function String2EffectStr takes string str returns string
    if (str == "light" or str == "l") then
        return "Abilities\\Weapons\\FarseerMissile\\FarseerMissile.mdl"
    endif
    if (str == "fire" or str == "f") then
        return "Abilities\\Spells\\Items\\AIfb\\AIfbTarget.mdl"
    endif
    if (str == "ice" or str == "i") then
        return "Abilities\\Spells\\Items\\AIob\\AIobTarget.mdl"
    endif
    if (str == "corruption" or str == "c") then
        return "Abilities\\Spells\\Items\\OrbCorruption\\OrbCorruption.mdl"
    endif
    if (str == "poison" or str == "p") then
        return "Abilities\\Spells\\Items\\OrbVenom\\OrbVenom.mdl"
    endif
    if (str == "slow" or str == "s") then
        return "Abilities\\Spells\\Items\\OrbSlow\\OrbSlow.mdl"
    endif
    return null
endfunction


function IsEffectStr takes string str returns boolean
    return String2EffectStr(str) != null
endfunction





endscope



//===========================================================================
function InitTrig_EscaperEffect_functions takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: EscaperEffect
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope EscaperEffect


struct EscaperEffect
	private effect ef
	private string efStr
	private string bodyPart
	

	static method create takes string efStr, unit u, string bodyPart returns EscaperEffect
		local EscaperEffect e = EscaperEffect.allocate()
		set e.efStr = efStr
		set e.bodyPart = bodyPart
		set e.ef = AddSpecialEffectTarget(efStr, u, bodyPart)
		return e
	endmethod
	
	private method onDestroy takes nothing returns nothing
        if(.ef != null)then
            call DestroyEffect(.ef)
            set .ef = null
        endif
	endmethod
	
	method recreate takes unit u returns nothing
		call .onDestroy()
		set .ef = AddSpecialEffectTarget(.efStr, u, .bodyPart)
	endmethod	

	method remove takes nothing returns nothing
		call DestroyEffect(.ef)
		set .ef = null
	endmethod
endstruct





endscope

//===========================================================================
function InitTrig_EscaperEffect takes nothing returns nothing
endfunction



//===========================================================================
// Trigger: EscaperEffectArray
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope EscaperEffectArray


struct EscaperEffectArray [240]
	private EscaperEffect array efs [20]
	private integer lastInstance
	
	
	static method create takes nothing returns EscaperEffectArray
		local EscaperEffectArray e = EscaperEffectArray.allocate()
		set e.lastInstance = -1
		return e
	endmethod
	
	method new takes string efStr, unit u, string bodyPart returns nothing
		local integer i
		if (.lastInstance >= 19) then
			call .efs[0].destroy()
			set i = 0
			loop
				exitwhen (i >= 19)
					set .efs[i] = .efs[i+1]
				set i = i + 1
			endloop
		else
			set .lastInstance = .lastInstance + 1
		endif
		set .efs[.lastInstance] = EscaperEffect.create(efStr, u, bodyPart)
	endmethod
	
	method count takes nothing returns integer
		local integer n = 0
		local integer i = 0
		loop
			exitwhen (i > .lastInstance)
				if .efs[i] != 0 then
					set n = n + 1
				endif
			set i = i + 1
		endloop
		return n
	endmethod
	
	private method onDestroy takes nothing returns nothing
		loop
			exitwhen (.lastInstance < 0)
				call .efs[.lastInstance].destroy()
			set .lastInstance = .lastInstance - 1
		endloop
	endmethod
	
	method destroyLastEffects takes integer numEfToDestroy returns nothing
		local integer i = numEfToDestroy
		loop
			exitwhen (i <= 0 or .lastInstance < 0)
				call .efs[.lastInstance].destroy()
				set .lastInstance = .lastInstance - 1
			set i = i - 1
		endloop
	endmethod
	
	method hideEffects takes nothing returns nothing
		local integer i = 0
		loop
			exitwhen i > .lastInstance
				call .efs[i].remove()
			set i = i + 1
		endloop	
	endmethod
	
	method showEffects takes unit u returns nothing
		local integer i = 0
		loop
			exitwhen (i > .lastInstance)
				call .efs[i].recreate(u)
			set i = i + 1
		endloop	
	endmethod
endstruct
	


//===========================================================================
function InitTrig_EscaperEffectArray takes nothing returns nothing
endfunction

	
endscope//===========================================================================
// Trigger: Escaper functions
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope EscaperFunctions





function ColorInfo takes Escaper escaperToGetInfo, player playerToDisplay returns nothing
    local integer baseColor = escaperToGetInfo.getBaseColor()
	local string red = I2S(R2I(escaperToGetInfo.getVcRed()))
	local string green = I2S(R2I(escaperToGetInfo.getVcGreen()))
	local string blue = I2S(R2I(escaperToGetInfo.getVcBlue()))
	local string transparency = I2S(R2I(escaperToGetInfo.getVcTransparency()))
    call Text_P(playerToDisplay, "Base color : " + udg_colorCode[baseColor] + udg_baseColorString[baseColor])
    call Text_P(playerToDisplay, udg_colorCode[0] + "red     :  " + red + "  %")
    call Text_P(playerToDisplay, udg_colorCode[6] + "green :  " + green + "  %")
    call Text_P(playerToDisplay, udg_colorCode[1] + "blue   :  " + blue + "  %")
    call Text_P(playerToDisplay, udg_colorCode[8] + "transparency : " + transparency + "  %" )
endfunction


function Hero2Escaper takes unit hero returns Escaper
    if (GetUnitTypeId(hero) == HERO_TYPE_ID) then
        return udg_escapers.get(GetUnitUserData(hero))
    endif
    return 0
endfunction




//===========================================================================
function InitTrig_Escaper_functions takes nothing returns nothing
endfunction



endscope

//===========================================================================
// Trigger: Escaper disco
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
function ApplyRandomColor takes integer n returns nothing   
    local Escaper esc = udg_escapers.get(n)
    call esc.setBaseColorDisco(GetRandomInt(0, 12))
    call esc.setVcRed(GetRandomPercentageBJ())
    call esc.setVcGreen(GetRandomPercentageBJ())
    call esc.setVcBlue(GetRandomPercentageBJ())
    call esc.setVcTransparency(GetRandomReal(0, 25))
    call SetUnitVertexColorBJ(esc.getHero(), esc.getVcRed(), esc.getVcGreen(), esc.getVcBlue(), esc.getVcTransparency())
endfunction


function Disco_Actions takes nothing returns nothing
    local integer n = 0
    loop
        exitwhen (udg_escapers.get(n).discoTrigger == GetTriggeringTrigger())
            if (n > 11) then
                return
            endif
        set n = n + 1
    endloop
    call ApplyRandomColor(n)
endfunction


//===========================================================================
function InitTrig_Escaper_disco takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: Escaper
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope EscaperStruct

globals
	constant boolean SHOW_REVIVE_EFFECTS = false
endglobals


struct Escaper
	private player p
    private unit hero
	private unit invisUnit
    private real walkSpeed
    private real slideSpeed
    private integer baseColorId
	private integer cameraField
	private TerrainType lastTerrainType
	
	private trigger slide
	private trigger checkTerrain
	
    private real vcRed
    private real vcGreen
    private real vcBlue
    private real vcTransparency
    trigger discoTrigger
    private EscaperEffectArray effects
	private effect terrainKillEffect
    private effect meteorEffect
	
	private boolean godMode
	private boolean godModeKills
	private boolean walkSpeedAbsolute
	private boolean slideSpeedAbsolute
	private boolean canTeleportB
	private boolean hasAutoreviveB
	
	private boolean canCheatB
	private boolean isMaximaxouB
	private boolean isTrueMaximaxouB
    
    private Make make
    private MakeLastActions makeLastActions
    private Level makingLevel
	
	Level currentLevelTouchTerrainDeath //pour le terrain qui tue, vérifie s'il faut bien tuer l'escaper
	private item itemInInventory //créer le déclo pour save ça
    
    
    
//item method
    method resetItem takes nothing returns boolean //renvoie true si le héros portait un item
        if (UnitHasItemOfTypeBJ(.hero, METEOR_NORMAL)) then
            call Meteor(GetItemUserData(UnitItemInSlot(.hero, 0))).replace()
            call DestroyEffect(.meteorEffect)
            set .meteorEffect = null
            return true
        endif
        return false
    endmethod
    
    method addEffectMeteor takes nothing returns nothing
        if(.meteorEffect == null)then
            set .meteorEffect = AddSpecialEffectTarget("Abilities\\Weapons\\DemonHunterMissile\\DemonHunterMissile.mdl", .hero, "hand right")
        endif
    endmethod
    
    method removeEffectMeteor takes nothing returns nothing
        if(.meteorEffect != null)then
            call DestroyEffect(.meteorEffect)
            set .meteorEffect = null
        endif
    endmethod
    
//select method
    method selectHero takes nothing returns nothing
        call SelectUnitAddForPlayer(.hero, .p)
    endmethod
	
//creation method
	method createHero takes real x, real y, real angle returns boolean //retourne false si le héros existe déja
		if (.hero != null) then
			return false
		endif
		set .hero = CreateUnit(.p, HERO_TYPE_ID, x, y, angle)
        call SetUnitUserData(.hero, GetPlayerId(.p))
        call ShowUnit(.hero, false)
        call ShowUnit(.hero, true)
        call UnitRemoveAbility(.hero, 'Aloc')
		call SetUnitMoveSpeed(.hero, .walkSpeed) //voir pour le nom de la fonction
        call .selectHero()
        if (.baseColorId == 0) then
            call SetUnitColor(.hero, PLAYER_COLOR_RED)
        else
            call SetUnitColor(.hero, ConvertPlayerColor(.baseColorId))
        endif
        call SetUnitVertexColorBJ(.hero, .vcRed, .vcGreen, .vcBlue, .vcTransparency)
        call SpecialIllidan(.hero)
		set .invisUnit = CreateUnit(NEUTRAL_PLAYER, INVIS_UNIT_TYPE_ID, x, y, angle)
        call SetUnitUserData(.invisUnit, GetPlayerId(.p)) 
        call TriggerRegisterUnitEvent(gg_trg_InvisUnit_is_getting_damage, .invisUnit, EVENT_UNIT_DAMAGED)
        call .effects.showEffects(.hero)
        set .lastTerrainType = 0
        call TimerStart(afkModeTimers[GetPlayerId(.p)], timeMinAfk, false, GetAfkModeTimeExpiresCodeFromId(GetPlayerId(.p)))
        call InitShortcutSkills(GetPlayerId(.p))
        call EnableTrigger(.checkTerrain)
        return true
	endmethod
	
	method createHeroAtStart takes nothing returns boolean
		local real x
		local real y
		local Start start = udg_levels.getCurrentLevel().getStart()
        local real angle
		if (start == 0) then //si le départ du niveau en cours n'existe pas
			set start = DEPART_PAR_DEFAUT
            set angle = HERO_START_ANGLE
        else
            set angle = GetRandomDirectionDeg()
		endif
		set x = start.getRandomX()
		set y = start.getRandomY()
		return .createHero(x, y, angle)
	endmethod
	
	static method create takes integer playerId returns Escaper //ne crée pas le héros
		local Escaper e = Escaper.allocate()
		set e.p = Player(playerId)
		set e.walkSpeed = HERO_WALK_SPEED
		set e.slideSpeed = HERO_SLIDE_SPEED
		set e.baseColorId = playerId
		set e.slide = CreateSlideTrigger(playerId)
        set e.checkTerrain = CreateCheckTerrainTrigger(playerId)
        set e.cameraField = DEFAULT_CAMERA_FIELD
        call SetCameraFieldForPlayer(e.p, CAMERA_FIELD_TARGET_DISTANCE, I2R(e.cameraField), 0)
        set e.effects = EscaperEffectArray.create()
        set e.vcRed = 100
        set e.vcGreen = 100
        set e.vcBlue = 100
        set e.vcTransparency = 0
        set e.lastTerrainType = 0
        set e.makingLevel = 0
        set e.make = 0
        set e.makeLastActions = MakeLastActions.create(e)
        set e.godMode = false
        set e.godModeKills = false
        set e.walkSpeedAbsolute = false
        set e.slideSpeedAbsolute = false
        set e.canTeleportB = false
        set e.hasAutoreviveB = false
        set e.canCheatB = false
        set e.isMaximaxouB = false
        set e.isTrueMaximaxouB = false
        set e.discoTrigger = null
		return e
	endmethod    
	
	method removeHero takes nothing returns nothing
		if (.hero == null) then
			return
		endif
		call .resetItem()
        if (IsUnitAliveBJ(.hero)) then
            call KillUnit(.hero)
        endif
		call RemoveUnit(.hero)
		set .hero = null
		call RemoveUnit(.invisUnit)
		set .invisUnit = null
		set .lastTerrainType = 0
        call .make.destroy()
        set .make = 0
        call .effects.hideEffects()
        call DisableTrigger(.checkTerrain)
        call DisableTrigger(.slide)
	endmethod
	
	private method onDestroy takes nothing returns nothing
		call .removeHero()
		call DestroyEffect(.terrainKillEffect)
		set .terrainKillEffect = null
		call .effects.destroy()
		call DestroyTrigger(.slide)
		set .slide = null
		call DestroyTrigger(.checkTerrain)
		set .checkTerrain = null
        call DestroyTrigger(.discoTrigger)
        set .discoTrigger = null
        call udg_escapers.nullify(GetPlayerId(.p))
	endmethod
    
//getId method
    method getId takes nothing returns integer
        local integer i = 0
        loop
            exitwhen (i > 11)
                if (this == udg_escapers.get(i)) then
                    return i
                endif
            set i = i + 1
        endloop
        return -1
    endmethod		
			
//trigger methods
	method enableSlide takes boolean doEnable returns boolean
		if (IsTriggerEnabled(.slide) == doEnable) then
			return false
		endif
		if (doEnable) then
			call EnableTrigger(.slide)
			call StopUnit(.hero)
		else
			call DisableTrigger(.slide)
		endif
		return true
	endmethod
	
	method enableCheckTerrain takes boolean doEnable returns boolean
		if (IsTriggerEnabled(.checkTerrain) == doEnable) then
			return false
		endif
		if (doEnable) then
			call EnableTrigger(.checkTerrain)
		else
			call DisableTrigger(.checkTerrain)
		endif
		return true
	endmethod
    
    method isSliding takes nothing returns boolean
        return IsTriggerEnabled(.slide)
    endmethod
    
    method doesCheckTerrain takes nothing returns boolean
        return IsTriggerEnabled(.checkTerrain)
    endmethod
	
	
//move methods
	method moveHero takes real x, real y returns nothing
		call SetUnitX(.hero, x)
		call SetUnitY(.hero, y)
	endmethod
	
	method moveInvisUnit takes real x, real y returns nothing
		call SetUnitX(.invisUnit, x)
		call SetUnitY(.invisUnit, y)
	endmethod	
	
	
//hero methods
	method getHero takes nothing returns unit
		return .hero
	endmethod
	
	method isAlive takes nothing returns boolean
		return IsUnitAliveBJ(.hero)
	endmethod
	
	method isPaused takes nothing returns boolean
		return IsUnitPaused(.hero)
	endmethod
	
	method kill takes nothing returns boolean
		if (.isAlive()) then
			call .resetItem()
			call KillUnit(.hero)
			set .lastTerrainType = 0
            call ShowUnit(.invisUnit, false)
            call .enableSlide(false)
            call .enableCheckTerrain(false)
			return true
		endif
		return false
	endmethod
	
	method pause takes boolean doPause returns boolean
		if (.isPaused() == doPause) then
            return false
		endif
        call PauseUnit(.hero, doPause)
        return true
	endmethod
	
	method specialIllidan takes nothing returns nothing
		call SetUnitAnimation(.hero, "Morph Alternate")
	endmethod
	
	method revive takes real x, real y returns boolean
		if (.isAlive()) then
			return false
		endif
		call ReviveHero(.hero, x, y, SHOW_REVIVE_EFFECTS)
		call SetUnitX(.invisUnit, x)
		call SetUnitY(.invisUnit, y)
		call ShowUnit(.invisUnit, true)
		call .enableCheckTerrain(true)
		call .specialIllidan()
		call .selectHero()
        return true
	endmethod
	
	method reviveAtStart takes nothing returns boolean
		local real x = udg_levels.getCurrentLevel().getStartRandomX()
		local real y = udg_levels.getCurrentLevel().getStartRandomY()
		return .revive(x, y)
	endmethod
    
    method turnInstantly takes real angle returns nothing
        local TerrainType lastTerrainType = .lastTerrainType
        local real x = GetUnitX(.hero)
		local real y = GetUnitY(.hero)
        local item meteor = UnitItemInSlot(.hero, 0)
		call .removeHero()
        call .createHero(x, y, angle)
        set .lastTerrainType = lastTerrainType
        call SetUnitAnimation(.getHero(), "stand")
        if (meteor != null) then
            call UnitAddItem(.hero, meteor)
        endif
        set meteor = null
    endmethod
	
	method reverse takes nothing returns nothing
		local real angle = GetUnitFacing(.hero) + 180 //à vérifier
		call .turnInstantly(angle)
	endmethod
	
//effects methods
	method newEffect takes string efStr, string bodyPart returns nothing
		call .effects.new(efStr, .hero, bodyPart)
	endmethod
	
	method destroyLastEffects takes integer numEfToDestroy returns nothing
		call .effects.destroyLastEffects(numEfToDestroy)
	endmethod
	
	method hideEffects takes nothing returns nothing
		call .effects.hideEffects()
	endmethod
	
	method showEffects takes nothing returns nothing
		call .effects.showEffects(.hero)
	endmethod
	
//terrainKill methods
	method destroyTerrainKillEffect takes nothing returns nothing
		call DestroyEffect(.terrainKillEffect)
		set .terrainKillEffect = null
	endmethod
	
	method createTerrainKillEffect takes string killEffectStr returns nothing
		if (.terrainKillEffect != null) then
			call .destroyTerrainKillEffect()
		endif
		set .terrainKillEffect = AddSpecialEffectTarget( killEffectStr, .hero, TERRAIN_KILL_EFFECT_BODY_PART )
	endmethod
	
//lastTerrainType methods
	method getLastTerrainType takes nothing returns TerrainType
		return .lastTerrainType
	endmethod
	
    method setLastTerrainType takes TerrainType terrainType returns nothing
		set .lastTerrainType = terrainType
	endmethod
	
//speed methods
	method setSlideSpeed takes real slideSpeed returns nothing
		set .slideSpeed = slideSpeed
	endmethod
	
	method setWalkSpeed takes real walkSpeed returns nothing
		set .walkSpeed = walkSpeed
		call SetUnitMoveSpeed(.hero, walkSpeed)
	endmethod
	
	method getSlideSpeed takes nothing returns real
		return .slideSpeed
	endmethod
	
	method getWalkSpeed takes nothing returns real
		return .walkSpeed
	endmethod
	
	method isAbsoluteSlideSpeed takes nothing returns boolean
		return .slideSpeedAbsolute
	endmethod
	
	method absoluteSlideSpeed takes real slideSpeed returns nothing
		set .slideSpeedAbsolute = true
		set .slideSpeed = slideSpeed
	endmethod
	
	method stopAbsoluteSlideSpeed takes nothing returns nothing
		set .slideSpeedAbsolute = false
	endmethod
	
	method isAbsoluteWalkSpeed takes nothing returns boolean
		return .walkSpeedAbsolute
	endmethod
	
	method absoluteWalkSpeed takes real walkSpeed returns nothing
		set .walkSpeedAbsolute = true
		call .setWalkSpeed( walkSpeed )
	endmethod
	
	method stopAbsoluteWalkSpeed takes nothing returns nothing
		set .walkSpeedAbsolute = false
	endmethod
	
//godMode methods    
    method setGodMode takes boolean godMode returns nothing
        set .godMode = godMode
    endmethod
    
    method setGodModeKills takes boolean godModeKills returns nothing
        set .godModeKills = godModeKills
    endmethod
	
	method isGodModeOn takes nothing returns boolean
		return .godMode
	endmethod

	method doesGodModeKills takes nothing returns boolean
		return .godModeKills
	endmethod
	
//color methods
	method setBaseColor takes integer baseColorId returns boolean
        if (baseColorId < 0 or baseColorId > 12) then
            return false
        endif
		set .baseColorId = baseColorId
		if (.hero != null) then
            if (baseColorId == 0) then
                call SetUnitColor(.hero, PLAYER_COLOR_RED)
            else
                call SetUnitColor(.hero, ConvertPlayerColor(baseColorId))
            endif
		endif
        call ColorInfo(this, .p)
        return true
	endmethod
    
	method setBaseColorDisco takes integer baseColorId returns boolean
        if (baseColorId < 0 or baseColorId > 12) then
            return false
        endif
		set .baseColorId = baseColorId
		if (.hero != null) then
            if (baseColorId == 0) then
                call SetUnitColor(.hero, PLAYER_COLOR_RED)
            else
                call SetUnitColor(.hero, ConvertPlayerColor(baseColorId))
            endif
		endif
        return true
	endmethod
    
    method getBaseColor takes nothing returns integer
        return .baseColorId
    endmethod
	
	method setVcRed takes real vcRed returns boolean
        if (vcRed < 0 or vcRed > 100) then
            return false
        endif
		set .vcRed = vcRed
        return true
	endmethod
	
	method setVcGreen takes real vcGreen returns boolean
        if (vcGreen < 0 or vcGreen > 100) then
            return false
        endif
		set .vcGreen = vcGreen
        return true
	endmethod
	
	method setVcBlue takes real vcBlue returns boolean
        if (vcBlue < 0 or vcBlue > 100) then
            return false
        endif
		set .vcBlue = vcBlue
        return true
	endmethod
	
	method setVcTransparency takes real vcTransparency returns boolean
        if (vcTransparency < 0 or vcTransparency > 100) then
            return false
        endif
		set .vcTransparency = vcTransparency
        return true
	endmethod
	
	method getVcRed takes nothing returns real
		return .vcRed
	endmethod
	
	method getVcGreen takes nothing returns real
		return .vcGreen
	endmethod
	
	method getVcBlue takes nothing returns real
		return .vcBlue
	endmethod
	
	method getVcTransparency takes nothing returns real
		return .vcTransparency
	endmethod
	
	method refreshVertexColor takes nothing returns nothing
		call SetUnitVertexColorBJ(.hero, .vcRed, .vcGreen, .vcBlue, .vcTransparency)
		call ColorInfo(this, .p)
	endmethod
	
//cheat methods
	method setCanCheat takes boolean canCheat returns nothing
        if (not canCheat) then
            set .isMaximaxouB = false
            set .isTrueMaximaxouB = false
        endif
		set .canCheatB = canCheat
	endmethod
	
	method setIsMaximaxou takes boolean isMaximaxou returns nothing
		if (isMaximaxou) then
			call .setCanCheat(true)
        else
            set .isTrueMaximaxouB = false
		endif
		set .isMaximaxouB = isMaximaxou
	endmethod
	
	method setIsTrueMaximaxou takes boolean isTrueMaximaxou returns nothing
		if (isTrueMaximaxou) then
			call .setIsMaximaxou(true)
		endif
		set .isTrueMaximaxouB = isTrueMaximaxou
	endmethod
	
	method canCheat takes nothing returns boolean
		return .canCheatB
	endmethod
	
	method isMaximaxou takes nothing returns boolean
		return .isMaximaxouB
	endmethod
	
	method isTrueMaximaxou takes nothing returns boolean
		return .isTrueMaximaxouB
	endmethod
	
    
//autres
	method getPlayer takes nothing returns player
		return .p
	endmethod
	
	method setCameraField takes integer cameraField returns nothing
		set .cameraField = cameraField
		call SetCameraFieldForPlayer(.p, CAMERA_FIELD_TARGET_DISTANCE, I2R(cameraField), 0)
	endmethod
    
    method getCameraField takes nothing returns integer
        return .cameraField
    endmethod
    
    method resetCamera takes nothing returns nothing
        call ResetToGameCameraForPlayer(.p, 0)
        call SetCameraFieldForPlayer(.p, CAMERA_FIELD_TARGET_DISTANCE, .cameraField, 0 )
    endmethod

	method kick takes Escaper kicked returns nothing
		call CustomDefeatBJ(kicked.getPlayer(), "You have been kicked by " + GetPlayerName(.p) + " !")
        call Text_A(udg_colorCode[GetPlayerId(kicked.getPlayer())] + GetPlayerName(kicked.getPlayer()) + " has been kicked by " + udg_colorCode[GetPlayerId(.p)] + GetPlayerName(.p) + " !")
		call .destroy()
	endmethod
	
    
//teleport methods
	method setCanTeleport takes boolean canTeleport returns nothing
		set .canTeleportB = canTeleport
	endmethod
	
	method canTeleport takes nothing returns boolean
		return .canTeleportB
	endmethod
	
    
//autorevive methods
	method hasAutorevive takes nothing returns boolean
		return .hasAutoreviveB
	endmethod
	
	method setHasAutorevive takes boolean hasAutorevive returns nothing
		set .hasAutoreviveB = hasAutorevive
	endmethod
    
    
//make methods
    method getMake takes nothing returns Make
        return .make
    endmethod
    
    method destroyMakeIfForSpecificLevel takes nothing returns nothing
        local boolean doDestroy
        if (.make != 0) then
            set doDestroy = (.make.getType() == MakeMonsterNoMove.typeid)
            set doDestroy = doDestroy or (.make.getType() == MakeMonsterSimplePatrol.typeid)
            set doDestroy = doDestroy or (.make.getType() == MakeMonsterMultiplePatrols.typeid)
            set doDestroy = doDestroy or (.make.getType() == MakeDeleteMonsters.typeid)
            set doDestroy = doDestroy or (.make.getType() == MakeMeteor.typeid)
            set doDestroy = doDestroy or (.make.getType() == MakeDeleteMeteors.typeid)
            set doDestroy = doDestroy or (.make.getType() == MakeStart.typeid)
            set doDestroy = doDestroy or (.make.getType() == MakeEnd.typeid)
            set doDestroy = doDestroy or (.make.getType() == MakeVisibilityModifier.typeid)
            if (doDestroy) then
                call .destroyMake()
            endif
        endif
    endmethod
    
    method setMakingLevel takes Level level returns boolean
        local Level oldMakingLevel
        if (.makingLevel == level) then
            return false
        endif
        set oldMakingLevel = .makingLevel
        set .makingLevel = level
        call .destroyMakeIfForSpecificLevel()
        if (not IsLevelBeingMade(oldMakingLevel)) then
            call oldMakingLevel.activate(false)
            if (udg_levels.getCurrentLevel().getId() < oldMakingLevel.getId()) then
                call oldMakingLevel.activateVisibilities(false)
            endif
        endif
        set Level_earningLivesActivated = false
        call level.activate(true)
        set Level_earningLivesActivated = true
        return true
    endmethod
    
    method getMakingLevel takes nothing returns Level
        if (.makingLevel == 0) then
            return udg_levels.getCurrentLevel()
        endif
        return .makingLevel
    endmethod
    
    method isMakingCurrentLevel takes nothing returns boolean
        return (.makingLevel == 0)
    endmethod
    
    method destroyMake takes nothing returns boolean
        if (.make == 0) then
            return false
        endif
        call .make.destroy()
        set .make = 0
        return true
    endmethod
    
    method makeCreateNoMoveMonsters takes MonsterType mt, real facingAngle returns nothing
        //mode : noMove
        call .destroyMake()
        set .make = MakeMonsterNoMove.create(.hero, mt, facingAngle)
    endmethod
    
	method makeCreateSimplePatrolMonsters takes string mode, MonsterType mt returns nothing
        call .destroyMake()
		//modes : normal, string, auto
		if (mode == "normal" or mode == "string" or mode == "auto") then
			set .make = MakeMonsterSimplePatrol.create(.hero, mode, mt)
		endif
	endmethod	
    
	method makeCreateMultiplePatrolsMonsters takes string mode, MonsterType mt returns nothing
        call .destroyMake()
        //modes : normal, string
		if (mode == "normal" or mode == "string") then
			set .make = MakeMonsterMultiplePatrols.create(.hero, mode, mt)
		endif
	endmethod	
    
    method makeMmpNext takes nothing returns boolean
        if (not(.make.getType() == MakeMonsterMultiplePatrols.typeid)) then
            return false
        endif
        call MakeMonsterMultiplePatrols(integer(.make)).nextMonster()
        return true
    endmethod
    
    method makeCreateMonsterSpawn takes string label, MonsterType mt, string sens, real frequence returns nothing
        call .destroyMake()
        set .make = MakeMonsterSpawn.create(.hero, label, mt, sens, frequence)
    endmethod
	
	method makeDeleteMonsters takes string mode returns nothing
		call .destroyMake()
		//delete modes : all, noMove, move, simplePatrol, multiplePatrols, oneByOne
		if (mode != "all" and mode != "noMove" and mode != "move" and mode != "simplePatrol" and mode != "multiplePatrols" and mode != "oneByOne") then
			return
		endif
		set .make = MakeDeleteMonsters.create(.hero, mode)
	endmethod
    
    method makeCreateMeteor takes nothing returns nothing
        call .destroyMake()
        set .make = MakeMeteor.create(.hero)
    endmethod
	
	method makeDeleteMeteors takes string mode returns nothing
		call .destroyMake()
		//delete modes : oneByOne, twoClics
		if (mode != "oneByOne" and mode != "twoClics") then
			return
		endif
		set .make = MakeDeleteMeteors.create(.hero, mode)
	endmethod
    
    method makeCreateTerrain takes TerrainType terrainType returns nothing
        call .destroyMake()
        set .make = MakeTerrainCreate.create(.hero, terrainType)    
    endmethod
    
    method makeTerrainCopyPaste takes nothing returns nothing
        call .destroyMake()
        set .make = MakeTerrainCopyPaste.create(.hero)
    endmethod
    
    method makeTerrainVerticalSymmetry takes nothing returns nothing
        call .destroyMake()
        set .make = MakeTerrainVerticalSymmetry.create(.hero)
    endmethod
    
    method makeTerrainHorizontalSymmetry takes nothing returns nothing
        call .destroyMake()
        set .make = MakeTerrainHorizontalSymmetry.create(.hero)
    endmethod
    
    method makeGetTerrainType takes nothing returns nothing
        call .destroyMake()
        set .make = MakeGetTerrainType.create(.hero)    
    endmethod
    
    method makeExchangeTerrains takes nothing returns nothing
        call .destroyMake()
        set .make = MakeExchangeTerrains.create(.hero)    
    endmethod  
    
    method makeCreateStart takes boolean forNext returns nothing
        call .destroyMake()
        set .make = MakeStart.create(.hero, forNext)
    endmethod 
    
    method makeCreateEnd takes nothing returns nothing
        call .destroyMake()
        set .make = MakeEnd.create(.hero)
    endmethod
    
    method makeCreateVisibilityModifier takes nothing returns nothing
        call .destroyMake()
        set .make = MakeVisibilityModifier.create(.hero)
    endmethod
    
    method cancelLastAction takes nothing returns boolean
        if (.make != 0) then
            if (.make.cancelLastAction()) then
                return true
            endif
        endif
        return .makeLastActions.cancelLastAction()
    endmethod
    
    method redoLastAction takes nothing returns boolean
        if (.makeLastActions.redoLastAction()) then
            return true
        endif
        if (.make != 0) then
            return .make.redoLastAction()
        endif
        return false
    endmethod
    
    method deleteSpecificActionsForLevel takes Level level returns nothing
        call .makeLastActions.deleteSpecificActionsForLevel(level)
    endmethod
    
    method newAction takes MakeAction action returns MakeAction
        return .makeLastActions.newAction(action)
    endmethod
    
    method destroyAllSavedActions takes nothing returns nothing
        call .makeLastActions.destroyAllActions()
    endmethod
    
    method destroyCancelledActions takes nothing returns nothing
        call .makeLastActions.destroyCancelledActions()
    endmethod
endstruct






//===========================================================================
function InitTrig_Escaper takes nothing returns nothing
endfunction




endscope//===========================================================================
// Trigger: EscaperArray
//===========================================================================
//TESH.scrollpos=54
//TESH.alwaysfold=0
scope EscaperArray


struct EscaperArray
	private Escaper array escapers [12]
	
	static method create takes nothing returns EscaperArray
		local EscaperArray e = EscaperArray.allocate()
		local integer playerId = 0
		loop
			exitwhen (playerId > 11)
				if (IsPlayerInGame(Player(playerId))) then
					set e.escapers[playerId] = Escaper.create(playerId)
				else
                    set e.escapers[playerId] = 0
                endif
			set playerId = playerId + 1
		endloop
		return e
	endmethod
    
    method newAt takes integer id returns nothing
        if (id < 0 or id > 11) then
            return
        endif
        if (.escapers[id] != 0) then
            return
        endif
        set .escapers[id] = Escaper.create(id)
    endmethod
	
	method count takes nothing returns integer
		local integer n = 0
		local integer i = 0
		loop
			exitwhen (i > 11)
				if (.escapers[i] != 0) then
					set n = n + 1
				endif
			set i = i + 1
		endloop
		return n
	endmethod
    
    method get takes integer id returns Escaper
        return .escapers[id]
    endmethod
    
    method nullify takes integer id returns nothing
        set .escapers[id] = 0
    endmethod
    
    method remove takes integer id returns nothing
        call .escapers[id].destroy()
        set .escapers[id] = 0
    endmethod
    
    method deleteSpecificActionsForLevel takes Level level returns nothing
        local integer i = 0
        loop
            exitwhen (i > 11)
                if (.escapers[i] != 0) then
                    call .escapers[i].deleteSpecificActionsForLevel(level)
                endif
            set i = i + 1
        endloop
    endmethod
    
    method destroyMakesIfForSpecificLevel_currentLevel takes nothing returns nothing
        //destroy le make des escapers si c'est un make pour spécifique level et que l'escaper make pour le "current_level"
        local boolean doDestroy
        local integer i = 0
        loop
            exitwhen (i > 11)
                if (.escapers[i] != 0 and .escapers[i].isMakingCurrentLevel()) then
                    call .escapers[i].destroyMakeIfForSpecificLevel()
                endif
            set i = i + 1
        endloop
    endmethod
endstruct



endscope

//===========================================================================
function InitTrig_EscaperArray takes nothing returns nothing
endfunction



endlibrary//===========================================================================
// Trigger: EscaperSavedCommands
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library EscaperSavedCommands needs CommandExecution


globals
    EscaperSavedCommands udg_savedCommands
endglobals


struct EscaperSavedCommands
    private hashtable savedCommands
    
    
    static method create takes nothing returns EscaperSavedCommands
        local EscaperSavedCommands sc = EscaperSavedCommands.allocate()
        set sc.savedCommands = InitHashtable()
        return sc
    endmethod
    
    method new takes Escaper escaper, string commandName, string command returns nothing
        call SaveStr(.savedCommands, escaper, StringHash(commandName), command)
    endmethod
    
    method execute takes Escaper escaper, string commandName returns boolean
        local string cmd = LoadStr(.savedCommands, escaper, StringHash(commandName))
        if (cmd == null) then
            return false
        else
            call ExecuteCommand(escaper, cmd)
        endif
        return true
    endmethod
endstruct



//===========================================================================
function InitTrig_EscaperSavedCommands takes nothing returns nothing
    set udg_savedCommands = EscaperSavedCommands.create()
endfunction



endlibrary//===========================================================================
// Trigger: Make
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library Make needs MMNoMoveActions, MMSimplePatrolActions, MMMultiplePatrolsActions, MonsterSpawnMakingActions, MonsterDeleteActions, TerrainMakingActions, GettingTerrainTypeInfoActions, MakeExchangeTerrainsActions, StartMakingActions, EndMakingActions, VisibilityModifierMakingActions, TerrainCopyPasteActions, TerrainVerticalSymmetryActions, TerrainHorizontalSymmetryActions, MeteorMakingActions, MeteorDeleteActions

globals
	constant integer MAKE_LAST_CLIC_UNIT_ID = 'e001' //à remplacer par l'id de l'unité choisie (need couleur variable)
	constant string MAKE_CANT_CANCEL_MORE = "Nothing else to cancel !"
	constant string MAKE_CANT_REDO_MORE = "Nothing else to redo !"
endglobals


interface Make
    player makerOwner
    string kind //monsterMaking, monsterDeleting...
    trigger t
    unit maker
    method cancelLastAction takes nothing returns boolean
    method redoLastAction takes nothing returns boolean
endinterface


public function GetActions takes string kind returns code
    if (kind == "monsterCreateNoMove") then
        return function MonsterMakingNoMove_Actions
    endif
    if (kind == "monsterCreateSimplePatrol") then
        return function MonsterMakingSimplePatrol_Actions
    endif
    if (kind == "monsterCreateMultiplePatrols") then
        return function MonsterMakingMultiplePatrols_Actions
    endif
    if (kind == "monsterSpawnCreate") then
        return function MonsterSpawnMaking_Actions
    endif
    if (kind == "deleteMonsters") then
        return function MonsterDelete_Actions
    endif
    if (kind == "meteorCreate") then
        return function MeteorMaking_Actions
    endif
    if (kind == "deleteMeteors") then
        return function MeteorDelete_Actions
    endif
    if (kind == "terrainCreate") then
        return function TerrainMaking_Actions
    endif
    if (kind == "terrainCopyPaste") then
        return function TerrainCopyPaste_Actions
    endif
    if (kind == "terrainVerticalSymmetry") then
        return function TerrainVerticalSymmetry_Actions
    endif
    if (kind == "terrainHorizontalSymmetry") then
        return function TerrainHorizontalSymmetry_Actions
    endif
    if (kind == "getTerrainType") then
        return function GettingTerrainTypeInfo_Actions
    endif
    if (kind == "exchangeTerrains") then
        return function MakeExchangeTerrains_Actions
    endif
    if (kind == "startCreate") then
        return function StartMaking_Actions
    endif
    if (kind == "endCreate") then
        return function EndMaking_Actions
    endif
    if (kind == "visibilityModifierCreate") then
        return function VisibilityModifierMaking_Actions
    endif
    return null
endfunction



//===========================================================================
function InitTrig_Make takes nothing returns nothing
endfunction


endlibrary


//===========================================================================
// Trigger: Monster making no move Actions
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library MMNoMoveActions needs BasicFunctions, Escaper

function MonsterMakingNoMove_Actions takes nothing returns nothing
    local Monster monster
    local Escaper escaper = Hero2Escaper(GetTriggerUnit())
    local Make mkGeneral = escaper.getMake()
	local MakeMonsterNoMove mk = MakeMonsterNoMove(integer(mkGeneral))
    local real x = GetOrderPointX()
    local real y = GetOrderPointY()

    if (not IsIssuedOrder("smart")) then
        return
    endif
    call StopUnit(mk.maker)
    
    set monster = escaper.getMakingLevel().monstersNoMove.new(mk.getMonsterType(), x, y, mk.getFacingAngle(), true)
    call escaper.newAction(MakeMonsterAction.create(escaper.getMakingLevel(), monster))
endfunction




//===========================================================================
function InitTrig_Monster_making_no_move_Actions takes nothing returns nothing
endfunction


endlibrary//===========================================================================
// Trigger: MakeMonsterNoMove
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library MakeMonsterNoMove needs Make




struct MakeMonsterNoMove extends Make    
    private MonsterType mt
    private real facingAngle
    
    method getMonsterType takes nothing returns MonsterType
        return .mt
    endmethod
    
    method getFacingAngle takes nothing returns real
        return .facingAngle
    endmethod
	
	static method create takes unit maker, MonsterType mt, real facingAngle returns MakeMonsterNoMove
        local MakeMonsterNoMove m
		if (maker == null or mt == 0) then
			return 0
		endif
        set m = MakeMonsterNoMove.allocate()
        set m.maker = maker
        set m.kind = "monsterCreateNoMove"
        set m.mt = mt
        set m.facingAngle = facingAngle
        set m.t = CreateTrigger()
        call TriggerAddAction(m.t, Make_GetActions(m.kind))
        call TriggerRegisterUnitEvent(m.t, m.maker, EVENT_UNIT_ISSUED_POINT_ORDER)
        return m
    endmethod
    
    method onDestroy takes nothing returns nothing
		call DestroyTrigger(.t)
		set .t = null
		set .maker = null
	endmethod
	
	method cancelLastAction takes nothing returns boolean
        return false
	endmethod
	
	method redoLastAction takes nothing returns boolean
        return false
	endmethod	
endstruct
	
	
	
	
endlibrary
	


//===========================================================================
function InitTrig_MakeMonsterNoMove takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: Monster making simple patrol Actions
//===========================================================================
//TESH.scrollpos=63
//TESH.alwaysfold=0
library MMSimplePatrolActions needs TerrainTypeFunctions, Escaper

globals
    private constant real MIN_DIST = 5
    private constant real MAX_DIST = 2000
    private constant real ECART_DIST = 32
    private constant real ECART_ANGLE = 9
    private constant real DIST_ON_TERRAIN_MAX = 300
    private constant real DIST_ON_TERRAIN_DEFAULT = 50
    private real distOnTerrain = 50
endglobals


function MakeSimplePatrolAuto_ChangeDistOnTerrain takes real newDist returns boolean
    if (newDist < 0 or newDist > DIST_ON_TERRAIN_MAX) then
        return false
    endif
    set distOnTerrain = newDist
    return true
endfunction

function MakeSimplePatrolAuto_ChangeDistOnTerrainDefault takes nothing returns nothing
    set distOnTerrain = DIST_ON_TERRAIN_DEFAULT
endfunction


function MonsterMakingSimplePatrol_Actions takes nothing returns nothing
    local Monster monster
    local Escaper escaper = Hero2Escaper(GetTriggerUnit())
    local Make mkGeneral = escaper.getMake()
	local MakeMonsterSimplePatrol mk = MakeMonsterSimplePatrol(integer(mkGeneral))
    local real x = GetOrderPointX()
    local real y = GetOrderPointY()
    
    local real x1
    local real y1
    local real x2
    local real y2
    local real dist
    local real angle 
    local boolean found
    
    if (not IsIssuedOrder("smart")) then   
        return
    endif
    call StopUnit(mk.maker)
	
	
	if (mk.getMode() == "normal") then
		if (mk.isLastLocSavedUsed()) then
            if (GetLocDist(mk.lastX, mk.lastY, x, y) <= PATROL_DISTANCE_MIN) then
                call Text_erP(mk.makerOwner, "Too close to the start location !")
                return
            else
                set monster = escaper.getMakingLevel().monstersSimplePatrol.new(mk.getMonsterType(), mk.lastX, mk.lastY, x, y, true)
                call escaper.newAction(MakeMonsterAction.create(escaper.getMakingLevel(), monster))
                call mk.unsaveLocDefinitely()
            endif
		else
			call mk.saveLoc(x, y)
		endif
	endif
    
	
	if (mk.getMode() == "string") then
		if (mk.isLastLocSavedUsed()) then
            if (GetLocDist(mk.lastX, mk.lastY, x, y) <= PATROL_DISTANCE_MIN) then
                call Text_erP(mk.makerOwner, "Too close to the start location !")
                return
            else
                set monster = escaper.getMakingLevel().monstersSimplePatrol.new(mk.getMonsterType(), mk.lastX, mk.lastY, x, y, true)
                call escaper.newAction(MakeMonsterAction.create(escaper.getMakingLevel(), monster))
                call mk.unsaveLoc()
            endif
        endif
		call mk.saveLoc(x, y)
	endif
    
    
    if (mk.getMode() == "auto") then
        if (IsTerrainTypeOfKind(GetTerrainType(x, y), "death")) then
            call Text_erP(mk.makerOwner, "You clicked on a death terrain !")
            return
        endif
        
        //find approximatively first location
        set found = false
        set dist = MIN_DIST
        loop
            exitwhen (found or dist > MAX_DIST)
                set angle = 0
                set x1 = x + dist * CosBJ(angle)
                set y1 = y + dist * SinBJ(angle)
                set found = IsTerrainTypeOfKind(GetTerrainType(x1, y1), "death")
                exitwhen found
                
                set angle = 90
                set x1 = x + dist * CosBJ(angle)
                set y1 = y + dist * SinBJ(angle)
                set found = IsTerrainTypeOfKind(GetTerrainType(x1, y1), "death")
                exitwhen found
                
                set angle = 180
                set x1 = x + dist * CosBJ(angle)
                set y1 = y + dist * SinBJ(angle)
                set found = IsTerrainTypeOfKind(GetTerrainType(x1, y1), "death")
                exitwhen found
                
                set angle = 270
                set x1 = x + dist * CosBJ(angle)
                set y1 = y + dist * SinBJ(angle)
                set found = IsTerrainTypeOfKind(GetTerrainType(x1, y1), "death")
                exitwhen found
                
                set angle = 1
                loop
                    exitwhen (found or angle >= 360)
                        set x1 = x + dist * CosBJ(angle)
                        set y1 = y + dist * SinBJ(angle)
                        set found = IsTerrainTypeOfKind(GetTerrainType(x1, y1), "death")
                    set angle = angle + ECART_ANGLE
                endloop
                set angle = angle - ECART_ANGLE
                
            set dist = dist + ECART_DIST
        endloop
        
        //first location not found
        if (not found) then
            call Text_erP(mk.makerOwner, "Death terrain too far !")
            return
        endif
        
        //precise position of first location
        loop
            exitwhen (not IsTerrainTypeOfKind(GetTerrainType(x1, y1), "death"))
            set dist = dist - 1
                set x1 = x + dist * CosBJ(angle)
                set y1 = y + dist * SinBJ(angle)
        endloop
        set dist = dist + distOnTerrain + 1
        set x1 = x + dist * CosBJ(angle)
        set y1 = y + dist * SinBJ(angle)
        
        //prepare angle for the second location
        if (angle >= 180) then
            set angle = angle - 180
        else
            set angle = angle + 180
        endif
        
        //find approximatively second location
        set found = false
        set dist = MIN_DIST
        loop
            exitwhen (found or dist > MAX_DIST)
                set x2 = x + dist * CosBJ(angle)
                set y2 = y + dist * SinBJ(angle)        
                set found = IsTerrainTypeOfKind(GetTerrainType(x2, y2), "death")
            set dist = dist + ECART_DIST
        endloop
        
        //second location not found
        if (not found) then
            call Text_erP(mk.makerOwner, "Death terrain too far for the second location !")
            return
        endif
        
        //precise position of second location
        loop
            exitwhen (not IsTerrainTypeOfKind(GetTerrainType(x2, y2), "death"))
            set dist = dist - 1
                set x2 = x + dist * CosBJ(angle)
                set y2 = y + dist * SinBJ(angle)
        endloop
        set dist = dist + distOnTerrain + 1
        set x2 = x + dist * CosBJ(angle)
        set y2 = y + dist * SinBJ(angle)
        
        //the two locations were found, creating monster
        set monster = escaper.getMakingLevel().monstersSimplePatrol.new(mk.getMonsterType(), x1, y1, x2, y2, true)
        call escaper.newAction(MakeMonsterAction.create(escaper.getMakingLevel(), monster))
    endif
endfunction




//===========================================================================
function InitTrig_Monster_making_simple_patrol_Actions takes nothing returns nothing
endfunction


endlibrary

//===========================================================================
// Trigger: MakeMonsterSimplePatrol
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library MakeMonsterSimplePatrol needs Make



struct MakeMonsterSimplePatrol extends Make
    private string mode
	private MonsterType mt
    real lastX
    real lastY
    private boolean lastLocIsSaved
	private boolean lastLocSavedIsUsed
    private unit unitLastClic
	
	method getMonsterType takes nothing returns MonsterType
        return .mt
    endmethod
    
	static method create takes unit maker, string mode, MonsterType mt returns MakeMonsterSimplePatrol
        local MakeMonsterSimplePatrol m
		if (maker == null or (mode != "normal" and mode != "string" and mode != "auto") or mt == 0) then
			return 0
		endif
        set m = MakeMonsterSimplePatrol.allocate()
        set m.maker = maker
		set m.makerOwner = GetOwningPlayer(maker)
        set m.kind = "monsterCreateSimplePatrol"
        set m.mode = mode
        set m.mt = mt
        set m.t = CreateTrigger()
        call TriggerAddAction(m.t, Make_GetActions(m.kind))
        call TriggerRegisterUnitEvent(m.t, maker, EVENT_UNIT_ISSUED_POINT_ORDER)
        set m.lastLocIsSaved = false
        set m.lastLocSavedIsUsed = false
        return m
    endmethod
    
    method onDestroy takes nothing returns nothing
		call DestroyTrigger(.t)
		set .t = null
		call RemoveUnit(.unitLastClic)
		set .unitLastClic = null
		set .maker = null
	endmethod	
	
	method saveLoc takes real x, real y returns nothing
		set .lastX = x
		set .lastY = y
        set .lastLocIsSaved = true
		set .lastLocSavedIsUsed = true
		if (.unitLastClic == null) then
			set .unitLastClic = CreateUnit(.makerOwner, MAKE_LAST_CLIC_UNIT_ID, x, y, GetRandomDirectionDeg())
		else
			call SetUnitX(.unitLastClic, x)
			call SetUnitY(.unitLastClic, y)
		endif
        call Hero2Escaper(.maker).destroyCancelledActions()
	endmethod
	
	method unsaveLoc takes nothing returns boolean
		if (not .lastLocSavedIsUsed) then
			return false
		endif
		call RemoveUnit(.unitLastClic)
		set .unitLastClic = null
		set .lastLocSavedIsUsed = false
		return true
	endmethod
    
    method unsaveLocDefinitely takes nothing returns nothing
        call .unsaveLoc()
        set .lastLocIsSaved = false
    endmethod
	
	method isLastLocSavedUsed takes nothing returns boolean
		return .lastLocSavedIsUsed
	endmethod
	
	method cancelLastAction takes nothing returns boolean
		return .unsaveLoc()
	endmethod
	
	method redoLastAction takes nothing returns boolean
		if (.lastLocIsSaved and not .lastLocSavedIsUsed) then
            call .saveLoc(.lastX, .lastY)
            return true
        endif
        return false
	endmethod	
    
    method getMode takes nothing returns string
        return .mode
    endmethod
endstruct
	
	
	
endlibrary




//============================================================
function InitTrig_MakeMonsterSimplePatrol takes nothing returns nothing
endfunction
	

//===========================================================================
// Trigger: Monster making multiple patrols Actions
//===========================================================================
//TESH.scrollpos=4
//TESH.alwaysfold=0
library MMMultiplePatrolsActions needs BasicFunctions, Escaper


function MonsterMakingMultiplePatrols_Actions takes nothing returns nothing
    local Escaper escaper = Hero2Escaper(GetTriggerUnit())
    local Make mkGeneral = escaper.getMake()
	local MakeMonsterMultiplePatrols mk = MakeMonsterMultiplePatrols(integer(mkGeneral))
    local real x = GetOrderPointX()
    local real y = GetOrderPointY()
    local integer erreur

    if (not IsIssuedOrder("smart")) then
        return
    endif
    call StopUnit(mk.maker)
    
	
	if (mk.getLocPointeur() >= 0) then
        set erreur = mk.getMonster().addNewLoc(x, y)
        if (erreur > 0) then
            if (erreur == 3) then
                call Text_erP(mk.makerOwner, "Number limit of patrol locations reached for this monster ! ( " + I2S(MonsterMultiplePatrols.NB_MAX_LOC) + " )")
            endif
            if (erreur == 2) then
                call Text_erP(mk.makerOwner, "Too close to the last location !")
            endif
            if (erreur == 1) then
                call Text_erP(mk.makerOwner, "Too close to the first location !")
            endif
        else
			call mk.saveLoc(x, y)
		endif		
	else
		call MonsterMultiplePatrols.destroyLocs()
		call MonsterMultiplePatrols.storeNewLoc(x, y)
		call mk.saveLoc(x, y)
		call mk.setMonster(escaper.getMakingLevel().monstersMultiplePatrols.new(mk.getMonsterType(), mk.getMode(), true))
	endif
endfunction




//===========================================================================
function InitTrig_Monster_making_multiple_patrols_Actions takes nothing returns nothing
endfunction



endlibrary

//===========================================================================
// Trigger: MakeMonsterMultiplePatrols
//===========================================================================
//TESH.scrollpos=56
//TESH.alwaysfold=0
library MakeMonsterMultiplePatrols needs Make



struct MakeMonsterMultiplePatrols extends Make
    private MonsterType mt
    private string mode //normal ou string
    private real array lastX [20]
    private real array lastY [20]
	private integer lastLocId
	private integer locPointeur
    private unit unitLastClic
    private MonsterMultiplePatrols monster
    
	method getMonsterType takes nothing returns MonsterType
        return .mt
    endmethod
    
    method getMode takes nothing returns string
        return .mode
    endmethod
    
    method getMonster takes nothing returns MonsterMultiplePatrols
        return .monster
    endmethod
	
	static method create takes unit maker, string mode, MonsterType mt returns MakeMonsterMultiplePatrols
        local MakeMonsterMultiplePatrols m
		if (maker == null or mt == 0 or (mode != "normal" and mode != "string")) then
			return 0
		endif
        set m = MakeMonsterMultiplePatrols.allocate()
        set m.maker = maker
		set m.makerOwner = GetOwningPlayer(maker)
        set m.kind = "monsterCreateMultiplePatrols"
        set m.mt = mt
        set m.mode = mode
        set m.monster = 0
        set m.t = CreateTrigger()
        call TriggerAddAction(m.t, Make_GetActions(m.kind))
        call TriggerRegisterUnitEvent(m.t, m.maker, EVENT_UNIT_ISSUED_POINT_ORDER)
		set m.lastLocId = -1
		set m.locPointeur = -1
        return m
    endmethod
    
    method onDestroy takes nothing returns nothing
        local Escaper escaper
        if (.monster != 0 and .monster.u != null) then
            set escaper = Hero2Escaper(.maker)
            call escaper.newAction(MakeMonsterAction.create(escaper.getMakingLevel(), .monster))
        else
            call .monster.destroy()
        endif
		call DestroyTrigger(.t)
		set .t = null
		call RemoveUnit(.unitLastClic)
		set .unitLastClic = null
		set .maker = null
	endmethod	
    
    method nextMonster takes nothing returns nothing
        local Escaper escaper
        set .lastLocId = -1
        set .locPointeur = -1
		call RemoveUnit(.unitLastClic)
		set .unitLastClic = null
        if (.monster != 0 and .monster.u != null) then
            set escaper = Hero2Escaper(.maker)
            call escaper.newAction(MakeMonsterAction.create(escaper.getMakingLevel(), .monster))
        else
            call .monster.destroy()
        endif
        set .monster = 0
    endmethod
	
	method getLocPointeur takes nothing returns integer
		return .locPointeur
	endmethod
    
    method setUnitLastClicPosition takes real x, real y returns nothing
        if (.unitLastClic == null) then
			set .unitLastClic = CreateUnit(.makerOwner, MAKE_LAST_CLIC_UNIT_ID, x, y, GetRandomDirectionDeg())
		else
			call SetUnitX(.unitLastClic, x)
			call SetUnitY(.unitLastClic, y)
		endif
    endmethod
	
	method saveLoc takes real x, real y returns nothing
		if (.locPointeur > 19) then
			return
		endif
		set .locPointeur = .locPointeur + 1
		set .lastX[.locPointeur] = x
		set .lastY[.locPointeur] = y
		set .lastLocId = .locPointeur
		call .setUnitLastClicPosition(x, y)
        call Hero2Escaper(.maker).destroyCancelledActions()
	endmethod
	
	method unsaveLoc takes nothing returns boolean
		if (.locPointeur < 0) then
			return false
		endif
        call .monster.destroyLastLoc()
		set .locPointeur = .locPointeur - 1
		if (.locPointeur >= 0) then
			call SetUnitX(.unitLastClic, .lastX[.locPointeur])
			call SetUnitY(.unitLastClic, .lastY[.locPointeur])
		else
			call RemoveUnit(.unitLastClic)
			set .unitLastClic = null
            call .monster.removeUnit()
		endif
		return true
	endmethod
	
	method setMonster takes MonsterMultiplePatrols monster returns nothing //intègre le monstre créé au Make
		set .monster = monster
	endmethod
	
	method cancelLastAction takes nothing returns boolean
        return .unsaveLoc()
	endmethod
	
	method redoLastAction takes nothing returns boolean 
        if (.locPointeur < .lastLocId) then
            set .locPointeur = .locPointeur + 1
            call .monster.addNewLoc(.lastX[.locPointeur], .lastY[.locPointeur])
            call .setUnitLastClicPosition(.lastX[.locPointeur], .lastY[.locPointeur])
            return true
        endif
		return false
	endmethod	
endstruct
	
	
	
endlibrary
	


//===========================================================================
function InitTrig_MakeMonsterMultiplePatrols takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: Monster spawn making Actions
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library MonsterSpawnMakingActions needs Escaper



function MonsterSpawnMaking_Actions takes nothing returns nothing
    local Escaper escaper = Hero2Escaper(GetTriggerUnit())
    local Make mkGeneral = escaper.getMake()
	local MakeMonsterSpawn mk = MakeMonsterSpawn(integer(mkGeneral))
    local real x = GetOrderPointX()
    local real y = GetOrderPointY()
    local Level level
    
    if (not IsIssuedOrder("smart")) then   
        return
    endif
    call StopUnit(mk.maker)
    
	
    if (mk.isLastLocSavedUsed()) then
        set level = escaper.getMakingLevel()
        if(level.monsterSpawns.new(mk.label, mk.mt, mk.sens, mk.frequence, mk.lastX, mk.lastY, x, y, true) != 0)then
            call Text_mkP(mk.makerOwner, "monster spawn \"" + mk.label + "\" created")
            call escaper.destroyMake()
        else
            call Text_erP(mk.makerOwner, "impossible to create monster spawn \"" + mk.label + "\", label propably already in use")
        endif
    else
        call mk.saveLoc(x, y)
    endif
endfunction



endlibrary




//===========================================================================
function InitTrig_Monster_spawn_making_Actions takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: MakeMonsterSpawn
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library MakeMonsterSpawn needs Make



struct MakeMonsterSpawn extends Make
    real lastX
    real lastY
    private unit unitLastClic
    private boolean lastLocIsSaved
	private boolean lastLocSavedIsUsed
    string label
    MonsterType mt
    string sens
    real frequence
    
    
	static method create takes unit maker, string label, MonsterType mt, string sens, real frequence returns MakeMonsterSpawn
        local MakeMonsterSpawn m
		if (maker == null) then
			return 0
		endif
        set m = MakeMonsterSpawn.allocate()
        set m.maker = maker
		set m.makerOwner = GetOwningPlayer(maker)
        set m.kind = "monsterSpawnCreate"
        set m.label = label
        set m.mt = mt
        set m.sens = sens
        set m.frequence = frequence
        set m.t = CreateTrigger()
        call TriggerAddAction(m.t, Make_GetActions(m.kind))
        call TriggerRegisterUnitEvent(m.t, maker, EVENT_UNIT_ISSUED_POINT_ORDER)
        set m.lastLocIsSaved = false
        set m.lastLocSavedIsUsed = false
        return m
    endmethod
    
    method onDestroy takes nothing returns nothing
		call DestroyTrigger(.t)
		set .t = null
		call RemoveUnit(.unitLastClic)
		set .unitLastClic = null
		set .maker = null
	endmethod	
	
	method saveLoc takes real x, real y returns nothing
		set .lastX = x
		set .lastY = y
        set .lastLocIsSaved = true
		set .lastLocSavedIsUsed = true
		if (.unitLastClic == null) then
			set .unitLastClic = CreateUnit(.makerOwner, MAKE_LAST_CLIC_UNIT_ID, x, y, GetRandomDirectionDeg())
		else
			call SetUnitX(.unitLastClic, x)
			call SetUnitY(.unitLastClic, y)
		endif
        call Hero2Escaper(.maker).destroyCancelledActions()
	endmethod
	
	method unsaveLoc takes nothing returns boolean
		if (not .lastLocSavedIsUsed) then
			return false
		endif
		call RemoveUnit(.unitLastClic)
		set .unitLastClic = null
		set .lastLocSavedIsUsed = false
		return true
	endmethod
	
	method isLastLocSavedUsed takes nothing returns boolean
		return .lastLocSavedIsUsed
	endmethod
	
	method cancelLastAction takes nothing returns boolean
		return .unsaveLoc()
	endmethod
	
	method redoLastAction takes nothing returns boolean
        if (not .lastLocSavedIsUsed and .lastLocIsSaved) then
            call .saveLoc(.lastX, .lastY)
            return true
        endif
        return false
	endmethod
endstruct
	
	
	
endlibrary
	




//===========================================================================
function InitTrig_MakeMonsterSpawn takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: Monster delete Actions
//===========================================================================
//TESH.scrollpos=20
//TESH.alwaysfold=0
library MonsterDeleteActions needs BasicFunctions, Escaper


function MonsterDelete_Actions takes nothing returns nothing

//modes : oneByOne, all, noMove, move, simplePatrol, multiplePatrols

    local Escaper escaper = Hero2Escaper(GetTriggerUnit())
    local Make mkGeneral = escaper.getMake()
	local MakeDeleteMonsters mk = MakeDeleteMonsters(integer(mkGeneral))
    local MonsterNoMove Mnm
    local MonsterSimplePatrol Msp
	local MonsterMultiplePatrols Mmp
    local hashtable suppressionHashTable = InitHashtable()
    local integer nbMonstersRemoved = 0
    local real x = GetOrderPointX()
    local real y = GetOrderPointY()
	local integer i

    if (not IsIssuedOrder("smart")) then
        call FlushParentHashtable(suppressionHashTable)
        set suppressionHashTable = null
        return
    endif
    call StopUnit(mk.maker)
    
    
    if (mk.getMode() == "oneByOne") then
        set Mnm = escaper.getMakingLevel().monstersNoMove.getMonsterNear(x, y)
        if (Mnm != 0 and Mnm.u != null) then
            call Mnm.removeUnit()
            call SaveInteger(suppressionHashTable, 0, nbMonstersRemoved, integer(Mnm))
            set nbMonstersRemoved = 1
        else        
            set Msp = escaper.getMakingLevel().monstersSimplePatrol.getMonsterNear(x, y)
            if (Msp != 0 and Msp.u != null) then
                call Msp.removeUnit()
                call SaveInteger(suppressionHashTable, 0, nbMonstersRemoved, integer(Msp))
                set nbMonstersRemoved = 1
            else        
                set Mmp = escaper.getMakingLevel().monstersMultiplePatrols.getMonsterNear(x, y)
                if (Mmp != 0 and Mmp.u != null) then
                    call Mmp.removeUnit()
                    call SaveInteger(suppressionHashTable, 0, nbMonstersRemoved, integer(Mmp))
                    set nbMonstersRemoved = 1
                endif      
            endif
        endif
        
    else
    
        if (not mk.isLastLocSavedUsed()) then
            call mk.saveLoc(x, y)
            call FlushParentHashtable(suppressionHashTable)
            set suppressionHashTable = null
            return
        endif
        
        if (mk.getMode() == "all") then
            set i = 0
            loop
                exitwhen (i >= MAX_NB_MONSTERS_BY_LEVEL)
                    set Mnm = escaper.getMakingLevel().monstersNoMove.get(i)
                    if (Mnm != 0 and Mnm.u != null and IsUnitBetweenLocs(Mnm.u, mk.lastX, mk.lastY, x, y)) then
                        call Mnm.removeUnit()
                        call SaveInteger(suppressionHashTable, 0, nbMonstersRemoved, integer(Mnm))
                        set nbMonstersRemoved = nbMonstersRemoved + 1
                    endif
                    
                    set Msp = escaper.getMakingLevel().monstersSimplePatrol.get(i)
                    if (Msp != 0 and Msp.u != null and IsUnitBetweenLocs(Msp.u, mk.lastX, mk.lastY, x, y)) then
                        call Msp.removeUnit()
                        call SaveInteger(suppressionHashTable, 0, nbMonstersRemoved, integer(Msp))
                        set nbMonstersRemoved = nbMonstersRemoved + 1
                    endif
                    
                    set Mmp = escaper.getMakingLevel().monstersMultiplePatrols.get(i)
                    if (Mmp != 0 and Mmp.u != null and IsUnitBetweenLocs(Mmp.u, mk.lastX, mk.lastY ,x, y)) then
                        call Mmp.removeUnit()
                        call SaveInteger(suppressionHashTable, 0, nbMonstersRemoved, integer(Mmp))
                        set nbMonstersRemoved = nbMonstersRemoved + 1
                    endif
                set i = i + 1
            endloop
            
        endif
        
        if (mk.getMode() == "noMove") then
            set i = 0
            loop
                exitwhen (i >= MAX_NB_MONSTERS_BY_LEVEL)
                    set Mnm = escaper.getMakingLevel().monstersNoMove.get(i)
                    if (Mnm != 0 and Mnm.u != null and IsUnitBetweenLocs(Mnm.u, mk.lastX, mk.lastY, x, y)) then
                        call Mnm.removeUnit()
                        call SaveInteger(suppressionHashTable, 0, nbMonstersRemoved, integer(Mnm))
                        set nbMonstersRemoved = nbMonstersRemoved + 1
                    endif
                set i = i + 1
            endloop
        endif
        
        if (mk.getMode() == "move") then
            set i = 0
            loop
                exitwhen (i >= MAX_NB_MONSTERS_BY_LEVEL)
                    set Msp = escaper.getMakingLevel().monstersSimplePatrol.get(i)
                    if (Msp != 0 and Msp.u != null and IsUnitBetweenLocs(Msp.u, mk.lastX, mk.lastY, x, y)) then
                        call Msp.removeUnit()
                        call SaveInteger(suppressionHashTable, 0, nbMonstersRemoved, integer(Msp))
                        set nbMonstersRemoved = nbMonstersRemoved + 1
                    endif
                    
                    set Mmp = escaper.getMakingLevel().monstersMultiplePatrols.get(i)
                    if (Mmp != 0 and Mmp.u != null and IsUnitBetweenLocs(Mmp.u, mk.lastX, mk.lastY, x, y)) then
                        call Mmp.removeUnit()
                        call SaveInteger(suppressionHashTable, 0, nbMonstersRemoved, integer(Mmp))
                        set nbMonstersRemoved = nbMonstersRemoved + 1
                    endif
                set i = i + 1
            endloop
        endif
                        
        if (mk.getMode() == "simplePatrol") then
            set i = 0
            loop
                exitwhen (i >= MAX_NB_MONSTERS_BY_LEVEL)
                    set Msp = escaper.getMakingLevel().monstersSimplePatrol.get(i)
                    if (Msp != 0 and Msp.u != null and IsUnitBetweenLocs(Msp.u, mk.lastX, mk.lastY, x, y)) then
                        call Msp.removeUnit()
                        call SaveInteger(suppressionHashTable, 0, nbMonstersRemoved, integer(Msp))
                        set nbMonstersRemoved = nbMonstersRemoved + 1
                    endif
                set i = i + 1
            endloop
        endif
        
        if (mk.getMode() == "multiplePatrols") then
            set i = 0
            loop
                exitwhen i >= MAX_NB_MONSTERS_BY_LEVEL
                    set Mmp = escaper.getMakingLevel().monstersMultiplePatrols.get(i)
                    if (Mmp != 0 and Mmp.u != null and IsUnitBetweenLocs(Mmp.u, mk.lastX, mk.lastY, x, y)) then
                        call Mmp.removeUnit()
                        call SaveInteger(suppressionHashTable, 0, nbMonstersRemoved, integer(Mmp))
                        set nbMonstersRemoved = nbMonstersRemoved + 1
                    endif
                set i = i + 1
            endloop
        endif
    endif
    
    if (nbMonstersRemoved <= 1) then
        call Text_mkP(mk.makerOwner, I2S(nbMonstersRemoved) + " monster removed.")
    else
        call Text_mkP(mk.makerOwner, I2S(nbMonstersRemoved) + " monsters removed.")
    endif
    
	if (nbMonstersRemoved > 0) then
		call escaper.newAction(MakeDeleteMonstersAction.create(escaper.getMakingLevel(), suppressionHashTable))
    endif
    
    call mk.unsaveLocDefinitely()
    
    call FlushParentHashtable(suppressionHashTable)
    set suppressionHashTable = null
endfunction





//===========================================================================
function InitTrig_Monster_delete_Actions takes nothing returns nothing
endfunction


endlibrary

//===========================================================================
// Trigger: MakeDeleteMonsters
//
//                 if Monster( monsters[ i ] ).getType() == MonsterNoMove.typeid then
//                     call MonsterNoMove( monsters[ i ] ).createUnit()
//                 endif
//                 if Monster( monsters[ i ] ).getType() == MonsterSimplePatrol.typeid then
//                     call MonsterSimplePatrol( monsters[ i ] ).createUnit()
//                 endif
//                 if Monster( monsters[ i ] ).getType() == MonsterMultiplePatrols.typeid then
//                     call Text.A("Mmp")
//                     call MonsterMultiplePatrols( monsters[ i ] ).createUnit()
//                 endif
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library MakeDeleteMonsters needs Make




struct MakeDeleteMonsters extends Make
    real lastX
    real lastY
    private boolean lastLocIsSaved
	private boolean lastLocSavedIsUsed
    private unit unitLastClic
    private string mode
	
	method isLastLocSavedUsed takes nothing returns boolean
		return .lastLocSavedIsUsed
	endmethod
    
    static method create takes unit maker, string mode returns MakeDeleteMonsters
	    local MakeDeleteMonsters m
		if (maker == null) then
			return 0
		endif
        set m = MakeDeleteMonsters.allocate()
        set m.maker = maker
		set m.makerOwner = GetOwningPlayer(maker)
        set m.kind = "deleteMonsters"
        set m.mode = mode
        set m.lastLocIsSaved = false
        set m.lastLocSavedIsUsed = false
        set m.t = CreateTrigger()
        call TriggerAddAction(m.t, Make_GetActions(m.kind))
        call TriggerRegisterUnitEvent(m.t, m.maker, EVENT_UNIT_ISSUED_POINT_ORDER)
        return m
	endmethod
    
    method onDestroy takes nothing returns nothing
		call DestroyTrigger(.t)
		set .t = null
		set .maker = null
        call RemoveUnit(.unitLastClic)
        set .unitLastClic = null
    endmethod
    
	method saveLoc takes real x, real y returns nothing
		set .lastX = x
		set .lastY = y
        set .lastLocIsSaved = true
		set .lastLocSavedIsUsed = true
		if (.unitLastClic == null) then
			set .unitLastClic = CreateUnit(.makerOwner, MAKE_LAST_CLIC_UNIT_ID, x, y, GetRandomDirectionDeg())
		else
			call SetUnitX(.unitLastClic, x)
			call SetUnitY(.unitLastClic, y)
		endif
        call Hero2Escaper(.maker).destroyCancelledActions()
	endmethod
	
	method unsaveLoc takes nothing returns boolean
		if (not .lastLocSavedIsUsed) then
			return false
		endif
		call RemoveUnit(.unitLastClic)
		set .unitLastClic = null
		set .lastLocSavedIsUsed = false
		return true
	endmethod
    
    method unsaveLocDefinitely takes nothing returns nothing
        call .unsaveLoc()
        set .lastLocIsSaved = false
    endmethod
    
    method cancelLastAction takes nothing returns boolean
        return .unsaveLoc()
    endmethod
	
	method redoLastAction takes nothing returns boolean
		if (.lastLocIsSaved and not .lastLocSavedIsUsed) then
            call .saveLoc(.lastX, .lastY)
            return true
        endif
        return false
	endmethod	
    
    method getMode takes nothing returns string
        return .mode
    endmethod
endstruct



endlibrary


//===========================================================================
function InitTrig_MakeDeleteMonsters takes nothing returns nothing
endfunction


//===========================================================================
// Trigger: Meteor making Actions
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library MeteorMakingActions needs BasicFunctions, Escaper

function MeteorMaking_Actions takes nothing returns nothing
    local Meteor meteor
    local Escaper escaper = Hero2Escaper(GetTriggerUnit())
    local Make mkGeneral = escaper.getMake()
	local MakeMeteor mk = MakeMeteor(integer(mkGeneral))
    local real x = GetOrderPointX()
    local real y = GetOrderPointY()

    if (not IsIssuedOrder("smart")) then
        return
    endif
    call StopUnit(mk.maker)
    
    set meteor = escaper.getMakingLevel().meteors.new(x, y, true)
    call escaper.newAction(MakeMeteorAction.create(escaper.getMakingLevel(), meteor))
endfunction




//===========================================================================
function InitTrig_Meteor_making_Actions takes nothing returns nothing
endfunction


endlibrary//===========================================================================
// Trigger: MakeMeteor
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library MakeMeteor needs Make



struct MakeMeteor extends Make    	
	static method create takes unit maker returns MakeMeteor
        local MakeMeteor m
		if (maker == null) then
			return 0
		endif
        set m = MakeMeteor.allocate()
        set m.maker = maker
        set m.kind = "meteorCreate"
        set m.t = CreateTrigger()
        call TriggerAddAction(m.t, Make_GetActions(m.kind))
        call TriggerRegisterUnitEvent(m.t, m.maker, EVENT_UNIT_ISSUED_POINT_ORDER)
        return m
    endmethod
    
    method onDestroy takes nothing returns nothing
		call DestroyTrigger(.t)
		set .t = null
		set .maker = null
	endmethod
	
	method cancelLastAction takes nothing returns boolean
        return false
	endmethod
	
	method redoLastAction takes nothing returns boolean
        return false
	endmethod	
endstruct
	
	
	
	
endlibrary
	


//===========================================================================
function InitTrig_MakeMeteor takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: Meteor delete Actions
//===========================================================================
//TESH.scrollpos=32
//TESH.alwaysfold=0
library MeteorDeleteActions needs BasicFunctions, Escaper


function MeteorDelete_Actions takes nothing returns nothing

//modes : oneByOne, twoClics

    local Escaper escaper = Hero2Escaper(GetTriggerUnit())
    local Make mkGeneral = escaper.getMake()
	local MakeDeleteMeteors mk = MakeDeleteMeteors(integer(mkGeneral))
    local Meteor meteor
    local hashtable suppressionHashTable = InitHashtable()
    local integer nbMeteorsRemoved = 0
    local real x = GetOrderPointX()
    local real y = GetOrderPointY()
	local integer i

    if (not IsIssuedOrder("smart")) then
        call FlushParentHashtable(suppressionHashTable)
        set suppressionHashTable = null
        return
    endif
    call StopUnit(mk.maker)
    
    
    if (mk.getMode() == "oneByOne") then
        if (GetItemTypeId(GetOrderTargetItem()) != METEOR_NORMAL) then
            call FlushParentHashtable(suppressionHashTable)
            set suppressionHashTable = null
            return
        endif        
        set meteor = Meteor(GetItemUserData(GetOrderTargetItem()))
        if (meteor != 0 and meteor.getItem() != null) then
            call meteor.removeMeteor()
            call SaveInteger(suppressionHashTable, 0, nbMeteorsRemoved, integer(meteor))
            set nbMeteorsRemoved = 1
        endif
    else
        //mode twoClics
        if (not mk.isLastLocSavedUsed()) then
            call mk.saveLoc(x, y)
            call FlushParentHashtable(suppressionHashTable)
            set suppressionHashTable = null
            return
        endif
        
        set i = 0
        loop
            exitwhen (i > escaper.getMakingLevel().meteors.getLastInstanceId())
                set meteor = escaper.getMakingLevel().meteors.get(i)
                if (meteor != 0 and meteor.getItem() != null and IsItemBetweenLocs(meteor.getItem(), mk.lastX, mk.lastY, x, y)) then
                    call meteor.removeMeteor()
                    call SaveInteger(suppressionHashTable, 0, nbMeteorsRemoved, integer(meteor))
                    set nbMeteorsRemoved = nbMeteorsRemoved + 1
                endif
            set i = i + 1
        endloop
    endif
    
    if (nbMeteorsRemoved <= 1) then
        call Text_mkP(mk.makerOwner, I2S(nbMeteorsRemoved) + " meteor removed.")
    else
        call Text_mkP(mk.makerOwner, I2S(nbMeteorsRemoved) + " meteors removed.")
    endif
    
	if (nbMeteorsRemoved > 0) then
		call escaper.newAction(MakeDeleteMeteorsAction.create(escaper.getMakingLevel(), suppressionHashTable))
	endif
    
    call mk.unsaveLocDefinitely()
    
    call FlushParentHashtable(suppressionHashTable)
    set suppressionHashTable = null
endfunction





//===========================================================================
function InitTrig_Meteor_delete_Actions takes nothing returns nothing
endfunction


endlibrary

//===========================================================================
// Trigger: MakeDeleteMeteors
//
//                 if Monster( monsters[ i ] ).getType() == MonsterNoMove.typeid then
//                     call MonsterNoMove( monsters[ i ] ).createUnit()
//                 endif
//                 if Monster( monsters[ i ] ).getType() == MonsterSimplePatrol.typeid then
//                     call MonsterSimplePatrol( monsters[ i ] ).createUnit()
//                 endif
//                 if Monster( monsters[ i ] ).getType() == MonsterMultiplePatrols.typeid then
//                     call Text.A("Mmp")
//                     call MonsterMultiplePatrols( monsters[ i ] ).createUnit()
//                 endif
//===========================================================================
//TESH.scrollpos=4
//TESH.alwaysfold=0
library MakeDeleteMeteors needs Make



struct MakeDeleteMeteors extends Make
    real lastX
    real lastY
    private boolean lastLocIsSaved
	private boolean lastLocSavedIsUsed
    private unit unitLastClic
    private string mode
	
	method isLastLocSavedUsed takes nothing returns boolean
		return .lastLocSavedIsUsed
	endmethod
    
    static method create takes unit maker, string mode returns MakeDeleteMeteors
        //modes : oneByOne, twoClics
	    local MakeDeleteMeteors m
		if (maker == null or (mode != "oneByOne" and mode != "twoClics")) then
			return 0
		endif
        set m = MakeDeleteMeteors.allocate()
        set m.maker = maker
		set m.makerOwner = GetOwningPlayer(maker)
        set m.kind = "deleteMeteors"
        set m.mode = mode
        set m.lastLocIsSaved = false
        set m.lastLocSavedIsUsed = false
        set m.t = CreateTrigger()
        call TriggerAddAction(m.t, Make_GetActions(m.kind))
        call TriggerRegisterUnitEvent(m.t, m.maker, EVENT_UNIT_ISSUED_POINT_ORDER)
        if (mode == "oneByOne") then
            call TriggerRegisterUnitEvent(m.t, m.maker, EVENT_UNIT_ISSUED_TARGET_ORDER)
        endif
        return m
	endmethod
    
    method onDestroy takes nothing returns nothing
		call DestroyTrigger(.t)
		set .t = null
		set .maker = null
        call RemoveUnit(.unitLastClic)
        set .unitLastClic = null
    endmethod
    
	method saveLoc takes real x, real y returns nothing
		set .lastX = x
		set .lastY = y
        set .lastLocIsSaved = true
		set .lastLocSavedIsUsed = true
		if (.unitLastClic == null) then
			set .unitLastClic = CreateUnit(.makerOwner, MAKE_LAST_CLIC_UNIT_ID, x, y, GetRandomDirectionDeg())
		else
			call SetUnitX(.unitLastClic, x)
			call SetUnitY(.unitLastClic, y)
		endif
        call Hero2Escaper(.maker).destroyCancelledActions()
	endmethod
	
	method unsaveLoc takes nothing returns boolean
		if (not .lastLocSavedIsUsed) then
			return false
		endif
		call RemoveUnit(.unitLastClic)
		set .unitLastClic = null
		set .lastLocSavedIsUsed = false
		return true
	endmethod
    
    method unsaveLocDefinitely takes nothing returns nothing
        call .unsaveLoc()
        set .lastLocIsSaved = false
    endmethod
    
    method cancelLastAction takes nothing returns boolean
        return .unsaveLoc()
    endmethod
	
	method redoLastAction takes nothing returns boolean
		if (.lastLocIsSaved and not .lastLocSavedIsUsed) then
            call .saveLoc(.lastX, .lastY)
            return true
        endif
        return false
	endmethod	
    
    method getMode takes nothing returns string
        return .mode
    endmethod
endstruct



endlibrary


//===========================================================================
function InitTrig_MakeDeleteMeteors takes nothing returns nothing
endfunction


//===========================================================================
// Trigger: Terrain making Actions
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library TerrainMakingActions needs Escaper


function TerrainMaking_Actions takes nothing returns nothing
    local MakeAction action
    local Escaper escaper = Hero2Escaper(GetTriggerUnit())
    local Make mkGeneral = escaper.getMake()
	local MakeTerrainCreate mk = MakeTerrainCreate(integer(mkGeneral))
    local real x = GetOrderPointX()
    local real y = GetOrderPointY() 
    
    if (not IsIssuedOrder("smart")) then
        return
    endif
    call StopUnit(mk.maker)	
    
    if (mk.isLastLocSavedUsed()) then
        set action = MakeTerrainCreateAction.create(mk.getTerrainType(), mk.lastX, mk.lastY, x, y)
        if (action == -1) then
            call Text_erP(escaper.getPlayer(), "this terrain type doesn't exist anymore")
        else
            if (action == 0) then
                call Text_erP(escaper.getPlayer(), "too big zone")
            else
                call escaper.newAction(action)
                call mk.unsaveLocDefinitely()
            endif
        endif
    else
        call mk.saveLoc(x, y)
    endif
endfunction


endlibrary


//===========================================================================
function InitTrig_Terrain_making_Actions takes nothing returns nothing
endfunction


//===========================================================================
// Trigger: MakeTerrainCreate
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library MakeTerrainCreate needs Make, BasicFunctions, ModifyTerrainFunctions



struct MakeTerrainCreate extends Make    
    real lastX
    real lastY
    private boolean lastLocIsSaved
	private boolean lastLocSavedIsUsed
    private unit unitLastClic
    private TerrainType terrainType
	
	method isLastLocSavedUsed takes nothing returns boolean
		return .lastLocSavedIsUsed
	endmethod
	
    method getTerrainType takes nothing returns TerrainType
        return .terrainType
    endmethod
	
	static method create takes unit maker, TerrainType terrainType returns MakeTerrainCreate
        local MakeTerrainCreate m
		if (maker == null or terrainType == 0) then
			return 0
		endif
        set m = MakeTerrainCreate.allocate()
        set m.maker = maker
		set m.makerOwner = GetOwningPlayer(maker)
        set m.terrainType = terrainType
        set m.kind = "terrainCreate"
        set m.t = CreateTrigger()
        call TriggerAddAction(m.t, Make_GetActions(m.kind))
        call TriggerRegisterUnitEvent(m.t, maker, EVENT_UNIT_ISSUED_POINT_ORDER)
        set m.lastLocIsSaved = false
        set m.lastLocSavedIsUsed = false
        return m
    endmethod
    
    method onDestroy takes nothing returns nothing
		call DestroyTrigger(.t)
		set .t = null
		call RemoveUnit(.unitLastClic)
		set .unitLastClic = null
		set .maker = null
	endmethod	
	
	method saveLoc takes real x, real y returns nothing
		set .lastX = x
		set .lastY = y
        set .lastLocIsSaved = true
		set .lastLocSavedIsUsed = true
		if (.unitLastClic == null) then
			set .unitLastClic = CreateUnit(.makerOwner, MAKE_LAST_CLIC_UNIT_ID, x, y, GetRandomDirectionDeg())
		else
			call SetUnitX(.unitLastClic, x)
			call SetUnitY(.unitLastClic, y)
		endif
        call Hero2Escaper(.maker).destroyCancelledActions()
	endmethod
	
	method unsaveLoc takes nothing returns boolean
		if (not .lastLocSavedIsUsed) then
			return false
		endif
		call RemoveUnit(.unitLastClic)
		set .unitLastClic = null
		set .lastLocSavedIsUsed = false
		return true
	endmethod
    
    method unsaveLocDefinitely takes nothing returns nothing
        call .unsaveLoc()
        set .lastLocIsSaved = false
    endmethod
    
    method cancelLastAction takes nothing returns boolean
        return .unsaveLoc()
    endmethod
    
    method redoLastAction takes nothing returns boolean
        if (.lastLocIsSaved and not .lastLocSavedIsUsed) then
            call .saveLoc(.lastX, .lastY)
            return true
        endif
        return false
    endmethod
endstruct



endlibrary

//===========================================================================
function InitTrig_MakeTerrainCreate takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: Terrain copy paste Actions
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library TerrainCopyPasteActions needs Escaper


function TerrainCopyPaste_Actions takes nothing returns nothing
    local Escaper escaper = Hero2Escaper(GetTriggerUnit())
    local Make mkGeneral = escaper.getMake()
	local MakeTerrainCopyPaste mk = MakeTerrainCopyPaste(integer(mkGeneral))
    local real x = GetOrderPointX()
    local real y = GetOrderPointY() 
    
    if (not IsIssuedOrder("smart")) then
        return
    endif
    call StopUnit(mk.maker)	
    
    call mk.saveLoc(x, y)
endfunction



endlibrary



//===========================================================================
function InitTrig_Terrain_copy_paste_Actions takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: MakeTerrainCopyPaste
//===========================================================================
//TESH.scrollpos=27
//TESH.alwaysfold=0
library MakeTerrainCopyPaste needs Make, BasicFunctions, ModifyTerrainFunctions, Escaper



struct MakeTerrainCopyPaste extends Make
    real x1
    real y1
    real x2
    real y2
    real x3
    real y3
    private unit unitLastClic1
    private unit unitLastClic2
    private unit unitLastClic3
    private boolean isPoint1Saved
    private boolean isPoint2Saved
    private boolean isPoint3Saved
    private boolean isPoint1Used
    private boolean isPoint2Used
    private boolean isPoint3Used
    
	
	static method create takes unit maker returns MakeTerrainCopyPaste
        local MakeTerrainCopyPaste m
		if (maker == null) then
			return 0
		endif
        set m = MakeTerrainCopyPaste.allocate()
        set m.maker = maker
		set m.makerOwner = GetOwningPlayer(maker)
        set m.kind = "terrainCopyPaste"
        set m.t = CreateTrigger()
        call TriggerAddAction(m.t, Make_GetActions(m.kind))
        call TriggerRegisterUnitEvent(m.t, maker, EVENT_UNIT_ISSUED_POINT_ORDER)
        set m.isPoint1Saved = false
        set m.isPoint2Saved = false
        set m.isPoint3Saved = false
        set m.isPoint1Used = false
        set m.isPoint2Used = false
        set m.isPoint3Used = false
        return m
    endmethod
    
    method onDestroy takes nothing returns nothing
		call DestroyTrigger(.t)
		set .t = null
		call RemoveUnit(.unitLastClic1)
		set .unitLastClic1 = null
		call RemoveUnit(.unitLastClic2)
		set .unitLastClic2 = null
		call RemoveUnit(.unitLastClic3)
		set .unitLastClic3 = null
		set .maker = null
	endmethod	
    
    private method createUnitClic takes unit u, real x, real y returns unit
		if (u == null) then
			set u = CreateUnit(.makerOwner, MAKE_LAST_CLIC_UNIT_ID, x, y, GetRandomDirectionDeg())
		else
			call SetUnitX(u, x)
			call SetUnitY(u, y)
		endif
        return u
    endmethod
    
    method unsaveLoc takes integer locId returns nothing
        if (locId == 1) then
            set .isPoint1Used = false
            call RemoveUnit(.unitLastClic1)
            set .unitLastClic1 = null
        else
            if (locId == 2) then
                set .isPoint2Used = false
                call RemoveUnit(.unitLastClic2)
                set .unitLastClic2 = null
            else
                if (locId == 3) then
                    set .isPoint3Used = false
                    call RemoveUnit(.unitLastClic3)
                    set .unitLastClic3 = null
                endif
            endif
        endif
    endmethod
    
    method unsaveLocDefinitely takes integer locId returns nothing
        call .unsaveLoc(locId)
        if (locId == 1) then
            set .isPoint1Saved = false
        else
            if (locId == 2) then
                set .isPoint2Saved = false
            else
                if (locId == 3) then
                    set .isPoint3Saved = false
                endif
            endif
        endif
    endmethod
    
    method unsaveLocsDefinitely takes nothing returns nothing
        call .unsaveLocDefinitely(1)
        call .unsaveLocDefinitely(2)
        call .unsaveLocDefinitely(3)
    endmethod
     
	method saveLoc takes real x, real y returns nothing
        local MakeAction action
        if (not .isPoint1Used) then
            set .unitLastClic1 = .createUnitClic(.unitLastClic1, x, y)
            set .x1 = x
            set .y1 = y
            set .isPoint1Saved = true
            set .isPoint1Used = true
            call .unsaveLocDefinitely(2)
            call .unsaveLocDefinitely(3)
        else
            if (not .isPoint2Used) then
                if (GetNbCaseBetween(.x1, .y1, x, y) > NB_MAX_TILES_MODIFIED) then
                    call Text_erP(.makerOwner, "Too big zone !")
                    return
                endif
                set .unitLastClic2 = .createUnitClic(.unitLastClic2, x, y)
                set .x2 = x
                set .y2 = y
                set .isPoint2Saved = true
                set .isPoint2Used = true
                call .unsaveLocDefinitely(3)
            else
                if (not .isPoint3Used) then
                    set .unitLastClic3 = .createUnitClic(.unitLastClic3, x, y)
                    set .x3 = x
                    set .y3 = y
                    set .isPoint3Saved = true
                    set .isPoint3Used = true
                else
                    set action = MakeTerrainCopyPasteAction.create(.x1, .y1, .x2, .y2, .x3, .y3, x, y)
                    if (action != 0) then
                        call .unsaveLocsDefinitely()
                        call Hero2Escaper(.maker).newAction(action)
                    else
                        call Text_erP(.makerOwner, "paste zone out of bounds")
                    endif
                endif
            endif
        endif
        call Hero2Escaper(.maker).destroyCancelledActions()
	endmethod
    
    method cancelLastAction takes nothing returns boolean
        if (.isPoint3Used) then
            call .unsaveLoc(3)
            return true
        else
            if (.isPoint2Used) then
                call .unsaveLoc(2)
                return true
            else
                if (.isPoint1Used) then
                    call .unsaveLoc(1)
                    return true
                endif
            endif
        endif
        return false
    endmethod
    
    method redoLastAction takes nothing returns boolean
        if (.isPoint1Saved and not .isPoint1Used) then
            call .saveLoc(.x1, .y1)
            return true
        else
            if (.isPoint2Saved and not .isPoint2Used) then
                call .saveLoc(.x2, .y2)
                return true
            else
                if (.isPoint3Saved and not .isPoint3Used) then
                    call .saveLoc(.x3, .y3)
                    return true
                endif
            endif
        endif
        return false
    endmethod
endstruct



endlibrary



//===========================================================================
function InitTrig_MakeTerrainCopyPaste takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: Terrain vertical symmetry Actions
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library TerrainVerticalSymmetryActions needs Escaper


function TerrainVerticalSymmetry_Actions takes nothing returns nothing
    local MakeAction action
    local Escaper escaper = Hero2Escaper(GetTriggerUnit())
    local Make mkGeneral = escaper.getMake()
	local MakeTerrainVerticalSymmetry mk = MakeTerrainVerticalSymmetry(integer(mkGeneral))
    local real x = GetOrderPointX()
    local real y = GetOrderPointY() 
    
    if (not IsIssuedOrder("smart")) then
        return
    endif
    call StopUnit(mk.maker)	
    
    if (mk.isLastLocSavedUsed()) then
        set action = MakeTerrainVerticalSymmetryAction.create(mk.lastX, mk.lastY, x, y)
        if (action == 0) then
            call Text_erP(escaper.getPlayer(), "too big zone")
        else
            call escaper.newAction(action)
            call mk.unsaveLocDefinitely()
        endif
    else
        call mk.saveLoc(x, y)
    endif
endfunction


endlibrary



//===========================================================================
function InitTrig_Terrain_vertical_symmetry_Actions takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: MakeTerrainVerticalSymmetry
//===========================================================================
//TESH.scrollpos=18
//TESH.alwaysfold=0
library MakeTerrainVerticalSymmetry needs Make, BasicFunctions, ModifyTerrainFunctions



struct MakeTerrainVerticalSymmetry extends Make    
    real lastX
    real lastY
    private boolean lastLocIsSaved
	private boolean lastLocSavedIsUsed
    private unit unitLastClic
	
	method isLastLocSavedUsed takes nothing returns boolean
		return .lastLocSavedIsUsed
	endmethod
	
	static method create takes unit maker returns MakeTerrainVerticalSymmetry
        local MakeTerrainVerticalSymmetry m
		if (maker == null) then
			return 0
		endif
        set m = MakeTerrainVerticalSymmetry.allocate()
        set m.maker = maker
		set m.makerOwner = GetOwningPlayer(maker)
        set m.kind = "terrainVerticalSymmetry"
        set m.t = CreateTrigger()
        call TriggerAddAction(m.t, Make_GetActions(m.kind))
        call TriggerRegisterUnitEvent(m.t, maker, EVENT_UNIT_ISSUED_POINT_ORDER)
        set m.lastLocIsSaved = false
        set m.lastLocSavedIsUsed = false
        return m
    endmethod
    
    method onDestroy takes nothing returns nothing
		call DestroyTrigger(.t)
		set .t = null
		call RemoveUnit(.unitLastClic)
		set .unitLastClic = null
		set .maker = null
	endmethod	
	
	method saveLoc takes real x, real y returns nothing
		set .lastX = x
		set .lastY = y
        set .lastLocIsSaved = true
		set .lastLocSavedIsUsed = true
		if (.unitLastClic == null) then
			set .unitLastClic = CreateUnit(.makerOwner, MAKE_LAST_CLIC_UNIT_ID, x, y, GetRandomDirectionDeg())
		else
			call SetUnitX(.unitLastClic, x)
			call SetUnitY(.unitLastClic, y)
		endif
        call Hero2Escaper(.maker).destroyCancelledActions()
	endmethod
	
	method unsaveLoc takes nothing returns boolean
		if (not .lastLocSavedIsUsed) then
			return false
		endif
		call RemoveUnit(.unitLastClic)
		set .unitLastClic = null
		set .lastLocSavedIsUsed = false
		return true
	endmethod
    
    method unsaveLocDefinitely takes nothing returns nothing
        call .unsaveLoc()
        set .lastLocIsSaved = false
    endmethod
    
    method cancelLastAction takes nothing returns boolean
        return .unsaveLoc()
    endmethod
    
    method redoLastAction takes nothing returns boolean
        if (.lastLocIsSaved and not .lastLocSavedIsUsed) then
            call .saveLoc(.lastX, .lastY)
            return true
        endif
        return false
    endmethod
endstruct



endlibrary





//===========================================================================
function InitTrig_MakeTerrainVerticalSymmetry takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: Terrain horizontal symmetry Actions
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library TerrainHorizontalSymmetryActions needs Escaper


function TerrainHorizontalSymmetry_Actions takes nothing returns nothing
    local MakeAction action
    local Escaper escaper = Hero2Escaper(GetTriggerUnit())
    local Make mkGeneral = escaper.getMake()
	local MakeTerrainHorizontalSymmetry mk = MakeTerrainHorizontalSymmetry(integer(mkGeneral))
    local real x = GetOrderPointX()
    local real y = GetOrderPointY() 
    
    if (not IsIssuedOrder("smart")) then
        return
    endif
    call StopUnit(mk.maker)	
    
    if (mk.isLastLocSavedUsed()) then
        set action = MakeTerrainHorizontalSymmetryAction.create(mk.lastX, mk.lastY, x, y)
        if (action == 0) then
            call Text_erP(escaper.getPlayer(), "too big zone")
        else
            call escaper.newAction(action)
            call mk.unsaveLocDefinitely()
        endif
    else
        call mk.saveLoc(x, y)
    endif
endfunction


endlibrary



//===========================================================================
function InitTrig_Terrain_horizontal_symmetry_Actions takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: MakeTerrainHorizontalSymmetry
//===========================================================================
//TESH.scrollpos=18
//TESH.alwaysfold=0
library MakeTerrainHorizontalSymmetry needs Make, BasicFunctions, ModifyTerrainFunctions



struct MakeTerrainHorizontalSymmetry extends Make    
    real lastX
    real lastY
    private boolean lastLocIsSaved
	private boolean lastLocSavedIsUsed
    private unit unitLastClic
	
	method isLastLocSavedUsed takes nothing returns boolean
		return .lastLocSavedIsUsed
	endmethod
	
	static method create takes unit maker returns MakeTerrainHorizontalSymmetry
        local MakeTerrainHorizontalSymmetry m
		if (maker == null) then
			return 0
		endif
        set m = MakeTerrainHorizontalSymmetry.allocate()
        set m.maker = maker
		set m.makerOwner = GetOwningPlayer(maker)
        set m.kind = "terrainHorizontalSymmetry"
        set m.t = CreateTrigger()
        call TriggerAddAction(m.t, Make_GetActions(m.kind))
        call TriggerRegisterUnitEvent(m.t, maker, EVENT_UNIT_ISSUED_POINT_ORDER)
        set m.lastLocIsSaved = false
        set m.lastLocSavedIsUsed = false
        return m
    endmethod
    
    method onDestroy takes nothing returns nothing
		call DestroyTrigger(.t)
		set .t = null
		call RemoveUnit(.unitLastClic)
		set .unitLastClic = null
		set .maker = null
	endmethod	
	
	method saveLoc takes real x, real y returns nothing
		set .lastX = x
		set .lastY = y
        set .lastLocIsSaved = true
		set .lastLocSavedIsUsed = true
		if (.unitLastClic == null) then
			set .unitLastClic = CreateUnit(.makerOwner, MAKE_LAST_CLIC_UNIT_ID, x, y, GetRandomDirectionDeg())
		else
			call SetUnitX(.unitLastClic, x)
			call SetUnitY(.unitLastClic, y)
		endif
        call Hero2Escaper(.maker).destroyCancelledActions()
	endmethod
	
	method unsaveLoc takes nothing returns boolean
		if (not .lastLocSavedIsUsed) then
			return false
		endif
		call RemoveUnit(.unitLastClic)
		set .unitLastClic = null
		set .lastLocSavedIsUsed = false
		return true
	endmethod
    
    method unsaveLocDefinitely takes nothing returns nothing
        call .unsaveLoc()
        set .lastLocIsSaved = false
    endmethod
    
    method cancelLastAction takes nothing returns boolean
        return .unsaveLoc()
    endmethod
    
    method redoLastAction takes nothing returns boolean
        if (.lastLocIsSaved and not .lastLocSavedIsUsed) then
            call .saveLoc(.lastX, .lastY)
            return true
        endif
        return false
    endmethod
endstruct



endlibrary





//===========================================================================
function InitTrig_MakeTerrainHorizontalSymmetry takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: Make exchange terrains Actions
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library MakeExchangeTerrainsActions needs Escaper, ExchangeTerrains


function MakeExchangeTerrains_Actions takes nothing returns nothing
    local Escaper escaper = Hero2Escaper(GetTriggerUnit())
    local Make mkGeneral = escaper.getMake()
	local MakeExchangeTerrains mk = MakeExchangeTerrains(integer(mkGeneral))
    local real x = GetOrderPointX()
    local real y = GetOrderPointY() 
    local TerrainType terrainTypeA
    local TerrainType terrainTypeB
    
    if (not IsIssuedOrder("smart")) then
        return
    endif
    call StopUnit(mk.maker)	
    
    if (mk.isLastLocSavedUsed()) then
        set terrainTypeA = udg_terrainTypes.getTerrainType(mk.lastX, mk.lastY)
        set terrainTypeB = udg_terrainTypes.getTerrainType(x, y)
        call ExchangeTerrains(terrainTypeA.label, terrainTypeB.label)
        call mk.unsaveLocDefinitely()
    else
        call mk.saveLoc(x, y)
    endif
endfunction




//===========================================================================
function InitTrig_Make_exchange_terrains_Actions takes nothing returns nothing
endfunction


endlibrary
//===========================================================================
// Trigger: MakeExchangeTerrains
//===========================================================================
//TESH.scrollpos=11
//TESH.alwaysfold=0
library MakeExchangeTerrains needs Make, BasicFunctions, ModifyTerrainFunctions



struct MakeExchangeTerrains extends Make    
    real lastX
    real lastY
    private boolean lastLocIsSaved
	private boolean lastLocSavedIsUsed
    private unit unitLastClic
	
    	
	static method create takes unit maker returns MakeExchangeTerrains
        local MakeExchangeTerrains m
		if (maker == null) then
			return 0
		endif
        set m = MakeExchangeTerrains.allocate()
        set m.maker = maker
		set m.makerOwner = GetOwningPlayer(maker)
        set m.kind = "exchangeTerrains"
        set m.t = CreateTrigger()
        call TriggerAddAction(m.t, Make_GetActions(m.kind))
        call TriggerRegisterUnitEvent(m.t, maker, EVENT_UNIT_ISSUED_POINT_ORDER)
        set m.lastLocIsSaved = false
        set m.lastLocSavedIsUsed = false
        return m
    endmethod
    
    method onDestroy takes nothing returns nothing
		call DestroyTrigger(.t)
		set .t = null
		call RemoveUnit(.unitLastClic)
		set .unitLastClic = null
		set .maker = null
	endmethod	
	
	method saveLoc takes real x, real y returns nothing
		set .lastX = x
		set .lastY = y
        set .lastLocIsSaved = true
		set .lastLocSavedIsUsed = true
		if (.unitLastClic == null) then
			set .unitLastClic = CreateUnit(.makerOwner, MAKE_LAST_CLIC_UNIT_ID, x, y, GetRandomDirectionDeg())
		else
			call SetUnitX(.unitLastClic, x)
			call SetUnitY(.unitLastClic, y)
		endif
        call Hero2Escaper(.maker).destroyCancelledActions()
	endmethod
	
	method unsaveLoc takes nothing returns boolean
		if (not .lastLocSavedIsUsed) then
			return false
		endif
		call RemoveUnit(.unitLastClic)
		set .unitLastClic = null
		set .lastLocSavedIsUsed = false
		return true
	endmethod
    
    method unsaveLocDefinitely takes nothing returns nothing
        call .unsaveLoc()
        set .lastLocIsSaved = false
    endmethod
	
	method isLastLocSavedUsed takes nothing returns boolean
		return .lastLocSavedIsUsed
	endmethod
    
    method cancelLastAction takes nothing returns boolean
        return .unsaveLoc()
    endmethod
    
    method redoLastAction takes nothing returns boolean
        if (.lastLocIsSaved and not .lastLocSavedIsUsed) then
            call .saveLoc(.lastX, .lastY)
            return true
        endif
        return false
    endmethod
endstruct



endlibrary

//===========================================================================
function InitTrig_MakeExchangeTerrains takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: Start making Actions
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library StartMakingActions needs Escaper



function StartMaking_Actions takes nothing returns nothing
    local Escaper escaper = Hero2Escaper(GetTriggerUnit())
    local Make mkGeneral = escaper.getMake()
	local MakeStart mk = MakeStart(integer(mkGeneral))
    local real x = GetOrderPointX()
    local real y = GetOrderPointY()
    local Level level
    
    if (not IsIssuedOrder("smart")) then   
        return
    endif
    call StopUnit(mk.maker)
    
	
    if (mk.isLastLocSavedUsed()) then
        set level = escaper.getMakingLevel()
        if (mk.forNext()) then
            if (udg_levels.get(level.getId() + 1) == 0) then
                if (not udg_levels.new()) then
                    call Text_erP(escaper.getPlayer(), "nombre maximum de niveaux atteint")
                    call escaper.destroyMake()
                    return
                endif
            endif
            set level = udg_levels.get(level.getId() + 1)
            if (level == 0) then
                call Text_erP(escaper.getPlayer(), "erreur d'origine inconnue")
                call escaper.destroyMake()
                return
            endif
        endif
        call level.newStart(mk.lastX, mk.lastY, x, y)
        call Text_mkP(mk.makerOwner, "start made for level " + I2S(level.getId()))
        call escaper.destroyMake()
    else
        call mk.saveLoc(x, y)
    endif
endfunction



endlibrary




//===========================================================================
function InitTrig_Start_making_Actions takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: MakeStart
//===========================================================================
//TESH.scrollpos=51
//TESH.alwaysfold=0
library MakeStart needs Make



struct MakeStart extends Make
    real lastX
    real lastY
    private unit unitLastClic
    private boolean lastLocIsSaved
	private boolean lastLocSavedIsUsed
    private boolean forNextB //à true si on veut créer le start du niveau suivant
    
	static method create takes unit maker, boolean forNext returns MakeStart
        local MakeStart m
		if (maker == null) then
			return 0
		endif
        set m = MakeStart.allocate()
        set m.maker = maker
		set m.makerOwner = GetOwningPlayer(maker)
        set m.kind = "startCreate"
        set m.t = CreateTrigger()
        call TriggerAddAction(m.t, Make_GetActions(m.kind))
        call TriggerRegisterUnitEvent(m.t, maker, EVENT_UNIT_ISSUED_POINT_ORDER)
        set m.lastLocIsSaved = false
        set m.lastLocSavedIsUsed = false
        set m.forNextB = forNext
        return m
    endmethod
    
    method onDestroy takes nothing returns nothing
		call DestroyTrigger(.t)
		set .t = null
		call RemoveUnit(.unitLastClic)
		set .unitLastClic = null
		set .maker = null
	endmethod	
	
	method saveLoc takes real x, real y returns nothing
		set .lastX = x
		set .lastY = y
        set .lastLocIsSaved = true
		set .lastLocSavedIsUsed = true
		if (.unitLastClic == null) then
			set .unitLastClic = CreateUnit(.makerOwner, MAKE_LAST_CLIC_UNIT_ID, x, y, GetRandomDirectionDeg())
		else
			call SetUnitX(.unitLastClic, x)
			call SetUnitY(.unitLastClic, y)
		endif
        call Hero2Escaper(.maker).destroyCancelledActions()
	endmethod
	
	method unsaveLoc takes nothing returns boolean
		if (not .lastLocSavedIsUsed) then
			return false
		endif
		call RemoveUnit(.unitLastClic)
		set .unitLastClic = null
		set .lastLocSavedIsUsed = false
		return true
	endmethod
	
	method isLastLocSavedUsed takes nothing returns boolean
		return .lastLocSavedIsUsed
	endmethod
	
	method cancelLastAction takes nothing returns boolean
		return .unsaveLoc()
	endmethod
	
	method redoLastAction takes nothing returns boolean
        if (not .lastLocSavedIsUsed and .lastLocIsSaved) then
            call .saveLoc(.lastX, .lastY)
            return true
        endif
        return false
	endmethod
    
    method forNext takes nothing returns boolean
        return .forNextB
    endmethod
endstruct
	
	
	
endlibrary
	




//===========================================================================
function InitTrig_MakeStart takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: End making Actions
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library EndMakingActions needs Escaper



function EndMaking_Actions takes nothing returns nothing
    local Escaper escaper = Hero2Escaper(GetTriggerUnit())
    local Make mkGeneral = escaper.getMake()
	local MakeEnd mk = MakeEnd(integer(mkGeneral))
    local real x = GetOrderPointX()
    local real y = GetOrderPointY()
    
    if (not IsIssuedOrder("smart")) then   
        return
    endif
    call StopUnit(mk.maker)
    
	
    if (mk.isLastLocSavedUsed()) then
        call escaper.getMakingLevel().newEnd(mk.lastX, mk.lastY, x, y)
        call Text_mkP(mk.makerOwner, "end made for level " + I2S(escaper.getMakingLevel().getId()))
        call escaper.destroyMake()
    else
        call mk.saveLoc(x, y)
    endif
endfunction



endlibrary




//===========================================================================
function InitTrig_End_making_Actions takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: MakeEnd
//===========================================================================
//TESH.scrollpos=16
//TESH.alwaysfold=0
library MakeEnd needs Make



struct MakeEnd extends Make
    real lastX
    real lastY
    private unit unitLastClic
    private boolean lastLocIsSaved
	private boolean lastLocSavedIsUsed
    
	static method create takes unit maker returns MakeEnd
        local MakeEnd m
		if (maker == null) then
			return 0
		endif
        set m = MakeEnd.allocate()
        set m.maker = maker
		set m.makerOwner = GetOwningPlayer(maker)
        set m.kind = "endCreate"
        set m.t = CreateTrigger()
        call TriggerAddAction(m.t, Make_GetActions(m.kind))
        call TriggerRegisterUnitEvent(m.t, maker, EVENT_UNIT_ISSUED_POINT_ORDER)
        set m.lastLocIsSaved = false
        set m.lastLocSavedIsUsed = false
        return m
    endmethod
    
    method onDestroy takes nothing returns nothing
		call DestroyTrigger(.t)
		set .t = null
		call RemoveUnit(.unitLastClic)
		set .unitLastClic = null
		set .maker = null
	endmethod	
	
	method saveLoc takes real x, real y returns nothing
		set .lastX = x
		set .lastY = y
        set .lastLocIsSaved = true
		set .lastLocSavedIsUsed = true
		if (.unitLastClic == null) then
			set .unitLastClic = CreateUnit(.makerOwner, MAKE_LAST_CLIC_UNIT_ID, x, y, GetRandomDirectionDeg())
		else
			call SetUnitX(.unitLastClic, x)
			call SetUnitY(.unitLastClic, y)
		endif
        call Hero2Escaper(.maker).destroyCancelledActions()
	endmethod
	
	method unsaveLoc takes nothing returns boolean
		if (not .lastLocSavedIsUsed) then
			return false
		endif
		call RemoveUnit(.unitLastClic)
		set .unitLastClic = null
		set .lastLocSavedIsUsed = false
		return true
	endmethod
	
	method isLastLocSavedUsed takes nothing returns boolean
		return .lastLocSavedIsUsed
	endmethod
	
	method cancelLastAction takes nothing returns boolean
		return .unsaveLoc()
	endmethod
	
	method redoLastAction takes nothing returns boolean
        if (not .lastLocSavedIsUsed and .lastLocIsSaved) then
            call .saveLoc(.lastX, .lastY)
            return true
        endif
        return false
	endmethod
endstruct
	
	
	
endlibrary
	




//===========================================================================
function InitTrig_MakeEnd takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: VisibilityModifier making Actions
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library VisibilityModifierMakingActions needs Escaper



function VisibilityModifierMaking_Actions takes nothing returns nothing
    local VisibilityModifier newVisibilityModifier
    local Escaper escaper = Hero2Escaper(GetTriggerUnit())
    local Make mkGeneral = escaper.getMake()
	local MakeVisibilityModifier mk = MakeVisibilityModifier(integer(mkGeneral))
    local real x = GetOrderPointX()
    local real y = GetOrderPointY()
    
    if (not IsIssuedOrder("smart")) then   
        return
    endif
    call StopUnit(mk.maker)
    
	
    if (mk.isLastLocSavedUsed()) then
        set newVisibilityModifier = escaper.getMakingLevel().newVisibilityModifier(mk.lastX, mk.lastY, x, y)
        if (newVisibilityModifier == 0) then
            call Text_erP(mk.makerOwner, "can't create visibility, full for this level")
        else
            call newVisibilityModifier.activate(true)
            call escaper.newAction(MakeVisibilityModifierAction.create(escaper.getMakingLevel(), newVisibilityModifier))
            call Text_mkP(mk.makerOwner, "visibility rectangle made for level " + I2S(escaper.getMakingLevel().getId()))
         endif
        call mk.unsaveLocDefinitely()
    else
        call mk.saveLoc(x, y)
    endif
endfunction



endlibrary





//===========================================================================
function InitTrig_VisibilityModifier_making_Actions takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: MakeVisibilityModifier
//===========================================================================
//TESH.scrollpos=38
//TESH.alwaysfold=0
library MakeVisibilityModifier needs Make



struct MakeVisibilityModifier extends Make
    real lastX
    real lastY
    private unit unitLastClic
    private boolean lastLocIsSaved
	private boolean lastLocSavedIsUsed
    
	static method create takes unit maker returns MakeVisibilityModifier
        local MakeVisibilityModifier m
		if (maker == null) then
			return 0
		endif
        set m = MakeVisibilityModifier.allocate()
        set m.maker = maker
		set m.makerOwner = GetOwningPlayer(maker)
        set m.kind = "visibilityModifierCreate"
        set m.t = CreateTrigger()
        call TriggerAddAction(m.t, Make_GetActions(m.kind))
        call TriggerRegisterUnitEvent(m.t, maker, EVENT_UNIT_ISSUED_POINT_ORDER)
        set m.lastLocIsSaved = false
        set m.lastLocSavedIsUsed = false
        return m
    endmethod
    
    method onDestroy takes nothing returns nothing
		call DestroyTrigger(.t)
		set .t = null
		call RemoveUnit(.unitLastClic)
		set .unitLastClic = null
		set .maker = null
	endmethod	
	
	method saveLoc takes real x, real y returns nothing
		set .lastX = x
		set .lastY = y
        set .lastLocIsSaved = true
		set .lastLocSavedIsUsed = true
		if (.unitLastClic == null) then
			set .unitLastClic = CreateUnit(.makerOwner, MAKE_LAST_CLIC_UNIT_ID, x, y, GetRandomDirectionDeg())
		else
			call SetUnitX(.unitLastClic, x)
			call SetUnitY(.unitLastClic, y)
		endif
        call Hero2Escaper(.maker).destroyCancelledActions()
	endmethod
	
	method unsaveLoc takes nothing returns boolean
		if (not .lastLocSavedIsUsed) then
			return false
		endif
		call RemoveUnit(.unitLastClic)
		set .unitLastClic = null
		set .lastLocSavedIsUsed = false
		return true
	endmethod
    
    method unsaveLocDefinitely takes nothing returns nothing
        call .unsaveLoc()
        set .lastLocIsSaved = false
    endmethod
	
	method isLastLocSavedUsed takes nothing returns boolean
		return .lastLocSavedIsUsed
	endmethod
	
	method cancelLastAction takes nothing returns boolean
		return .unsaveLoc()
	endmethod
	
	method redoLastAction takes nothing returns boolean
        if (not .lastLocSavedIsUsed and .lastLocIsSaved) then
            call .saveLoc(.lastX, .lastY)
            return true
        endif
        return false
	endmethod
endstruct
	
	
	
endlibrary
	




//===========================================================================
function InitTrig_MakeVisibilityModifier takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: Getting terrain type info Actions
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library GettingTerrainTypeInfoActions needs Escaper



function GettingTerrainTypeInfo_Actions takes nothing returns nothing
    local Escaper escaper = Hero2Escaper(GetTriggerUnit())
    local Make mkGeneral = escaper.getMake()
	local MakeGetTerrainType mk = MakeGetTerrainType(integer(mkGeneral))
    local real x = GetOrderPointX()
    local real y = GetOrderPointY()

    if (not IsIssuedOrder("smart")) then
        return
    endif
    call StopUnit(mk.maker)
	
    call Text_P(mk.makerOwner, GetTerrainData(GetTerrainType(x, y)))
endfunction






//===========================================================================
function InitTrig_Getting_terrain_type_info_Actions takes nothing returns nothing
endfunction


endlibrary//===========================================================================
// Trigger: MakeGetTerrainType
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library MakeGetTerrainType needs Make



struct MakeGetTerrainType extends Make
	static method create takes unit maker returns MakeGetTerrainType
        local MakeGetTerrainType m
		if (maker == null) then
			return 0
		endif
        set m = MakeGetTerrainType.allocate()
        set m.maker = maker
        set m.makerOwner = GetOwningPlayer(maker)
        set m.kind = "getTerrainType"
        set m.t = CreateTrigger()
        call TriggerAddAction(m.t, Make_GetActions(m.kind))
        call TriggerRegisterUnitEvent(m.t, m.maker, EVENT_UNIT_ISSUED_POINT_ORDER)
        return m
    endmethod
    
    method onDestroy takes nothing returns nothing
		call DestroyTrigger(.t)
		set .t = null
		set .maker = null
	endmethod		
    
    method cancelLastAction takes nothing returns boolean
        return false
    endmethod
    
    method redoLastAction takes nothing returns boolean
        return false
    endmethod
endstruct



endlibrary



//===========================================================================
function InitTrig_MakeGetTerrainType takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: MakeAction
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library MakeAction


interface MakeAction
    boolean isActionMadeB
    Escaper owner
    method cancel takes nothing returns boolean
    method redo takes nothing returns boolean
endinterface


endlibrary





//===========================================================================
function InitTrig_MakeAction takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: MakeMonsterAction
//===========================================================================
//TESH.scrollpos=4
//TESH.alwaysfold=0
library MakeMonsterAction needs MakeAction



struct MakeMonsterAction extends MakeAction
    private Monster monster
    private Level level
    
    method getLevel takes nothing returns Level
        return .level
    endmethod

    static method create takes Level level, Monster monster returns MakeMonsterAction
        local MakeMonsterAction a 
        if (monster == 0 or monster.u == null) then
            return 0
        endif
        set a = MakeMonsterAction.allocate()
        set a.isActionMadeB = true
        set a.monster = monster
        set a.level = level
        return a
    endmethod
    
    method onDestroy takes nothing returns nothing
        if (not .isActionMadeB) then //si le monstre a été supprimé
            call .monster.destroy()
        endif
    endmethod
    
	method cancel takes nothing returns boolean
        if (not .isActionMadeB) then
            return false
        endif
		call .monster.removeUnit()
        set .isActionMadeB = false
        call Text_mkP(.owner.getPlayer(), "monster creation cancelled")
        return true
	endmethod
	
	method redo takes nothing returns boolean
        if (.isActionMadeB) then
            return false
        endif
		call .monster.createUnit()
        set .isActionMadeB = true
        call Text_mkP(.owner.getPlayer(), "monster creation redone")
        return true
	endmethod	
endstruct




endlibrary






//===========================================================================
function InitTrig_MakeMonsterAction takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: MakeDeleteMonstersAction
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library MakeDeleteMonstersAction needs MakeAction



struct MakeDeleteMonstersAction extends MakeAction
    static hashtable suppressions
    static integer suppressionLastId
    
    private static method onInit takes nothing returns nothing
        set MakeDeleteMonstersAction.suppressions = InitHashtable()
        set MakeDeleteMonstersAction.suppressionLastId = -1
    endmethod
    
    static method newSuppression takes hashtable suppression returns integer
        local integer i
        local integer suppressionId = MakeDeleteMonstersAction.suppressionLastId + 1
        set MakeDeleteMonstersAction.suppressionLastId = suppressionId
        set i = 0
        loop
            exitwhen (not HaveSavedInteger(suppression, 0, i))
                call SaveInteger(MakeDeleteMonstersAction.suppressions, suppressionId, i, LoadInteger(suppression, 0, i))
            set i = i + 1
        endloop
        return suppressionId
    endmethod
    
    static method removeSuppression takes integer suppressionId returns nothing
        call FlushChildHashtable(MakeDeleteMonstersAction.suppressions, suppressionId)
    endmethod    
    
    
    private integer suppressionId
    private Level level
    
    method getLevel takes nothing returns Level
        return .level
    endmethod

    static method create takes Level level, hashtable suppression returns MakeDeleteMonstersAction
        local MakeDeleteMonstersAction a 
        if (suppression == null) then
            return 0
        endif
        set a = MakeDeleteMonstersAction.allocate()
        set a.isActionMadeB = true
        set a.suppressionId = MakeDeleteMonstersAction.newSuppression(suppression)
        set a.level = level
        return a
    endmethod
    
    method onDestroy takes nothing returns nothing
        local integer i
        if (.isActionMadeB) then
            //suppression définitive des mobs
            set i = 0
            loop
                exitwhen (not HaveSavedInteger(MakeDeleteMonstersAction.suppressions, .suppressionId, i))
                    call Monster(LoadInteger(MakeDeleteMonstersAction.suppressions, .suppressionId, i)).destroy()
                set i = i + 1
            endloop
        endif
        call MakeDeleteMonstersAction.removeSuppression(.suppressionId)
    endmethod
    
	method cancel takes nothing returns boolean
        local integer i
        if (not .isActionMadeB) then
            return false
        endif
		//création des monstres supprimés
        set i = 0
        loop
            exitwhen (not HaveSavedInteger(MakeDeleteMonstersAction.suppressions, .suppressionId, i))
                call Monster(LoadInteger(MakeDeleteMonstersAction.suppressions, .suppressionId, i)).createUnit()
            set i = i + 1
        endloop
        set .isActionMadeB = false
        call Text_mkP(.owner.getPlayer(), "monster deleting cancelled")
        return true
	endmethod
	
	method redo takes nothing returns boolean
        local integer i
        if (.isActionMadeB) then
            return false
        endif
		//suppression des monstres recréés
        set i = 0
        loop
            exitwhen (not HaveSavedInteger(MakeDeleteMonstersAction.suppressions, .suppressionId, i))
                call Monster(LoadInteger(MakeDeleteMonstersAction.suppressions, .suppressionId, i)).removeUnit()
            set i = i + 1
        endloop
        set .isActionMadeB = true
        call Text_mkP(.owner.getPlayer(), "monster deleting redone")
        return true
	endmethod	
endstruct




endlibrary






//===========================================================================
function InitTrig_MakeDeleteMonstersAction takes nothing returns nothing
    
endfunction

//===========================================================================
// Trigger: MakeMeteorAction
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library MakeMeteorAction needs MakeAction



struct MakeMeteorAction extends MakeAction
    private Meteor meteor
    private Level level
    
    method getLevel takes nothing returns Level
        return .level
    endmethod

    static method create takes Level level, Meteor meteor returns MakeMeteorAction
        local MakeMeteorAction a 
        if (meteor == 0 or meteor.getItem() == null) then
            return 0
        endif
        set a = MakeMeteorAction.allocate()
        set a.isActionMadeB = true
        set a.meteor = meteor
        set a.level = level
        return a
    endmethod
    
    method onDestroy takes nothing returns nothing
        if (not .isActionMadeB) then //si le monstre a été supprimé
            call .meteor.destroy()
        endif
    endmethod
    
	method cancel takes nothing returns boolean
        if (not .isActionMadeB) then
            return false
        endif
		call .meteor.removeMeteor()
        set .isActionMadeB = false
        call Text_mkP(.owner.getPlayer(), "meteor creation cancelled")
        return true
	endmethod
	
	method redo takes nothing returns boolean
        if (.isActionMadeB) then
            return false
        endif
		call .meteor.createMeteor()
        set .isActionMadeB = true
        call Text_mkP(.owner.getPlayer(), "meteor creation redone")
        return true
	endmethod	
endstruct




endlibrary






//===========================================================================
function InitTrig_MakeMeteorAction takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: MakeDeleteMeteorsAction
//===========================================================================
//TESH.scrollpos=14
//TESH.alwaysfold=0
library MakeDeleteMeteorsAction needs MakeAction



struct MakeDeleteMeteorsAction extends MakeAction
    static hashtable suppressions
    static integer suppressionLastId
    
    private static method onInit takes nothing returns nothing
        set MakeDeleteMeteorsAction.suppressions = InitHashtable()
        set MakeDeleteMeteorsAction.suppressionLastId = -1
    endmethod
    
    static method newSuppression takes hashtable suppression returns integer
        local integer i
        local integer suppressionId = MakeDeleteMeteorsAction.suppressionLastId + 1
        set MakeDeleteMeteorsAction.suppressionLastId = suppressionId
        set i = 0
        loop
            exitwhen (not HaveSavedInteger(suppression, 0, i))
                call SaveInteger(MakeDeleteMeteorsAction.suppressions, suppressionId, i, LoadInteger(suppression, 0, i))
            set i = i + 1
        endloop
        return suppressionId
    endmethod
    
    static method removeSuppression takes integer suppressionId returns nothing
        call FlushChildHashtable(MakeDeleteMeteorsAction.suppressions, suppressionId)
    endmethod    
    
    
    private integer suppressionId
    private Level level
    
    method getLevel takes nothing returns Level
        return .level
    endmethod

    static method create takes Level level, hashtable suppression returns MakeDeleteMeteorsAction
        local MakeDeleteMeteorsAction a 
        if (suppression == null) then
            return 0
        endif
        set a = MakeDeleteMeteorsAction.allocate()
        set a.isActionMadeB = true
        set a.suppressionId = MakeDeleteMeteorsAction.newSuppression(suppression)
        set a.level = level
        return a
    endmethod
    
    method onDestroy takes nothing returns nothing
        local integer i
        if (.isActionMadeB) then
            //suppression définitive des météores
            set i = 0
            loop
                exitwhen (not HaveSavedInteger(MakeDeleteMeteorsAction.suppressions, .suppressionId, i))
                    call Meteor(LoadInteger(MakeDeleteMeteorsAction.suppressions, .suppressionId, i)).destroy()
                set i = i + 1
            endloop
        endif
        call MakeDeleteMeteorsAction.removeSuppression(.suppressionId)
    endmethod
    
	method cancel takes nothing returns boolean
        local integer i
        if (not .isActionMadeB) then
            return false
        endif
		//création des météores supprimées
        set i = 0
        loop
            exitwhen (not HaveSavedInteger(MakeDeleteMeteorsAction.suppressions, .suppressionId, i))
                call Meteor(LoadInteger(MakeDeleteMeteorsAction.suppressions, .suppressionId, i)).createMeteor()
            set i = i + 1
        endloop
        set .isActionMadeB = false
        call Text_mkP(.owner.getPlayer(), "meteor deleting cancelled")
        return true
	endmethod
	
	method redo takes nothing returns boolean
        local integer i
        if (.isActionMadeB) then
            return false
        endif
		//suppression des météores recréés
        set i = 0
        loop
            exitwhen (not HaveSavedInteger(MakeDeleteMeteorsAction.suppressions, .suppressionId, i))
                call Meteor(LoadInteger(MakeDeleteMeteorsAction.suppressions, .suppressionId, i)).removeMeteor()
            set i = i + 1
        endloop
        set .isActionMadeB = true
        call Text_mkP(.owner.getPlayer(), "meteor deleting redone")
        return true
	endmethod	
endstruct




endlibrary






//===========================================================================
function InitTrig_MakeDeleteMeteorsAction takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: MakeTerrainCreateAction
//===========================================================================
//TESH.scrollpos=14
//TESH.alwaysfold=0
library MakeTerrainCreateAction needs MakeAction, ModifyTerrainFunctions


struct MakeTerrainCreateAction extends MakeAction
    static hashtable terrainSaves
    static integer terrainSaveLastId
    
    private static method onInit takes nothing returns nothing
        set MakeTerrainCreateAction.terrainSaves = InitHashtable()
        set MakeTerrainCreateAction.terrainSaveLastId = -1
    endmethod
    
    static method newTerrainSaveId takes nothing returns integer
        set MakeTerrainCreateAction.terrainSaveLastId = MakeTerrainCreateAction.terrainSaveLastId + 1
        return MakeTerrainCreateAction.terrainSaveLastId
    endmethod
    
    static method removeTerrainSave takes integer terrainSaveId returns nothing
        call FlushChildHashtable(MakeTerrainCreateAction.terrainSaves, terrainSaveId)
    endmethod    
    
    
    
    private integer terrainSaveId
    private TerrainType terrainTypeNew
    private real minX
    private real minY
    private real maxX
    private real maxY

    static method create takes TerrainType terrainTypeNew, real x1, real y1, real x2, real y2 returns MakeTerrainCreateAction
        local hashtable terrainSave
        local integer terrainSaveId
        local MakeTerrainCreateAction a
        local real x
        local real y
        local integer i
       
        local real minX = RMinBJ(x1, x2)
        local real maxX = RMaxBJ(x1, x2)
        local real minY = RMinBJ(y1, y2)
        local real maxY = RMaxBJ(y1, y2)
        
        if (terrainTypeNew == 0 or terrainTypeNew.getTerrainTypeId() == 0) then
            return -1
        endif
        if (GetNbCaseBetween(minX, minY, maxX, maxY) > NB_MAX_TILES_MODIFIED) then
            return 0
        endif
        set a = MakeTerrainCreateAction.allocate()
        set terrainSave = MakeTerrainCreateAction.terrainSaves
        set a.terrainSaveId = MakeTerrainCreateAction.newTerrainSaveId()
        
        set i = 0
        set x = minX
        set y = minY
        loop
            exitwhen (y > maxY)
                loop
                    exitwhen (x > maxX)
                        call SaveInteger(terrainSave, a.terrainSaveId, i, integer(udg_terrainTypes.getTerrainType(x, y)))
                        set i = i + 1
                    set x = x + LARGEUR_CASE
                endloop
                set x = minX
            set y = y + LARGEUR_CASE
        endloop 
        set terrainSave = null
        
        call ChangeTerrainBetween(terrainTypeNew.getTerrainTypeId(), minX, minY, maxX, maxY)
        set a.terrainTypeNew = terrainTypeNew
        set a.minX = minX
        set a.maxX = maxX
        set a.minY = minY
        set a.maxY = maxY
        set a.isActionMadeB = true
        return a
    endmethod
    
    private method onDestroy takes nothing returns nothing
        call MakeTerrainCreateAction.removeTerrainSave(.terrainSaveId)
    endmethod
    
    method terrainModificationCancel takes nothing returns nothing 
        local TerrainType terrainType
        local real x
        local real y
        local integer i
       
        set i = 0
        set x = .minX
        set y = .minY
        loop
            exitwhen (y > .maxY)
                loop
                    exitwhen (x > .maxX)
                        set terrainType = TerrainType(LoadInteger(MakeTerrainCreateAction.terrainSaves, .terrainSaveId, i))
                        if (terrainType != 0 and terrainType.getTerrainTypeId() != 0) then
                            call ChangeTerrainType(x, y, terrainType.getTerrainTypeId())
                        endif
                        set i = i + 1
                    set x = x + LARGEUR_CASE
                endloop
                set x = .minX
            set y = y + LARGEUR_CASE
        endloop
    endmethod
    
    method terrainModificationRedo takes nothing returns nothing 
        local integer terrainTypeId = .terrainTypeNew.getTerrainTypeId()
        if (terrainTypeId == 0) then
            call Text_erP(.owner.getPlayer(), "the terrain type for this action doesn't exist anymore")
        else
            call ChangeTerrainBetween(terrainTypeId, .minX, .minY, .maxX, .maxY)
        endif
    endmethod
    
	method cancel takes nothing returns boolean
        if (not .isActionMadeB) then
            return false
        endif
        call .terrainModificationCancel()
        set .isActionMadeB = false
        call Text_mkP(.owner.getPlayer(), "terrain creation cancelled")
        return true
	endmethod
	
	method redo takes nothing returns boolean
        if (.isActionMadeB) then
            return false
        endif
        call .terrainModificationRedo()
        set .isActionMadeB = true
        call Text_mkP(.owner.getPlayer(), "terrain creation redone")
        return true
	endmethod		
endstruct




endlibrary







//===========================================================================
function InitTrig_MakeTerrainCreateAction takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: MakeTerrainCopyPasteAction
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library MakeTerrainCopyPasteAction needs MakeAction, ModifyTerrainFunctions


struct MakeTerrainCopyPasteAction extends MakeAction
    static hashtable terrainSavesBefore
    static hashtable terrainSavesAfter
    static integer terrainSaveLastId
    
    private static method onInit takes nothing returns nothing
        set MakeTerrainCopyPasteAction.terrainSavesBefore = InitHashtable()
        set MakeTerrainCopyPasteAction.terrainSavesAfter = InitHashtable()
        set MakeTerrainCopyPasteAction.terrainSaveLastId = -1
    endmethod
    
    static method newTerrainSaveId takes nothing returns integer
        set MakeTerrainCopyPasteAction.terrainSaveLastId = MakeTerrainCopyPasteAction.terrainSaveLastId + 1
        return MakeTerrainCopyPasteAction.terrainSaveLastId
    endmethod
    
    static method removeTerrainSave takes integer terrainSaveId returns nothing
        call FlushChildHashtable(MakeTerrainCopyPasteAction.terrainSavesBefore, terrainSaveId)
        call FlushChildHashtable(MakeTerrainCopyPasteAction.terrainSavesAfter, terrainSaveId)
    endmethod    
    
    
    private integer terrainSaveId
    private real minX
    private real minY
    private real maxX
    private real maxY

    static method create takes real x1, real y1, real x2, real y2, real x3, real y3, real x4, real y4 returns MakeTerrainCopyPasteAction
        local MakeTerrainCopyPasteAction a
        local real xCopy
        local real yCopy
        local real xPaste
        local real yPaste
        local integer i
        local TerrainType terrainType
        local integer terrainTypeId
       
        local real minXcopy = RMinBJ(x1, x2)
        local real maxXcopy = RMaxBJ(x1, x2)
        local real minYcopy = RMinBJ(y1, y2)
        local real maxYcopy = RMaxBJ(y1, y2)
        
        local real diffX = maxXcopy - minXcopy
        local real diffY = maxYcopy - minYcopy
        
        local real minXpaste
        local real minYpaste
        if (x4 > x3) then 
            //direction droite
            set minXpaste = x3
        else    
            //direction gauche
            set minXpaste = x3 - diffX
        endif
        if (y4 > y3) then 
            //direction haut
            set minYpaste = y3
        else    
            //direction bas
            set minYpaste = y3 - diffY
        endif
        
        if (minXpaste < MAP_MIN_X or minXpaste + diffX > MAP_MAX_X or minYpaste < MAP_MIN_Y or minYpaste + diffY > MAP_MAX_Y) then
            return 0
        endif
        
        set a = MakeTerrainCopyPasteAction.allocate()
        set a.terrainSaveId = MakeTerrainCopyPasteAction.newTerrainSaveId()
        set a.minX = minXpaste
        set a.minY = minYpaste
        set a.maxX = minXpaste + diffX
        set a.maxY = minYpaste + diffY
        
        set i = 0
        set xPaste = minXpaste
        set yPaste = minYpaste
        set xCopy = minXcopy
        set yCopy = minYcopy
        loop
            exitwhen (yCopy > maxYcopy)
                loop
                    exitwhen (xCopy > maxXcopy)
                        call SaveInteger(MakeTerrainCopyPasteAction.terrainSavesBefore, a.terrainSaveId, i, integer(udg_terrainTypes.getTerrainType(xPaste, yPaste)))
                        set terrainType = udg_terrainTypes.getTerrainType(xCopy, yCopy)
                        call SaveInteger(MakeTerrainCopyPasteAction.terrainSavesAfter, a.terrainSaveId, i, integer(udg_terrainTypes.getTerrainType(xCopy, yCopy)))
                        if (terrainType != 0) then
                            set terrainTypeId = terrainType.getTerrainTypeId()
                            if (terrainTypeId != 0) then
                                call ChangeTerrainType(xPaste, yPaste, terrainTypeId)
                            endif
                        endif                        
                        set i = i + 1
                        set xPaste = xPaste + LARGEUR_CASE
                    set xCopy = xCopy + LARGEUR_CASE
                endloop
                set xPaste = minXpaste
                set xCopy = minXcopy
                set yPaste = yPaste + LARGEUR_CASE
            set yCopy = yCopy + LARGEUR_CASE
        endloop
        
        set a.isActionMadeB = true
        return a
    endmethod
    
    private method onDestroy takes nothing returns nothing
        call MakeTerrainCopyPasteAction.removeTerrainSave(.terrainSaveId)
    endmethod
    
    method terrainModificationCancel takes nothing returns nothing 
        local TerrainType terrainType
        local real x
        local real y
        local integer i
       
        set i = 0
        set x = .minX
        set y = .minY
        loop
            exitwhen (y > .maxY)
                loop
                    exitwhen (x > .maxX)
                        set terrainType = TerrainType(LoadInteger(MakeTerrainCopyPasteAction.terrainSavesBefore, .terrainSaveId, i))
                        if (terrainType != 0 and terrainType.getTerrainTypeId() != 0) then
                            call ChangeTerrainType(x, y, terrainType.getTerrainTypeId())
                        endif
                        set i = i + 1
                    set x = x + LARGEUR_CASE
                endloop
                set x = .minX
            set y = y + LARGEUR_CASE
        endloop
    endmethod
    
    method terrainModificationRedo takes nothing returns nothing
        local TerrainType terrainType
        local real x
        local real y
        local integer i
       
        set i = 0
        set x = .minX
        set y = .minY
        loop
            exitwhen (y > .maxY)
                loop
                    exitwhen (x > .maxX)
                        set terrainType = TerrainType(LoadInteger(MakeTerrainCopyPasteAction.terrainSavesAfter, .terrainSaveId, i))
                        if (terrainType != 0 and terrainType.getTerrainTypeId() != 0) then
                            call ChangeTerrainType(x, y, terrainType.getTerrainTypeId())
                        endif
                        set i = i + 1
                    set x = x + LARGEUR_CASE
                endloop
                set x = .minX
            set y = y + LARGEUR_CASE
        endloop
    endmethod
    
	method cancel takes nothing returns boolean
        if (not .isActionMadeB) then
            return false
        endif
        call .terrainModificationCancel()
        set .isActionMadeB = false
        call Text_mkP(.owner.getPlayer(), "terrain copy/paste cancelled")
        return true
	endmethod
	
	method redo takes nothing returns boolean
        if (.isActionMadeB) then
            return false
        endif
        call .terrainModificationRedo()
        set .isActionMadeB = true
        call Text_mkP(.owner.getPlayer(), "terrain copy/paste redone")
        return true
	endmethod		
endstruct




endlibrary




//===========================================================================
function InitTrig_MakeTerrainCopyPasteAction takes nothing returns nothing
endfunction
   //===========================================================================
// Trigger: MakeTerrainVerticalSymmetryAction
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library MakeTerrainVerticalSymmetryAction needs MakeAction, ModifyTerrainFunctions


struct MakeTerrainVerticalSymmetryAction extends MakeAction   
    private real minX
    private real minY
    private real maxX
    private real maxY

    static method create takes real x1, real y1, real x2, real y2 returns MakeTerrainVerticalSymmetryAction
        local MakeTerrainVerticalSymmetryAction a
       
        local real minX = RMinBJ(x1, x2)
        local real maxX = RMaxBJ(x1, x2)
        local real minY = RMinBJ(y1, y2)
        local real maxY = RMaxBJ(y1, y2)
        
        //pour éviter les ptits décalages
        set minX = I2R(R2I(minX / LARGEUR_CASE)) * LARGEUR_CASE
        set minY = I2R(R2I(minY / LARGEUR_CASE)) * LARGEUR_CASE
        set maxX = I2R(R2I(maxX / LARGEUR_CASE)) * LARGEUR_CASE
        set maxY = I2R(R2I(maxY / LARGEUR_CASE)) * LARGEUR_CASE
        
        if (GetNbCaseBetween(minX, minY, maxX, maxY) > NB_MAX_TILES_MODIFIED) then
            return 0
        endif
        set a = MakeTerrainVerticalSymmetryAction.allocate()
        set a.minX = minX
        set a.minY = minY
        set a.maxX = maxX
        set a.maxY = maxY
        call a.applySymmetry()        
        set a.isActionMadeB = true
        return a
    endmethod
    
    method applySymmetry takes nothing returns nothing
        local integer i
        local real x
        local real y
        local integer array terrainTypeIds
        
        //sauvegarde du terrain
        set i = 0
        set x = .minX
        set y = .minY
        loop
            exitwhen (y > .maxY)
                loop
                    exitwhen (x > .maxX)
                        set terrainTypeIds[i] = GetTerrainType(x, y)
                        set i = i + 1
                    set x = x + LARGEUR_CASE
                endloop
                set x = .minX
            set y = y + LARGEUR_CASE
        endloop
        
        //application de la symétrie
        set i = 0
        set x = .minX
        set y = .maxY
        loop
            exitwhen (y < .minY)
                loop
                    exitwhen (x > .maxX)
                        call ChangeTerrainType(x, y, terrainTypeIds[i])
                        set i = i + 1
                    set x = x + LARGEUR_CASE
                endloop
                set x = .minX
            set y = y - LARGEUR_CASE
        endloop  
    endmethod
    
	method cancel takes nothing returns boolean
        if (not .isActionMadeB) then
            return false
        endif
        call .applySymmetry()
        set .isActionMadeB = false
        call Text_mkP(.owner.getPlayer(), "terrain vertical symmetry cancelled")
        return true
	endmethod
	
	method redo takes nothing returns boolean
        if (.isActionMadeB) then
            return false
        endif
        call .applySymmetry()
        set .isActionMadeB = true
        call Text_mkP(.owner.getPlayer(), "terrain vertical symmetry redone")
        return true
	endmethod		
endstruct




endlibrary






//===========================================================================
function InitTrig_MakeTerrainVerticalSymmetryAction takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: MakeTerrainHorizontalSymmetryAction
//===========================================================================
//TESH.scrollpos=4
//TESH.alwaysfold=0
library MakeTerrainHorizontalSymmetryAction needs MakeAction, ModifyTerrainFunctions


struct MakeTerrainHorizontalSymmetryAction extends MakeAction   
    private real minX
    private real minY
    private real maxX
    private real maxY

    static method create takes real x1, real y1, real x2, real y2 returns MakeTerrainHorizontalSymmetryAction
        local MakeTerrainHorizontalSymmetryAction a
       
        local real minX = RMinBJ(x1, x2)
        local real maxX = RMaxBJ(x1, x2)
        local real minY = RMinBJ(y1, y2)
        local real maxY = RMaxBJ(y1, y2)
        
        //pour éviter les ptits décalages
        set minX = I2R(R2I(minX / LARGEUR_CASE)) * LARGEUR_CASE
        set minY = I2R(R2I(minY / LARGEUR_CASE)) * LARGEUR_CASE
        set maxX = I2R(R2I(maxX / LARGEUR_CASE)) * LARGEUR_CASE
        set maxY = I2R(R2I(maxY / LARGEUR_CASE)) * LARGEUR_CASE
        
        if (GetNbCaseBetween(minX, minY, maxX, maxY) > NB_MAX_TILES_MODIFIED) then
            return 0
        endif
        set a = MakeTerrainHorizontalSymmetryAction.allocate()
        set a.minX = minX
        set a.minY = minY
        set a.maxX = maxX
        set a.maxY = maxY
        call a.applySymmetry()        
        set a.isActionMadeB = true
        return a
    endmethod
    
    method applySymmetry takes nothing returns nothing
        local integer i
        local real x
        local real y
        local integer array terrainTypeIds
        
        //sauvegarde du terrain
        set i = 0
        set x = .minX
        set y = .minY
        loop
            exitwhen (y > .maxY)
                loop
                    exitwhen (x > .maxX)
                        set terrainTypeIds[i] = GetTerrainType(x, y)
                        set i = i + 1
                    set x = x + LARGEUR_CASE
                endloop
                set x = .minX
            set y = y + LARGEUR_CASE
        endloop
        
        //application de la symétrie
        set i = 0
        set x = .maxX
        set y = .minY
        loop
            exitwhen (y > .maxY)
                loop
                    exitwhen (x < .minX)
                        call ChangeTerrainType(x, y, terrainTypeIds[i])
                        set i = i + 1
                    set x = x - LARGEUR_CASE
                endloop
                set x = .maxX
            set y = y + LARGEUR_CASE
        endloop  
    endmethod
    
	method cancel takes nothing returns boolean
        if (not .isActionMadeB) then
            return false
        endif
        call .applySymmetry()
        set .isActionMadeB = false
        call Text_mkP(.owner.getPlayer(), "terrain vertical symmetry cancelled")
        return true
	endmethod
	
	method redo takes nothing returns boolean
        if (.isActionMadeB) then
            return false
        endif
        call .applySymmetry()
        set .isActionMadeB = true
        call Text_mkP(.owner.getPlayer(), "terrain vertical symmetry redone")
        return true
	endmethod		
endstruct




endlibrary






//===========================================================================
function InitTrig_MakeTerrainHorizontalSymmetryAction takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: MakeVisibilityModifierAction
//===========================================================================
//TESH.scrollpos=22
//TESH.alwaysfold=0
library MakeVisibilityModifierAction needs MakeAction



struct MakeVisibilityModifierAction extends MakeAction
    private Level level
    private VisibilityModifier visibilityModifierSave
    private VisibilityModifier visibilityModifierPointeur //pointe vers le vm effectif
    
    method getLevel takes nothing returns Level
        return .level
    endmethod

    static method create takes Level level, VisibilityModifier visibilityModifier returns MakeVisibilityModifierAction
        local MakeVisibilityModifierAction a 
        if (visibilityModifier == 0) then
            return 0
        endif
        set a = MakeVisibilityModifierAction.allocate()
        set a.isActionMadeB = true
        set a.level = level
        set a.visibilityModifierSave = 0
        set a.visibilityModifierPointeur = visibilityModifier
        return a
    endmethod
    
    method onDestroy takes nothing returns nothing
        if (.visibilityModifierSave != 0) then
            call .visibilityModifierSave.destroy()
        endif
    endmethod
    
	method cancel takes nothing returns boolean
        if (not .isActionMadeB) then
            return false
        endif
		set .visibilityModifierSave = .visibilityModifierPointeur.copy()
        call .visibilityModifierPointeur.destroy()
        set .isActionMadeB = false
        call Text_mkP(.owner.getPlayer(), "visibility creation cancelled")
        return true
	endmethod
	
	method redo takes nothing returns boolean
        if (.isActionMadeB) then
            return false
        endif
        set .visibilityModifierPointeur = .level.newVisibilityModifierFromExisting(.visibilityModifierSave)
		if (.visibilityModifierPointeur == 0) then
            call Text_erP(.owner.getPlayer(), "can't recreate visibility, full for this level")
        else
            call .visibilityModifierPointeur.activate(true)
        endif
        set .visibilityModifierSave = 0
        set .isActionMadeB = true
        call Text_mkP(.owner.getPlayer(), "visibility creation redone")
        return true
	endmethod	
endstruct




endlibrary







//===========================================================================
function InitTrig_MakeVisibilityModifierAction takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: MakeLastActions
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library MakeLastActions needs Text


globals
    private constant integer NB_MAX_ACTIONS_SAVED = 30
endglobals



struct MakeLastActions
    private MakeAction array lastActions [NB_MAX_ACTIONS_SAVED]
    private integer lastActionId
    private integer lastActionEffective //anciennement appelé "pointeur"
    private Escaper owner
    
    static method create takes Escaper owner returns MakeLastActions
        local MakeLastActions la = MakeLastActions.allocate()
        set la.lastActionId = -1
        set la.lastActionEffective = -1
        set la.owner = owner
        return la
    endmethod   
    
    private method onDestroy takes nothing returns nothing
        local integer i = 0
        loop
            exitwhen (i > .lastActionId)
                call .lastActions[i].destroy()
            set i = i + 1
        endloop
    endmethod
    
    method newAction takes MakeAction action returns MakeAction
        local integer i
        if (.lastActionEffective < .lastActionId) then
            //suppression des actions annulées (à l'ajout d'une nouvelle action)
            set i = .lastActionEffective + 1
            loop
                exitwhen (i > .lastActionId)
                    call .lastActions[i].destroy()
                set i = i + 1
            endloop
        endif
        if (.lastActionEffective == NB_MAX_ACTIONS_SAVED - 1) then
            //suppression de la plus ancienne des actions et décalage de tout le tableau
            call .lastActions[0].destroy()
            set i = 0
            loop
                exitwhen (i == NB_MAX_ACTIONS_SAVED - 1)
                    set .lastActions[i] = .lastActions[i + 1]
                set i = i + 1
            endloop
        else
            set .lastActionEffective = .lastActionEffective + 1
        endif
        //sauvegarde de l'action
        set .lastActions[.lastActionEffective] = action
        set .lastActionId = .lastActionEffective
        //assignation du "owner" de l'action
        set action.owner = .owner
        return action
    endmethod
    
    method cancelLastAction takes nothing returns boolean
        if (.lastActionEffective < 0) then
            return false
        endif
        if (.lastActions[.lastActionEffective] == 0) then //action obsolète
            call Text_erP(.owner.getPlayer(), "action obsolète")
        else
            //annulation de l'action
            if (not .lastActions[.lastActionEffective].cancel()) then
                call Text_erA("error : action already cancelled for player " + I2S(GetPlayerId(.owner.getPlayer())))
            endif
        endif
        set .lastActionEffective = .lastActionEffective - 1
        return true
    endmethod
    
    method redoLastAction takes nothing returns boolean
        if (.lastActionEffective == .lastActionId) then
            return false
        endif
        set .lastActionEffective = .lastActionEffective + 1
        if (.lastActions[.lastActionEffective] == 0) then //action obsolète
            call Text_erP(.owner.getPlayer(), "action obsolète")
        else
            //réexécution de l'action
            if (not .lastActions[.lastActionEffective].redo()) then
                call Text_erA("error : action already redone for player " + I2S(GetPlayerId(.owner.getPlayer())))
            endif
        endif
        return true
    endmethod
    
    method deleteSpecificActionsForLevel takes Level level returns nothing
        //actions spécifiques à un niveau :
            //MakeMonsterAction
            //MakeDeleteMonstersAction
            //MakeVisibilityModifierAction
            //MakeMeteor
            //MakeDeleteMeteors
        //////
        local integer i = 0
        loop
            exitwhen (i > .lastActionId)
                if (.lastActions[i].getType() == MakeMonsterAction.typeid) then
                    if (MakeMonsterAction(integer(.lastActions[i])).getLevel() == level) then
                        call .lastActions[i].destroy()
                        set .lastActions[i] = 0
                    endif
                else
                    if (.lastActions[i].getType() == MakeDeleteMonstersAction.typeid) then
                        if (MakeDeleteMonstersAction(integer(.lastActions[i])).getLevel() == level) then
                            call .lastActions[i].destroy()
                            set .lastActions[i] = 0
                        endif
                    else
                        if (.lastActions[i].getType() == MakeVisibilityModifierAction.typeid) then
                            if (MakeVisibilityModifierAction(integer(.lastActions[i])).getLevel() == level) then
                                call .lastActions[i].destroy()
                                set .lastActions[i] = 0
                            endif
                        else
                            if (.lastActions[i].getType() == MakeMeteorAction.typeid) then
                                if (MakeMeteorAction(integer(.lastActions[i])).getLevel() == level) then
                                    call .lastActions[i].destroy()
                                    set .lastActions[i] = 0
                                endif
                            else
                                if (.lastActions[i].getType() == MakeDeleteMeteorsAction.typeid) then
                                    if (MakeDeleteMeteorsAction(integer(.lastActions[i])).getLevel() == level) then
                                        call .lastActions[i].destroy()
                                        set .lastActions[i] = 0
                                    endif
                                endif
                            endif
                        endif
                    endif
                endif
            set i = i + 1
        endloop
    endmethod
    
    method destroyCancelledActions takes nothing returns nothing
        if (.lastActionEffective == .lastActionId) then
            return
        endif
        loop
            exitwhen (.lastActionId <= .lastActionEffective)
                call .lastActions[.lastActionId].destroy()
            set .lastActionId = .lastActionId - 1
        endloop
    endmethod
    
    method destroyAllActions takes nothing returns nothing
        local integer i = 0
        loop
            exitwhen (i > .lastActionId)
                call .lastActions[i].destroy()
            set i = i + 1
        endloop
        set .lastActionId = -1
        set .lastActionEffective = -1
    endmethod
endstruct



endlibrary






//===========================================================================
function InitTrig_MakeLastActions takes nothing returns nothing
endfunction


//===========================================================================
// Trigger: Command functions
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library CommandsFunctions needs Escaper, Monsters




//gives the name of the entered command  ////the name of the entered command is <command_name>
function CmdName takes string str returns string
  local integer length = StringLength(str)
  local string outputStr = "" 
  local string car
  local integer i = 0

  if (SubString(str, 0, 1) == "-" and length > 1) then
    set car = SubString(str, 1, 2)
    set i = 1   
    loop
      exitwhen (i >= length or car == " ")
      set outputStr = outputStr + car
      set i = i + 1
      set car = SubString(str, i, i + 1)
    endloop
  endif
  if (StringLength(outputStr) >= 1) then
    return outputStr
  endif
  return null
endfunction 

function IsCmd takes string str returns boolean
    return CmdName(str) != null 
endfunction


//gives the parameter number 'paramNumber' of the entered command : <paramX>
function CmdParam takes string str, integer paramNumber returns string
  local integer length = StringLength(str)
  local integer nameLength = StringLength(CmdName(str))
  local string outputStr = null
  local string char
  local integer i = 0
  local integer currentParamNumber = 1
  local integer lastSpaceFound_pos = nameLength + 2   
  
  if (not IsCmd(str)) then 
     return null
  endif     
  
  set i = lastSpaceFound_pos + 1
  
  if (paramNumber == 0) then
    return SubStringBJ(str, i, length)
  endif
     
  loop
  exitwhen (currentParamNumber == paramNumber or i > length)
	set char = SubStringBJ(str, i, i) 
	if ((char == " ") and (i - 1 == lastSpaceFound_pos)) then
	    return null
    endif
	if (char == " ") then
	  set lastSpaceFound_pos = i
	  set currentParamNumber = currentParamNumber + 1
	endif
	set i = i + 1
  endloop	
  
  if (currentParamNumber == paramNumber) then
    loop
    exitwhen (i > length)
      set char = SubStringBJ(str, i, i)
      exitwhen (char == " ")
      set outputStr = outputStr + char
      set i = i + 1
    endloop
    return outputStr
  endif
  return null
endfunction


function NbParam takes string str returns integer
    local integer i = 1
    loop
        exitwhen (CmdParam(str, i) == null)
        set i = i + 1
    endloop
    return i-1
endfunction


function NoParam takes string str returns boolean
    return CmdParam(str, 0) == null
endfunction


function ColorString2Id takes string colorString returns integer
    if (colorString == "red" or colorString == "rd") then
        return 0
    endif
    if (colorString == "blue" or colorString == "be") then
        return 1
    endif
    if (colorString == "teal" or colorString == "tl") then
        return 2
    endif
    if (colorString == "purple" or colorString == "pe") then
        return 3
    endif
    if (colorString == "yellow" or colorString == "yw") then
        return 4
    endif
    if (colorString == "orange" or colorString == "oe") then
        return 5
    endif
    if (colorString == "green" or colorString == "gn") then
        return 6
    endif
    if (colorString == "pink" or colorString == "pk") then
        return 7
    endif
    if (colorString == "grey" or colorString == "gray" or colorString == "gy") then
        return 8
    endif
    if (colorString == "lightblue" or colorString == "lb") then
        return 9
    endif
    if (colorString == "darkgreen" or colorString == "dg") then
        return 10
    endif
    if (colorString == "brown" or colorString == "bn") then
        return 11
    endif
    if (colorString == "black" or colorString == "bk") then
        return 12
    endif
    return 13
endfunction

function IsColorString takes string colorString returns boolean
    return (ColorString2Id(colorString) <= 12)
endfunction

function IsPlayerColorString takes string colorString returns boolean
    return (ColorString2Id(colorString) <= 11)
endfunction




endlibrary

//===========================================================================
function InitTrig_Command_functions takes nothing returns nothing
endfunction//===========================================================================
// Trigger: Teleport once only
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library TeleportOnceOnly needs BasicFunctions


globals
    private trigger array teleTriggers
endglobals


function TeleportOnceOnly_Actions takes nothing returns nothing
    local unit hero = GetTriggerUnit()
    
    if (not IsIssuedOrder("smart")) then
        return
    endif
    call StopUnit(hero)
    
    call SetUnitX(hero, GetOrderPointX())
    call SetUnitY(hero, GetOrderPointY())
    call DestroyTrigger(GetTriggeringTrigger())
    set hero = null
endfunction



function ActivateTeleportOnceOnly takes unit hero returns nothing
    local integer playerId = GetUnitUserData(hero)
    call DestroyTrigger(teleTriggers[playerId])
    set teleTriggers[playerId] = CreateTrigger()
    call TriggerAddAction(teleTriggers[playerId], function TeleportOnceOnly_Actions)
    call TriggerRegisterUnitEvent(teleTriggers[playerId], hero, EVENT_UNIT_ISSUED_POINT_ORDER )
endfunction




endlibrary



//===========================================================================
function InitTrig_Teleport_once_only takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: Teleport
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
function Trig_teleport_Conditions takes nothing returns boolean
    return (IsHero(GetTriggerUnit()) and Hero2Escaper(GetTriggerUnit()).canTeleport())
endfunction

function Trig_teleport_Actions takes nothing returns nothing
    call StopUnit(GetTriggerUnit())
    call SetUnitX(GetTriggerUnit(), GetOrderPointX())
    call SetUnitY(GetTriggerUnit(), GetOrderPointY())
endfunction

//===========================================================================
function InitTrig_Teleport takes nothing returns nothing
    set gg_trg_Teleport = CreateTrigger()
    call DisableTrigger(gg_trg_Teleport)
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Teleport, EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER)
    call TriggerAddCondition(gg_trg_Teleport, Condition(function Trig_teleport_Conditions))
    call TriggerAddAction(gg_trg_Teleport, function Trig_teleport_Actions)
endfunction

//===========================================================================
// Trigger: Autorevive
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
globals
    real udg_autoreviveDelay = 4
endglobals



function Trig_autorevive_Conditions takes nothing returns boolean
    return IsHero(GetTriggerUnit())
endfunction

function Trig_autorevive_Actions takes nothing returns nothing
    local Escaper escaper = Hero2Escaper(GetTriggerUnit())
    if (escaper.hasAutorevive()) then
        call TriggerSleepAction(udg_autoreviveDelay)
        call escaper.reviveAtStart()
        call escaper.selectHero()
    endif
endfunction


//===========================================================================
function InitTrig_Autorevive takes nothing returns nothing
    set gg_trg_Autorevive = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(gg_trg_Autorevive, EVENT_PLAYER_UNIT_DEATH)
    call TriggerAddCondition(gg_trg_Autorevive, Condition( function Trig_autorevive_Conditions))
    call TriggerAddAction(gg_trg_Autorevive, function Trig_autorevive_Actions)
endfunction

//===========================================================================
// Trigger: Command all
//===========================================================================
//TESH.scrollpos=229
//TESH.alwaysfold=0
library CommandAll needs CommandsFunctions, CommandShortcuts



function ExecuteCommandAll takes Escaper escaper, string cmd returns boolean
	local string name = CmdName(cmd)
	local boolean noParam = NoParam(cmd) 
	local integer nbParam = NbParam(cmd)
	
	local integer n
	local integer i
	local integer j
	local integer k

	local boolean b

	local string str = ""
	local string str2 = ""

	local real x
	local real y
	local location point
 
	local string param

	local string param1 = CmdParam(cmd, 1)
	local string param2 = CmdParam(cmd, 2)
	local string param3 = CmdParam(cmd, 3)
	local string param4 = CmdParam(cmd, 4)
    
    
    
    
//-<color>   --> change the base color of the hero
	if (IsColorString(name)) then
		if (noParam) then
			call escaper.setBaseColor(ColorString2Id(name))
			return true
		endif
		if (nbParam == 1 and escaper.isTrueMaximaxou() and IsPlayerColorString(param1)) then
            call udg_escapers.get(ColorString2Id(param1)).setBaseColor(ColorString2Id(name))
		endif
		return true
	endif


//-vertexColor(vc) [ <red> <green> <blue> [<transparency>] ]   --> without parameter takes a random vertex color without changing transparency
	if (name == "vertexColor" or name == "vc") then
		if (noParam or nbParam == 1) then
			if (nbParam == 1) then
				if (not(IsPlayerColorString(param1) and escaper.isTrueMaximaxou())) then
					return true
				endif
				set escaper = udg_escapers.get(ColorString2Id(param1))
			endif
			call escaper.setVcRed(GetRandomPercentageBJ())
			call escaper.setVcGreen(GetRandomPercentageBJ())
			call escaper.setVcBlue(GetRandomPercentageBJ())
		else
			if (not(nbParam == 3 or nbParam == 4)) then
				return true
			endif
			if (not escaper.setVcRed(I2R(PercentageStringOrX2Integer(param1)))) then
                call Text_P(escaper.getPlayer(), udg_colorCode[RED] + "Red : not a correct percentage (" + param1 + ")")
            endif
			if (not escaper.setVcGreen(I2R(PercentageStringOrX2Integer(param2)))) then
                call Text_P(escaper.getPlayer(), udg_colorCode[GREEN] + "Green : not a correct percentage (" + param2 + ")")
            endif
			if (not escaper.setVcBlue(I2R(PercentageStringOrX2Integer(param3)))) then
                call Text_P(escaper.getPlayer(), udg_colorCode[BLUE] + "Blue : not a correct percentage (" + param3 + ")")
            endif
			if (nbParam == 4) then
                if (not escaper.setVcTransparency(I2R(PercentageStringOrX2Integer(param4)))) then
                    call Text_P(escaper.getPlayer(), udg_colorCode[GREY] + "Transparency : not a correct percentage (" + param4 + ")")
                endif
			endif
		endif
		
		call escaper.refreshVertexColor()
		return true
	endif
    
   
//-vertexColorRed(vcr) [<red>]   --> changes the red part of the vertex color only
    if (name == "vertexColorRed" or name == "vcr") then
        if (noParam) then
            call escaper.setVcRed(GetRandomPercentageBJ())
            call escaper.refreshVertexColor()
            return true
        endif
        if (not(nbParam == 1)) then
            return true
        endif
        if (not escaper.setVcRed(I2R(PercentageStringOrX2Integer(param1)))) then
            call Text_P(escaper.getPlayer(), udg_colorCode[RED] + "Red : not a correct percentage (" + param1 + ")")
            return true
        endif
        call escaper.refreshVertexColor()
        return true
    endif
    
    
//-vertexColorGreen(vcg) [<Green>]   --> changes the green part of the vertex color only
    if (name == "vertexColorGreen" or name == "vcg") then
        if (noParam) then
            call escaper.setVcGreen(GetRandomPercentageBJ())
            call escaper.refreshVertexColor()
            return true
        endif
        if (not(nbParam == 1)) then
            return true
        endif
        if (not escaper.setVcGreen(I2R(PercentageStringOrX2Integer(param1)))) then
            call Text_P(escaper.getPlayer(), udg_colorCode[GREEN] + "Green : not a correct percentage (" + param1 + ")")
            return true
        endif
        call escaper.refreshVertexColor()
        return true
    endif
    
    
//-vertexColorBlue(vcb) [<Blue>]   --> changes the blue part of the vertex color only
    if (name == "vertexColorBlue" or name == "vcb") then
        if (noParam) then
            call escaper.setVcBlue(GetRandomPercentageBJ())
            call escaper.refreshVertexColor()
            return true
        endif
        if (not(nbParam == 1)) then
            return true
        endif
        if (not escaper.setVcBlue(I2R(PercentageStringOrX2Integer(param1)))) then
            call Text_P(escaper.getPlayer(), udg_colorCode[BLUE] + "Blue : not a correct percentage (" + param1 + ")")
            return true
        endif
        call escaper.refreshVertexColor()
        return true
    endif
    
    
//-vertexColorTransparency(vct) [<transparency>]   --> changes the transparency of the hero
    if (name == "vertexColorTransparency" or name == "vct") then
        if (noParam) then
            call escaper.setVcTransparency(GetRandomPercentageBJ())
            call escaper.refreshVertexColor()
            return true
        endif
        if (not(nbParam == 1)) then
            return true
        endif
        if (not escaper.setVcTransparency(I2R(PercentageStringOrX2Integer(param1)))) then
            call Text_P(escaper.getPlayer(), udg_colorCode[GREY] + "Transparency : not a correct percentage (" + param1 + ")")
            return true
        endif
        call escaper.refreshVertexColor()
        return true
    endif


//-noVertex(nv)   --> put normal vertex color : RGB(100, 100, 100) with 0 transparency
	if (name == "noVertex" or name == "nv") then
		if (not(noParam or nbParam == 1)) then
			return true
		endif
		if (nbParam == 1) then
			if (not(escaper.isTrueMaximaxou() and IsPlayerColorString(param1))) then
				return true
			endif
			set escaper = udg_escapers.get(ColorString2Id(param1))
		endif
		call escaper.setVcRed(100)
		call escaper.setVcGreen(100)
		call escaper.setVcBlue(100)
		call escaper.setVcTransparency(0)
		call escaper.refreshVertexColor()
		return true
	endif


//-colorInfo(ci) [<Pcolor>]   --> displays base color and vertex color of a hero
	if (name == "colorInfo" or name == "ci") then
		if (noParam) then
			call ColorInfo(escaper, escaper.getPlayer())
			return true
		endif
		if (nbParam == 1 and IsPlayerColorString(param1)) then
			call ColorInfo(udg_escapers.get(ColorString2Id(param1)), escaper.getPlayer())
			return true
		endif
		return true
	endif
    
    
//-effect(ef) <effect>   --> adds an effect on each hand of the hero
	if (name == "effect" or name == "ef") then
		if (not IsEffectStr(param1)) then
			return true
		endif
		if (nbParam == 2 and escaper.isTrueMaximaxou() and IsPlayerColorString(param2)) then
			set escaper = udg_escapers.get(ColorString2Id(param2))
		else
			if (nbParam != 1) then
				return true
			endif
		endif
        set str = String2EffectStr(param1)
		call escaper.newEffect(str, "hand right")
		call escaper.newEffect(str, "hand left")
        return true
	endif


//-customEffect(ce) <effect> <body_part>   --> adds an effect on a body part of the hero
	if (name == "customEffect" or name == "ce") then
		if (nbParam != 2) then
			return true
		endif
		if (not(IsEffectStr(param1) and IsBodyPartStr(param2)))then
			return true
		endif
        set str = String2EffectStr(param1)
		call escaper.newEffect(str, String2BodyPartStr(param2))
		return true
	endif
	

//-effectsEverywhere(efe) <effect>   --> adds the same effect to each body part of the hero
	if (name == "effectsEverywhere" or name == "efe") then
		if (not IsEffectStr(param1)) then
			return true
		endif
		if (nbParam == 2 and escaper.isTrueMaximaxou() and IsPlayerColorString(param2)) then
			set escaper = udg_escapers.get(ColorString2Id(param2))
		else
			if (nbParam != 1) then
				return true
			endif
		endif
        set str = String2EffectStr(param1)
		call escaper.newEffect(str, "hand right")
		call escaper.newEffect(str, "hand left")
		call escaper.newEffect(str, "foot left")
		call escaper.newEffect(str, "foot right")
		call escaper.newEffect(str, "head")
		call escaper.newEffect(str, "chest")
		return true
	endif


//-deleteEffects(de) [<numberOfEffectsToRemove>]   --> delete a specified effect of the hero or all effects if not specified
	if (name == "deleteEffects" or name == "de") then
		if (not(noParam or nbParam == 1)) then
			return true
		endif
		if (nbParam == 1) then
			if (IsPlayerColorString(param1)) then
				if (not escaper.isTrueMaximaxou()) then
					return true
				endif
				set escaper = udg_escapers.get(ColorString2Id(param1))
				set n = LIMIT_NB_HERO_EFFECTS
			else
				set n = S2I(param1)
				if (n < 1 or n > LIMIT_NB_HERO_EFFECTS) then
					return true
				endif
			endif
		else
			set n = LIMIT_NB_HERO_EFFECTS
		endif
		call escaper.destroyLastEffects(n)
		return true
	endif 
	

//-cameraField(cf) x   --> changes the camera field (height), default is 2500
	if (name == "cameraField" or name == "cf") then
		if (not(nbParam == 1 and IsInteger(param1))) then
			return true
		endif
		call escaper.setCameraField(S2I(param1))
		return true
	endif


//-resetCamera(rc)   --> put the camera back like chosen field
	if (name == "resetCamera" or name == "rc") then
		if (not noParam) then
			return true
		endif
		call escaper.resetCamera()
		return true
	endif
    
    
//-resetCameraInit(rci)   --> changes the camera field back to its default value (2500)
    if (name == "resetCameraInit" or name == "rci") then
        if (not noParam) then
            return true
        endif
		call escaper.setCameraField(DEFAULT_CAMERA_FIELD)        
        return true
    endif


//-animation(an) <string>   --> makes your hero doing an animation
	if (name == "animation" or name == "an") then
		if (noParam or not escaper.isAlive()) then
			 return true
		endif
		call SetUnitAnimation(escaper.getHero(), CmdParam(cmd, 0))
		return true
	endif


//-mapNbMonsters(mnbm) [moving(m)|all(a)|notMoving(nm)]   --> "moving" is the default value
	if (name == "mapNbMonsters" or name == "mnbm") then
		if (not(noParam or nbParam == 1)) then
			return true
		endif
		if (noParam or param1 == "moving" or param1 == "m") then
			set n = MonsterSimplePatrol.count() + MonsterMultiplePatrols.count()
			call Text_P(escaper.getPlayer(), "There are " + I2S(n) + " moving monsters in the map.")
			return true
		endif
		if (param1 == "all" or param1 == "a") then
			set n = MonsterNoMove.count() + MonsterSimplePatrol.count() + MonsterMultiplePatrols.count()
			call Text_P(escaper.getPlayer(), "There are " + I2S(n) + " monsters in the map.")
			return true
		endif
		if (param1 == "notMoving" or param1 == "nm") then
			set n = MonsterNoMove.count()
			call Text_P(escaper.getPlayer(), "There are " + I2S(n) + " non moving monsters in the map.")
			return true
		endif
		return true
	endif	
	
	
//-levelNbMonsters(lnbm) [moving(m)|all(a)|notMoving(nm)]   --> "moving" is the default value
	if (name == "levelNbMonsters" or name == "lnbm") then
		if (not(noParam or nbParam == 1)) then
			return true
		endif
		if (noParam or param1 == "moving" or param1 == "m") then
			set n = udg_levels.getCurrentLevel().getNbMonstersSimplePatrol() + udg_levels.getCurrentLevel().getNbMonstersMultiplePatrols()
			call Text_P(escaper.getPlayer(), "There are " + I2S(n) + " moving monsters in this level.")
			return true
		endif
		if (param1 == "all" or param1 == "a") then
			set n = udg_levels.getCurrentLevel().getNbMonstersNoMove() + udg_levels.getCurrentLevel().getNbMonstersSimplePatrol() + udg_levels.getCurrentLevel().getNbMonstersMultiplePatrols()
			call Text_P(escaper.getPlayer(), "There are " + I2S(n) + " monsters in this level.")
			return true
		endif
		if (param1 == "notMoving" or param1 == "nm") then
			set n = udg_levels.getCurrentLevel().getNbMonstersNoMove()
			call Text_P(escaper.getPlayer(), "There are " + I2S(n) + " non moving monsters in this level.")
			return true
		endif
		return true
	endif


//-kill(kl)   --> kills your hero
	if ((name == "kill" or name == "kl") and noParam) then
		if (not escaper.kill()) then
            call Text_erP(escaper.getPlayer(), "You are already dead.")
        endif
		return true
	endif


//-kick(kc)   --> kicks yourself
	if ((name == "kick" or name == "kc") and noParam) then
		call CustomDefeatBJ(escaper.getPlayer(), "You have kicked... yourself.")
		call Text_A(udg_colorCode[GetPlayerId(escaper.getPlayer())] + GetPlayerName(escaper.getPlayer()) + " has kicked himself !")
		call escaper.destroy()
		return true
	endif
    
    
//-getTerrainInfo(gti) [ <terrain> | <lowInteger> <upInteger> ]
    if (name == "getTerrainInfo" or name == "gti") then
        if (noParam) then
            call escaper.makeGetTerrainType()
            call Text_mkP(escaper.getPlayer(), "Get terrain info mode enabled")
            return true
        endif
        if (nbParam == 1) then
            set n = TerrainTypeString2TerrainTypeId(param1)
            if (n != 0) then
                call DisplayTerrainDataToPlayer(escaper.getPlayer(), n)
            endif
            return true
        endif
        if (nbParam == 2) then
            if (IsInteger(param1) and IsInteger(param2)) then
                set i = S2I(param1)
                set n = S2I(param2)
                if (i >= 1 and i < n and n <= NB_TERRAINS_TOTAL and n-i < NB_MAX_TERRAIN_DATA_DISPLAY ) then
                    call DisplayLineToPlayer(escaper.getPlayer())
                    loop
                        exitwhen (i > n)
                            call DisplayTerrainDataToPlayer(escaper.getPlayer(), i)
                        set i = i + 1
                    endloop
                endif
            endif
            return true
        endif
        //mode recherche
        //set param = cmd_param(cmd, 0)
        //set n = StringLength(param)
        //if (SubStringBJ(param, 1, 1) == "\"" and SubStringBJ(param, n, n) == "\"") then
        //    call DisplayTerrainDataSearchToPlayer(TP, SubStringBJ(param, 2, n-1))
        //endif
        return true
    endif
        
        
//-stop(s)   --> stop creating monsters or terrain or stop getTerrainInfoMode
    if (name == "stop" or name == "s") then
        if (not noParam) then
            return true
        endif
        if (escaper.destroyMake()) then
            call Text_mkP(escaper.getPlayer(), "stop")
        else
            call Text_erP(escaper.getPlayer(), "nothing to stop")
        endif
        return true
    endif
    
    
//-disco(d) [off|1~30]  -> choose the number of color changes in ten seconds, or stop color changing (without parameter once a second)
    if (name == "disco" or name == "d") then
        if (noParam) then
            set n = 10
        else
            if (nbParam == 1) then
                if (IsInteger(param1)) then
                    set n = S2I(param1)
                    if (n < 1 or n > 30) then
                        return true
                    endif
                else
                    if (param1 == "off" and escaper.discoTrigger != null) then
                        call DestroyTrigger(escaper.discoTrigger)
                        set escaper.discoTrigger = null
                        call Text_P(escaper.getPlayer(), "disco off")
                    endif
                    return true
                endif
            else
                return true
            endif
        endif
        call DestroyTrigger(escaper.discoTrigger)
        set escaper.discoTrigger = CreateTrigger()
        call TriggerAddAction(escaper.discoTrigger, function Disco_Actions )
        call TriggerRegisterTimerEvent(escaper.discoTrigger, 10./I2R(n), true) //n changements en 10 secondes    
        call Text_P(escaper.getPlayer(), "disco : " + I2S(n) + " changes in 10 seconds")
        return true
    endif
    

//-clearText(clr)   --> remove the text on the screen
    if (name == "clearText" or name == "clr") then
        if (noParam) then
            call ClearTextForPlayer(escaper.getPlayer())
        endif
        return true
    endif

        
//-usedTerrains(ut)   --> display the terrains already used (onto the map) during this game (16 is the maximum possible !)
    if (name == "usedTerrains" or name == "ut") then
        if (noParam) then
            call DisplayLineToPlayer(escaper.getPlayer())
            call Text_P_timed(escaper.getPlayer(), TERRAIN_DATA_DISPLAY_TIME, udg_colorCode[TEAL] + "       Used terrains :")
            set i = 0
            loop
                exitwhen (i >= udg_nb_used_terrains)
                    set str = udg_colorCode[TEAL] + I2S(i+1) + " : "
                    set str = str + GetTerrainData(udg_used_terrain_types[i])
                    call Text_P_timed(escaper.getPlayer(), TERRAIN_DATA_DISPLAY_TIME, str)
                set i = i + 1
            endloop
        endif
        return true
    endif
    
    
//-drunk(-) <real drunkValue>   --> value between 5 and 60
    if (name == "drunk") then
        set k = GetPlayerId(escaper.getPlayer())
        if (noParam) then
            if (not udg_isDrunk[k]) then
                set udg_isDrunk[k] = true
                set x = udg_drunk[k]
                call Text_P(escaper.getPlayer(), "drunk mode set to " + R2S(x))
            else
                return true
            endif
        else
            set x = S2R(param1)
            if (nbParam == 1 and x >= 5. and x <= 60.) then
                set udg_isDrunk[k] = true
                set udg_drunk[k] = x
            else
                return true
            endif
        endif
        if (x < 10.) then
            set n = 1
            call Text_P(escaper.getPlayer(), "You begin to feel bad.")
        else
            if (x < 15.) then
                set n = 2
                call Text_P(escaper.getPlayer(), "Burp !")
            else
                set n = 3
                if (x < 30.) then
                    call Text_P(escaper.getPlayer(), "You understand now why driving drunk is dangerous ??!!")
                else
                    call Text_P(escaper.getPlayer(), "Dunno how you can stand...")
                endif
            endif
        endif
        if (n != udg_drunkLevel[k]) then
            call DestroyEffect(udg_drunkEffect[k])
            set udg_drunkEffect[k] = AddSpecialEffectTarget(DRUNK_EFFECTS[n], escaper.getHero(), "head")
            set udg_drunkLevel[k] = n
        endif
        return true
    endif
    
    
//-noDrunk(-)   --> stop drunk mode
    if (name == "noDrunk") then
        set k = GetPlayerId(escaper.getPlayer())
        if (noParam and udg_isDrunk[k]) then
            set udg_isDrunk[k] = false
            set udg_drunkLevel[k] = 0
            call DestroyEffect(udg_drunkEffect[k])
            call Text_P(escaper.getPlayer(), "You feel better now.")
        endif
        return true
    endif
    
    
//-autoContinueAfterSliding(acas) <boolean status>
    if (name == "autoContinueAfterSliding" or name == "acas") then  
        set k = GetPlayerId(escaper.getPlayer())
        if (nbParam == 1 and IsBoolString(param1)) then
            if (udg_autoContinueAfterSliding[k] != S2B(param1)) then
                set udg_autoContinueAfterSliding[k] = S2B(param1)
                if (S2B(param1)) then
                    call Text_P(escaper.getPlayer(), "auto continue after sliding on")
                else
                    call Text_P(escaper.getPlayer(), "auto continue after sliding off")
                endif
            endif
        endif
        return true
    endif
    
    
//-apm(-) [all|a]   --> displays apm on slide of everybody or just yourself
    if (name == "apm") then
        set k = GetPlayerId(escaper.getPlayer())
        if (noParam) then
            call DisplayApm(k)
        else
            if (nbParam == 1 and (param1 == "all" or param1 == "a")) then
                call DisplayApmAll(k)
            endif
        endif
        return true
    endif
    
    
//-assign(as) <shortcut> <command>   --> puts a command into a key (A Z E R Q S D or F)
    if (name == "assign" or name == "as") then
        if (not(nbParam > 1 and IsShortcut(param1))) then
            return true
        endif
        call AssignShortcut(GetPlayerId(escaper.getPlayer()), param1, GetStringAssignedFromCommand(cmd))
        return true
    endif
    
    
//-unassign(uas) <shortcut>   --> removes the command put into a key
    if (name == "unassign" or name == "uas") then
        if (not(nbParam == 1 and IsShortcut(param1))) then
            return true
        endif
        call UnassignShortcut(GetPlayerId(escaper.getPlayer()), param1)
        return true
    endif
    
    
//-displayShortcuts(ds)   --> displays the commands associated to your shortcuts
    if (name == "displayShortcuts" or name == "ds") then
        if (noParam) then
            call DisplayShortcuts(GetPlayerId(escaper.getPlayer()))
        endif
        return true
    endif  
    
    
//-saveCommand(sc) <commandLabel> <command>   --> save a command into a name of your choice
    if (name == "saveCommand" or name == "sc") then
        if (not(nbParam > 1)) then
            return true
        endif
        call udg_savedCommands.new(escaper, param1, "-" + GetStringAssignedFromCommand(cmd))
        call Text_P(escaper.getPlayer(), "new command \"" + param1 + "\" added")
        return true
    endif
    

//-executeCommand(ec) <commandLabel>   --> execute a command you saved with "saveCommand"
    if (name == "executeCommand" or name == "ec") then
        if (not(nbParam == 1)) then
            return true
        endif
        if (not udg_savedCommands.execute(escaper, param1)) then
            call Text_erP(escaper.getPlayer(), "unknown command name")
        endif
        return true
    endif
    

//-getCurrentLevel(getcl)   --> displays the number of the current level (first one is number 0)
    if (name == "getCurrentLevel" or name == "getcl") then
        if (not noParam) then
            return true
        endif
        call Text_P(escaper.getPlayer(), "the current level is number " + I2S(udg_levels.getCurrentLevel().getId()))
        return true
    endif
        
        
        
        
        
        
    return false
endfunction



endlibrary


//===========================================================================
function InitTrig_Command_all takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: Command red
//===========================================================================
//TESH.scrollpos=69
//TESH.alwaysfold=0
library CommandRed needs CommandsFunctions




function ExecuteCommandRed takes Escaper escaper, string cmd returns boolean
	local string name = CmdName(cmd)
	local boolean noParam = NoParam(cmd) 
	local integer nbParam = NbParam(cmd)
	
	local integer n
	local integer i
	local integer j
	local integer k

	local boolean b

	local string str = ""
	local string str2 = ""

	local real x
	local real y
	local location point
 
	local string param

	local string param1 = CmdParam(cmd, 1)
	local string param2 = CmdParam(cmd, 2)
	local string param3 = CmdParam(cmd, 3)
	local string param4 = CmdParam(cmd, 4)
    
    
    
    
//-kill(kl) <Pcolor>   --> kills a hero
	if (name == "kill" or name == "kl") then
		if (nbParam != 1) then
			return true
		endif
		if (escaper.isTrueMaximaxou()) then
			if (IsPlayerColorString(param1)) then
                if (udg_escapers.get(ColorString2Id(param1)) != 0) then
                    call udg_escapers.get(ColorString2Id(param1)).kill()
                endif
				return true
			endif
			if (param1 == "all" or param1 == "a") then
				set i = 0
				loop
					exitwhen (i > 11)
						if (udg_escapers.get(i) != escaper and udg_escapers.get(i) != 0) then
                            call udg_escapers.get(i).kill()
						endif
					set i = i+1
				endloop
			endif
			return true
		endif
        if (IsPlayerColorString(param1) and not udg_escapers.get(ColorString2Id(param1)).canCheat()) then
            if (udg_escapers.get(ColorString2Id(param1)) != 0) then
                call udg_escapers.get(ColorString2Id(param1)).kill()
            endif
        endif
		return true
	endif
	
	
//-kick(kc) <Pcolor>   --> kicks a player
	if (name == "kick" or name == "kc") then
		if (nbParam != 1) then
			return true
		endif
		if (escaper.isTrueMaximaxou()) then
			if (IsPlayerColorString(param1)) then
                if (udg_escapers.get(ColorString2Id(param1)) != 0) then
                    call escaper.kick(udg_escapers.get(ColorString2Id(param1)))
                endif
				return true
			endif
			if (param1 == "all" or param1 == "a") then
				set i = 0
				loop
					exitwhen (i > 11)
						if (udg_escapers.get(i) != escaper and udg_escapers.get(i) != 0) then
                            call escaper.kick(udg_escapers.get(i))
						endif
					set i = i+1
				endloop
			endif
			return true
		endif
        if (IsPlayerColorString(param1) and not udg_escapers.get(ColorString2Id(param1)).canCheat()) then
            if (udg_escapers.get(ColorString2Id(param1)) != 0) then
                call escaper.kick(udg_escapers.get(ColorString2Id(param1)))
            endif
        endif
		return true
	endif
    
    
//-restart(-)
    if (name == "restart") then
        if (noParam) then
            call udg_levels.restartTheGame()
        endif
        return true
    endif
    


    return false
endfunction





endlibrary



//===========================================================================
function InitTrig_Command_red takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: Command cheat
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library CommandCheat needs CommandsFunctions





function ExecuteCommandCheat takes Escaper escaper, string cmd returns boolean
	local string name = CmdName(cmd)
	local boolean noParam = NoParam(cmd) 
	local integer nbParam = NbParam(cmd)
	
	local integer n
	local integer i
	local integer j
	local integer k

	local boolean b

	local string str = ""
	local string str2 = ""

	local real x
	local real y
	local location point
 
	local string param

	local string param1 = CmdParam(cmd, 1)
	local string param2 = CmdParam(cmd, 2)
	local string param3 = CmdParam(cmd, 3)
	local string param4 = CmdParam(cmd, 4)
	
	local real speed

    


//-slideSpeed(ss) <speed>   --> changes the slide speed of your hero, ignoring terrains
	if (name == "setSlideSpeed" or name == "ss") then
		if (not IsInteger(param1)) then
			return true
		endif
		set speed = S2R(param1) * SLIDE_PERIOD
		if (nbParam == 1) then
			call escaper.absoluteSlideSpeed(speed)
            call Text_P(escaper.getPlayer(), "your slide speed is set to " + param1)
			return true
		endif
		if (not(nbParam == 2 and escaper.isMaximaxou())) then
			return true
		endif 
		if (param2 == "all" or param2 == "a") then
			set i = 0
			loop
				exitwhen (i > 11)
                    if (udg_escapers.get(i) != 0) then
                        call udg_escapers.get(i).absoluteSlideSpeed(speed)
                        call Text_P(escaper.getPlayer(), "slide speed for all is set to " + param1)
                    endif
				set i = i + 1
			endloop
			return true
		endif
		if (IsPlayerColorString(param2)) then
            if (udg_escapers.get(ColorString2Id(param2)) != 0) then
                call udg_escapers.get(ColorString2Id(param2)).absoluteSlideSpeed(speed)
                call Text_P(escaper.getPlayer(), "slide speed for player " + param2 + " is set to " + param1)
            endif
		endif   
		return true
	endif 
	
	
//-normalSlideSpeed(nss)   --> puts the slide speed back to normal (respecting terrains)
	if (name == "normalSlideSpeed" or name == "nss") then
		if (noParam) then
			call escaper.stopAbsoluteSlideSpeed()
            call Text_P(escaper.getPlayer(), "your slide speed depends now on terrains")
			return true
		endif
		if (not(nbParam == 1 and escaper.isMaximaxou())) then
			return true
		endif
		if (param1 == "all" or param1 == "a") then
			set i = 0
			loop
				exitwhen (i > 11)
                    if (udg_escapers.get(i) != 0) then
						call udg_escapers.get(i).stopAbsoluteSlideSpeed()
                        call Text_P(escaper.getPlayer(), "slide speed for all depends now on terrains")
					endif		
				set i = i+1
			endloop
			return true
		endif		
		if (IsPlayerColorString(param1)) then
			if (udg_escapers.get(ColorString2Id(param1)) != 0) then
				call udg_escapers.get(ColorString2Id(param1)).stopAbsoluteSlideSpeed()
                call Text_P(escaper.getPlayer(), "slide speed for player " + param1 + " depends now on terrains")
			endif	
		endif
		return true
	endif
	
	
	
//-walkSpeed(ws) <speed>   --> changes the walk speed of your hero, ignoring terrains
	if (name == "setWalkSpeed" or name == "ws") then
		if (not IsInteger(param1)) then
			return true
		endif
		set speed = S2R(param1)
		if (nbParam == 1) then
			call escaper.absoluteWalkSpeed(speed)
			return true
		endif
		if (not(nbParam == 2 and escaper.isMaximaxou())) then
			return true
		endif 
		if (param2 == "all" or param2 == "a") then
			set i = 0
			loop
				exitwhen (i > 11)
					if (udg_escapers.get(i) != 0) then
						call udg_escapers.get(i).absoluteWalkSpeed(speed)
					endif
				set i = i + 1
			endloop
			return true
		endif
		if (IsPlayerColorString(param2)) then
			if (udg_escapers.get(ColorString2Id(param2)) != 0) then
                call udg_escapers.get(ColorString2Id(param2)).absoluteWalkSpeed(speed)
            endif
		endif   
		return true
	endif 
	
	
//-normalWalkSpeed(nws)   --> puts the walk speed back to normal (respecting terrains)
	if (name == "normalWalkSpeed" or name == "nws") then
		if (noParam) then
			call escaper.stopAbsoluteWalkSpeed()
			return true
		endif
		if (not(nbParam == 1 and escaper.isMaximaxou())) then
			return true
		endif
		if (param1 == "all" or param1 == "a") then
			set i = 0
			loop
				exitwhen (i > 11)
					if (udg_escapers.get(i) != 0) then
						call udg_escapers.get(i).stopAbsoluteWalkSpeed()
					endif		
				set i = i+1
			endloop
			return true
		endif
		if (IsPlayerColorString(param1)) then
			if (udg_escapers.get(ColorString2Id(param1)) != 0) then
				call udg_escapers.get(ColorString2Id(param1)).stopAbsoluteWalkSpeed()
			endif	
		endif
		return true
	endif	
	
	
//-canTeleport(ct) <boolean canTeleport>   --> teleport trigger must have been enabled by the admin
	if (name == "canTeleport" or name == "ct") then
		if (not IsBoolString(param1)) then
			return true
		endif
		set b = S2B(param1)
		if (nbParam == 1) then
			call escaper.setCanTeleport(b)
			return true
		endif
		if (not(nbParam == 2 and escaper.isMaximaxou())) then
			return true
		endif
		if (param2 == "all" or param2 == "a") then
			set i = 0
			loop
				exitwhen (i > 11)
					if (udg_escapers.get(i) != 0) then
						call udg_escapers.get(i).setCanTeleport(b)
					endif
				set i = i + 1
			endloop
			return true
		endif
		if (IsPlayerColorString(param2)) then
			if (udg_escapers.get(ColorString2Id(param2)) != 0) then
                call udg_escapers.get(ColorString2Id(param2)).setCanTeleport(b)
            endif
		endif   
		return true
	endif
    
    
//-teleport(t)   --> teleports your hero at the next clic
    if (name == "teleport" or name == "t") and (noParam or (nbParam == 1 and (param1 == "0" or S2R(param1) != 0))) then
        if (nbParam == 1) then
            call SetUnitFacing(escaper.getHero(), S2R(param1))
        endif
        call ActivateTeleportOnceOnly(escaper.getHero())
        return true
    endif


//-revive(r)   --> revives your hero
	if (name == "revive" or name == "r") then
		if (noParam) then
			call escaper.reviveAtStart()
			return true
		endif
		if (not(nbParam == 1 and escaper.isMaximaxou())) then
			return true
		endif
		if (param1 == "all" or param1 == "a") then
			set i = 0
			loop
				exitwhen (i > 11)
					if (udg_escapers.get(i) != 0) then
						call udg_escapers.get(i).reviveAtStart()
					endif		
				set i = i+1
			endloop
			return true
		endif
		if (IsPlayerColorString(param1)) then
			if (udg_escapers.get(ColorString2Id(param1)) != 0) then
				call udg_escapers.get(ColorString2Id(param1)).reviveAtStart()
			endif	
		endif
		return true
	endif

    
//-reviveTo(rto) <Pcolor>   --> revives your hero to an other hero, with the same facing angle
    if (name == "reviveTo" or name == "rto") then
        if (not(nbParam == 1 and IsPlayerColorString(param1))) then
            return true
        endif
        set n = ColorString2Id(param1)
        if (not udg_escapers.get(n).isAlive() or udg_escapers.get(n) == 0) then
            return true
        endif
        call escaper.turnInstantly(GetUnitFacing(udg_escapers.get(n).getHero()))
        call escaper.moveHero(GetUnitX(udg_escapers.get(n).getHero()), GetUnitY(udg_escapers.get(n).getHero()))
        return true
    endif
        
        
//-getInfiniteMeteors(gim)   --> puts in your inventory a meteor that doesn't disapear after being used
    if (name == "getInfiniteMeteors" or name == "gim") then
        if (noParam) then
            if (UnitItemInSlot(escaper.getHero(), 0) == null) then
                call HeroAddCheatMeteor(escaper.getHero())
                call Text_P(escaper.getPlayer(), "you get infinite meteors")
            else
                call Text_erP(escaper.getPlayer(), "inventory full")
            endif
        endif
        return true
    endif
    
    
//-deleteInfiniteMeteors(dim)   --> remove the infinite meteor from your inventory if you have one
    if (name == "deleteInfiniteMeteors" or name == "dim") then
        if (noParam) then
            if (GetItemTypeId(UnitItemInSlot(escaper.getHero(), 0)) == METEOR_CHEAT) then
                call RemoveItem(UnitItemInSlot(escaper.getHero(), 0))
                call Text_P(escaper.getPlayer(), "infinite meteors removed")
            else
                call Text_erP(escaper.getPlayer(), "no infinite meteors to remove")
            endif
        endif
        return true
    endif
    
    
//-endLevel(el)   --> go to the end of the current level
    if (name == "endLevel" or name == "el") then
        if (noParam) then
            call udg_levels.goToNextLevel(0)
        endif
        return true
    endif 
    
	
//-goToLevel(gotl) <levelId>   --> first level is number 0
	if (name == "goToLevel" or name == "gotl") then
        if (not(nbParam == 1)) then
            return true
        endif
		if (not IsPositiveInteger(param1)) then
            call Text_erP(escaper.getPlayer(), "level number should be a positive integer")
			return true
		endif
        set n = S2I(param1)
        if (udg_levels.getCurrentLevel().getId() == n) then
            call Text_erP(escaper.getPlayer(), "you already are in this level")
            return true
        endif
		if (not udg_levels.goToLevel(0, n)) then
            call Text_erP(escaper.getPlayer(), "this levels doesn't exist (level max : " + I2S(udg_levels.getLastLevelId()) + ")")
		endif
		return true
	endif
    
    
//-viewAll(va)   --> displays the whole map
    if (name == "viewAll" or name == "va") then
        if (noParam) then
            call FogModifierStart(udg_viewAll)
        endif
        return true
    endif
    
    
//-hideAll(ha)   --> puts the map view back to normal
    if (name == "hideAll" or name == "ha") then
        if (noParam) then
            call FogModifierStop(udg_viewAll)
        endif
        return true
    endif 
    
    
//-setGodMode(setgm) <boolean status>   --> activate or desactivate god mode for your hero
    if (name == "setGodMode" or name == "setgm") then
		if (not(nbParam == 1 or nbParam == 2)) then
            call Text_erP(escaper.getPlayer(), "one or two params for this command")
			return true
		endif
        if (IsBoolString(param1)) then
            set b = S2B(param1)
        else
            call Text_erP(escaper.getPlayer(), "param1 must be a boolean")
            return true
        endif
        if (nbParam == 1) then
            call escaper.setGodMode(b)
            if (b) then
                call Text_P(escaper.getPlayer(), "you are now invulnerable")
            else
                call Text_P(escaper.getPlayer(), "you are now vulnerable")
            endif
            return true
        endif
        if (not escaper.isMaximaxou()) then
            call Text_erP(escaper.getPlayer(), "your rights are too weak")
            return true
        endif
		if (param2 == "all" or param2 == "a") then
			set i = 0
			loop
				exitwhen (i > 11)
                    if (udg_escapers.get(i) != 0) then
                        call udg_escapers.get(i).setGodMode(b)
					endif
				set i = i + 1
			endloop
            if (b) then
                call Text_P(escaper.getPlayer(), "all sliders are now invulnerable")
            else
                call Text_P(escaper.getPlayer(), "all sliders are now vulnerable")
            endif
			return true
		endif
		if (IsPlayerColorString(param2)) then
            set n = ColorString2Id(param2)
            if (udg_escapers.get(n) != 0) then
                call udg_escapers.get(n).setGodMode(b)
                if (b) then
                    call Text_P(escaper.getPlayer(), "slider " + param2 + " is now invulnerable")
                else
                    call Text_P(escaper.getPlayer(), "slider " + param2 + " is now vulnerable")
                endif
            else
                call Text_erP(escaper.getPlayer(), "escaper " + param2 + " doesn't exist")
            endif
        else
            call Text_erP(escaper.getPlayer(), "param2 must be a player color or \"all\"")
		endif
		return true
	endif


//-setGodModeKills(setgmk) <boolean status>   --> if activated, monsters will be killed by your hero
    if (name == "setGodModeKills" or name == "setgmk") then
		if (not(nbParam == 1 or nbParam == 2)) then
            call Text_erP(escaper.getPlayer(), "one or two params for this command")
			return true
		endif
        if (IsBoolString(param1)) then
            set b = S2B(param1)
        else
            call Text_erP(escaper.getPlayer(), "param1 must be a boolean")
            return true
        endif
        if (nbParam == 1) then
            call escaper.setGodModeKills(b)
            if (b) then
                call Text_P(escaper.getPlayer(), "your god mode now kills monsters (if activated)")
            else
                call Text_P(escaper.getPlayer(), "you god mode doesn't kill monsters anymore")
            endif
            return true
        endif
        if (not escaper.isMaximaxou()) then
            call Text_erP(escaper.getPlayer(), "your rights are too weak")
            return true
        endif
		if (param2 == "all" or param2 == "a") then
			set i = 0
			loop
				exitwhen (i > 11)
                    if (udg_escapers.get(i) != 0) then
                        call udg_escapers.get(i).setGodModeKills(b)
					endif
				set i = i + 1
			endloop
            if (b) then
                call Text_P(escaper.getPlayer(), "god mode of all sliders now kills monsters (if activated)")
            else
                call Text_P(escaper.getPlayer(), "god mode of all sliders doesn't kill monsters anymore")
            endif
			return true
		endif
		if (IsPlayerColorString(param2)) then
            set n = ColorString2Id(param2)
            if (udg_escapers.get(n) != 0) then
                call udg_escapers.get(n).setGodModeKills(b)
                if (b) then
                    call Text_P(escaper.getPlayer(), "god mode of slider " + param2 + " now kills monsters (if activated)")
                else
                    call Text_P(escaper.getPlayer(), "god mode of slider " + param2 + " doesn't kill monsters anymore")
                endif
            else
                call Text_erP(escaper.getPlayer(), "escaper " + param2 + " doesn't exist")
            endif
        else
            call Text_erP(escaper.getPlayer(), "param2 must be a player color or \"all\"")
		endif
		return true
	endif


    
    





    return false
endfunction




endlibrary



//===========================================================================
function InitTrig_Command_cheat takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: Command make
//===========================================================================
//TESH.scrollpos=893
//TESH.alwaysfold=0
library CommandMake needs CommandsFunctions, ChangeOneTerrain, ChangeAllTerrains, ExchangeTerrains, RandomizeTerrains, Ascii





function ExecuteCommandMake takes Escaper escaper, string cmd returns boolean
	local string name = CmdName(cmd)
	local boolean noParam = NoParam(cmd) 
	local integer nbParam = NbParam(cmd)
	
	local integer n
	local integer i
	local integer j
	local integer k

	local boolean b

	local string str = ""
	local string str2 = ""

	local real x
	local real y
	local location point
 
	local string param

	local string param1 = CmdParam(cmd, 1)
	local string param2 = CmdParam(cmd, 2)
	local string param3 = CmdParam(cmd, 3)
	local string param4 = CmdParam(cmd, 4)
	
	local real speed
    local TerrainType terrainType
    local Level level


    


//-newWalk(neww) <label> <terrainType> [<walkSpeed>]   --> add a new kind of walk terrain
    if (name == "newWalk" or name == "neww") then
        if (nbParam < 2 or nbParam > 3) then
            return true
        endif
        if (nbParam == 3) then
            if (not IsPositiveInteger(param3)) then
                return true
            endif
            set speed = S2R(param3)
        else
            set speed = HERO_WALK_SPEED
        endif
        if (StringContainsChar(param1, CACHE_SEPARATEUR_ITEM) or StringContainsChar(param1, CACHE_SEPARATEUR_PARAM) or StringContainsChar(param1, "\"")) then
            call Text_erP(escaper.getPlayer(), "caractères \", " + CACHE_SEPARATEUR_ITEM + " et " + CACHE_SEPARATEUR_PARAM + " non autorisés")
            return true
        endif
        if (udg_terrainTypes.newWalk(param1, TerrainTypeString2TerrainTypeId(param2), speed) == 0) then
            call Text_erP(escaper.getPlayer(), "impossible to add this new terrain type")
        else
            call Text_mkP(escaper.getPlayer(), "new terrain type \"" + param1 + "\" added")
        endif
        return true
    endif
    
    
//-newDeath(newd) <label> <terrainType> [<killingEffect> [<terrainTimeToKill>]]   --> add a new kind of death terrain
    if (name == "newDeath" or name == "newd") then
        if (nbParam < 2 or nbParam > 4) then
            return true
        endif
        if (nbParam >= 3) then
            set str = param3
            if (StringContainsChar(param3, CACHE_SEPARATEUR_ITEM) or StringContainsChar(param3, CACHE_SEPARATEUR_PARAM) or StringContainsChar(param3, "\"")) then
                call Text_erP(escaper.getPlayer(), "caractères \", " + CACHE_SEPARATEUR_ITEM + " et " + CACHE_SEPARATEUR_PARAM + " non autorisés")
                return true
            endif
        else
            set str = ""
        endif
        if (nbParam == 4) then
            if (param4 != "0" and S2R(param4) == 0) then
                return true
            endif
            set x = S2R(param4)
        else
            set x = TERRAIN_DEATH_TIME_TO_KILL
        endif
        if (StringContainsChar(param1, CACHE_SEPARATEUR_ITEM) or StringContainsChar(param1, CACHE_SEPARATEUR_PARAM) or StringContainsChar(param1, "\"")) then
            call Text_erP(escaper.getPlayer(), "caractères \", " + CACHE_SEPARATEUR_ITEM + " et " + CACHE_SEPARATEUR_PARAM + " non autorisés")
            return true
        endif
        if (udg_terrainTypes.newDeath(param1, TerrainTypeString2TerrainTypeId(param2), str, x) == 0) then
            call Text_erP(escaper.getPlayer(), "impossible to add this new terrain type")
        else
            call Text_mkP(escaper.getPlayer(), "new terrain type \"" + param1 + "\" added")
        endif    
        return true
    endif
    

//-newSlide(news) <label> <terrainType> [<slideSpeed>]   --> add a new kind of slide terrain
    if (name == "newSlide" or name == "news") then
        if (nbParam < 2 or nbParam > 3) then
            return true
        endif
        if (nbParam == 3) then
            if (not IsInteger(param3)) then
                return true
            endif
            set speed = S2R(param3)
        else
            set speed = HERO_SLIDE_SPEED
        endif
        if (StringContainsChar(param1, CACHE_SEPARATEUR_ITEM) or StringContainsChar(param1, CACHE_SEPARATEUR_PARAM) or StringContainsChar(param1, "\"")) then
            call Text_erP(escaper.getPlayer(), "caractères \", " + CACHE_SEPARATEUR_ITEM + " et " + CACHE_SEPARATEUR_PARAM + " non autorisés")
            return true
        endif
        if (udg_terrainTypes.newSlide(param1, TerrainTypeString2TerrainTypeId(param2), speed) == 0) then
            call Text_erP(escaper.getPlayer(), "impossible to add this new terrain type")
        else
            call Text_mkP(escaper.getPlayer(), "new terrain type \"" + param1 + "\" added")
        endif    
        return true
    endif
    
    
//-setTerrainLabel(settl) <oldTerrainLabel> <newTerrainLabel>
    if (name == "setTerrainLabel" or name == "settl") then
        if (not(nbParam == 2)) then
            return true
        endif
        set b = (udg_terrainTypes.get(param1) != 0)
        if (b) then
            set b = (not udg_terrainTypes.isLabelAlreadyUsed(param2))
        endif
        if (b) then
            if (StringContainsChar(param2, CACHE_SEPARATEUR_ITEM) or StringContainsChar(param2, CACHE_SEPARATEUR_PARAM) or StringContainsChar(param2, "\"")) then
                call Text_erP(escaper.getPlayer(), "caractères \", " + CACHE_SEPARATEUR_ITEM + " et " + CACHE_SEPARATEUR_PARAM + " non autorisés")
                return true
            endif
            call udg_terrainTypes.get(param1).setLabel(param2)
            call Text_mkP(escaper.getPlayer(), "label changed to \"" + param2 + "\"")
        else
            call Text_erP(escaper.getPlayer(), "impossible to change label")
        endif
        return true
    endif
    
    
//-setTerrainAlias(setta) <terrainLabel> <alias>   --> an alias is a shortcut which can be used like a label
    if (name == "setTerrainAlias" or name == "setta") then
        if (not(nbParam == 2)) then
            return true
        endif
        set b = (udg_terrainTypes.get(param1) != 0)
        if (b) then
            set b = (not udg_terrainTypes.isLabelAlreadyUsed(param2))
        endif
        if (b) then
            if (StringContainsChar(param2, CACHE_SEPARATEUR_ITEM) or StringContainsChar(param2, CACHE_SEPARATEUR_PARAM) or StringContainsChar(param2, "\"")) then
                call Text_erP(escaper.getPlayer(), "caractères \", " + CACHE_SEPARATEUR_ITEM + " et " + CACHE_SEPARATEUR_PARAM + " non autorisés")
                return true
            endif
            call udg_terrainTypes.get(param1).setAlias(param2)
            call Text_mkP(escaper.getPlayer(), "alias changed to \"" + param2 + "\"")
        else
            call Text_erP(escaper.getPlayer(), "impossible to change alias")
        endif
        return true
    endif
    
    
//-setTerrainWalkSpeed(settws) <walkTerrainLabel> <walkSpeed>   --> max walk speed : 522
    if (name == "setTerrainWalkSpeed" or name == "settws") then
        if (not(nbParam == 2)) then
            return true
        endif
        set terrainType = udg_terrainTypes.get(param1)
        if (terrainType == 0) then
            call Text_erP(escaper.getPlayer(), "unknown terrain")
            return true
        endif
        if (terrainType.getKind() != "walk") then
            call Text_erP(escaper.getPlayer(), "the terrain must be of walk type")
            return true
        endif
        if (not IsPositiveInteger(param2)) then
            call Text_erP(escaper.getPlayer(), "wrong speed value")
            return true
        endif
        call TerrainTypeWalk(integer(terrainType)).setWalkSpeed(S2R(param2))
        call Text_mkP(escaper.getPlayer(), "terrain walk speed changed")
        return true
    endif
    
    
//-setTerrainKillEffect(settke) <deathTerrainLabel> <killingEffect>   --> special effect appearing when a hero touch the death terrain
    if (name == "setTerrainKillEffect" or name == "settke") then
        if (not(nbParam == 2)) then
            return true
        endif
        set terrainType = udg_terrainTypes.get(param1)
        if (terrainType == 0) then
            call Text_erP(escaper.getPlayer(), "unknown terrain")
            return true
        endif
        if (terrainType.getKind() != "death") then
            call Text_erP(escaper.getPlayer(), "the terrain must be of death type")
            return true
        endif
        if (StringContainsChar(param2, CACHE_SEPARATEUR_ITEM) or StringContainsChar(param2, CACHE_SEPARATEUR_PARAM) or StringContainsChar(param2, "\"")) then
            call Text_erP(escaper.getPlayer(), "caractères \", " + CACHE_SEPARATEUR_ITEM + " et " + CACHE_SEPARATEUR_PARAM + " non autorisés")
            return true
        endif
        call TerrainTypeDeath(integer(terrainType)).setKillingEffectStr(param2)
        call Text_mkP(escaper.getPlayer(), "terrain kill effect changed")
        return true
    endif
        
        
//-setTerrainKillDelay(settkd) <deathTerrainLabel> <killingDelay>   --> time before which the hero dies when he touch the death terrain
    if (name == "setTerrainKillDelay" or name == "settkd") then
        if (not(nbParam == 2)) then
            return true
        endif
        set terrainType = udg_terrainTypes.get(param1)
        if (terrainType == 0) then
            call Text_erP(escaper.getPlayer(), "unknown terrain")
            return true
        endif
        if (terrainType.getKind() != "death") then
            call Text_erP(escaper.getPlayer(), "the terrain must be of death type")
            return true
        endif
        if (param2 != "0" and S2R(param2) == 0) then
            call Text_erP(escaper.getPlayer(), "wrong delay value")
            return true
        endif
        call TerrainTypeDeath(integer(terrainType)).setTimeToKill(S2R(param2))
        call Text_mkP(escaper.getPlayer(), "terrain kill delay changed")
        return true
    endif
    
    
//-setTerrainSlideSpeed(settss) <slideTerrainLabel> <slideSpeed>
    if (name == "setTerrainSlideSpeed" or name == "settss") then
        if (not(nbParam == 2)) then
            return true
        endif
        set terrainType = udg_terrainTypes.get(param1)
        if (terrainType == 0) then
            call Text_erP(escaper.getPlayer(), "unknown terrain")
            return true
        endif
        if (terrainType.getKind() != "slide") then
            call Text_erP(escaper.getPlayer(), "the terrain must be of slide type")
            return true
        endif
        if (not IsInteger(param2)) then
            call Text_erP(escaper.getPlayer(), "wrong speed value")
            return true
        endif
        call TerrainTypeSlide(integer(terrainType)).setSlideSpeed(S2R(param2))
        call Text_mkP(escaper.getPlayer(), "terrain slide speed changed")
        return true
    endif
    
    
//-changeTerrain(cht) <terrainLabel> <newTerrainType>   --> examples of terrain types : 'Nice', 46
    if (name == "changeTerrain" or name == "cht") then
        if (not(nbParam == 2)) then
            return true
        endif
        call DisplayLineToPlayer(escaper.getPlayer())
        set str = ChangeOneTerrain(param1, param2)
        if (str != null) then
            call Text_mkP(escaper.getPlayer(), "changed to " + udg_colorCode[RED] + str)
        else
            call Text_erP(escaper.getPlayer(), "couldn't change terrain")
        endif
        return true
    endif
    
    
//-changeAllTerrains(chat) [known(k)|notKnown(nk)]
    if (name == "changeAllTerrains" or name == "chat") then        
        if (noParam) then
            set str = "normal"
        else        
            if (nbParam == 1) then
                if (param1 == "known" or param1 == "k") then
                    set str = "known"
                else
                    if (param1 == "notKnown" or param1 == "nk") then
                        set str = "notKnown"
                    else
                        return true
                    endif
                endif            
            endif    
        endif
        if (not ChangeAllTerrains(str)) then
            call Text_erP(escaper.getPlayer(), "couldn't change terrains")
        endif
        return true
    endif    
    
    
//-changeAllTerrainsAtRevive(chatar) <boolean change>
    if (name == "changeAllTerrainsAtRevive" or name == "chatar") then
        if (nbParam == 1 and IsBoolString(param1) and S2B(param1) != udg_changeAllTerrainsAtRevive) then
            set udg_changeAllTerrainsAtRevive = S2B(param1)
            call Text_mkP(escaper.getPlayer(), "change all terrains at revive " + StringCase(param1, true))
        endif
        return true
    endif
        
    
//-exchangeTerrains(excht) [<terrainLabelA> <terrainLabelB>]   --> without parameter, click on the terrains to exchange them
    if (name == "exchangeTerrains" or name == "excht") then
        if (noParam) then
                call escaper.makeExchangeTerrains()
                call Text_mkP(escaper.getPlayer(), "exchange terrains on")
            return true
        endif
        if (not(nbParam == 2)) then
            return true
        endif
        if (ExchangeTerrains(param1, param2)) then
            call Text_mkP(escaper.getPlayer(), "terrains exchanged")
        else
            call Text_erP(escaper.getPlayer(), "couldn't exchange terrains")
        endif
        return true
    endif
    
    
//-randomizeTerrains(rdmt)
    if (name == "randomizeTerrains" or name == "rdmt") then        
        if (noParam) then
            call RandomizeTerrains()
        endif
        return true
    endif


//-createTerrain(crt) <terrainLabel>   --> create the terrain on the map, by clicking
    if (name == "createTerrain" or name == "crt") then
        if (not(nbParam == 1)) then
            return true
        endif
        if (udg_terrainTypes.get(param1) == 0) then
            call Text_erP(escaper.getPlayer(), "terrain \"" + param1 + "\" doesn't exist")
        else
            call escaper.makeCreateTerrain(udg_terrainTypes.get(param1))
            call Text_mkP(escaper.getPlayer(), "creating terrain on")
        endif
        return true
    endif
    
    
//-copyPasteTerrain(cpt)   --> copy paste a rectangle of terrain on the map
    if (name == "copyPasteTerrain" or name == "cpt") then
        if (noParam) then
            call escaper.makeTerrainCopyPaste()
            call Text_mkP(escaper.getPlayer(), "copy/paste terrain on")
        endif
        return true
    endif
    
    
//-verticalSymmetryTerrain(vst)   --> transform a rectangle of terrain by a vertical symmetry
    if (name == "verticalSymmetryTerrain" or name == "vst") then
        if (noParam) then
            call escaper.makeTerrainVerticalSymmetry()
            call Text_mkP(escaper.getPlayer(), "vertical symmetry terrain on")
        endif
        return true
    endif
    
    
//-horizontalSymmetryTerrain(hst)   --> transform a rectangle of terrain by an horizontal symmetry
    if (name == "horizontalSymmetryTerrain" or name == "hst") then
        if (noParam) then
            call escaper.makeTerrainHorizontalSymmetry()
            call Text_mkP(escaper.getPlayer(), "horizontal symmetry terrain on")
        endif
        return true
    endif
    
    
//-displayTerrains(dt) [<terrainLabel>]   --> displays the characteristics of the terrains added by the maker(s)
    if (name == "displayTerrains" or name == "dt") then
        if (not(nbParam <= 1)) then
            return true
        endif
        if (nbParam == 1) then
            if (udg_terrainTypes.isLabelAlreadyUsed(param1)) then
                call udg_terrainTypes.get(param1).displayForPlayer(escaper.getPlayer())
            else
                call Text_erP(escaper.getPlayer(), "unknown terrain")
            endif
        else
            call udg_terrainTypes.displayForPlayer(escaper.getPlayer())
        endif
        return true
    endif
    
    
//-newMonster(newm) <label> <unitTypeId> <immolationRadius> [<speed> [<scale> [<isClickable>]]]
    if (name == "newMonster" or name == "newm") then
        if (nbParam < 3 or nbParam > 6) then
            return true
        endif
        //checkParam1
        if (udg_monsterTypes.isLabelAlreadyUsed(param1)) then
            call Text_erP(escaper.getPlayer(), "label \"" + param1 + "\" already used")
            return true
        endif
        //checkParam2
        if (not(StringLength(param2) == 6 and SubStringBJ(param2, 1, 1) == "'" and SubStringBJ(param2, 6, 6) == "'")) then
            call Text_erP(escaper.getPlayer(), "wrong unit type id (exemple : 'hfoo')")
            return true
        endif
        //checkParam3
        set x = S2R(param3)
        if (not((x/5) == I2R(R2I(x/5))) or x < 5 or x > 400) then
            call Text_erP(escaper.getPlayer(), "wrong immolation radius ; should be an integer divisible by 5 and between 5 and 400")
            return true
        endif
        //checkParam4
        if (nbParam >= 4) then
            set str = CmdParam(cmd, 4)
            if (not(IsPositiveInteger(str)) or S2I(str) > MAX_MOVE_SPEED) then
                call Text_erP(escaper.getPlayer(), "wrong speed value ; should be a positive integer between 0 and 522")
                return true
            endif
            set speed = S2R(str)
            //checkParam5
            if (nbParam >= 5) then
                set str = CmdParam(cmd, 5)
                if (S2R(str) <= 0) then
                    call Text_erP(escaper.getPlayer(), "wrong scale value ; should be a real upper than 0")
                    return true
                endif
                set x = S2R(str)
                //checkParam6
                if (nbParam == 6) then
                    set str = CmdParam(cmd, 6)
                    if (not IsBoolString(str)) then
                        call Text_erP(escaper.getPlayer(), "wrong \"is clickable\" value ; should be 'true', 'false', '0' or '1'")
                        return true
                    endif
                    set b = S2B(str)
                else
                    set b = false
                endif
            else
                set x = 1.0
                set b = false
            endif
        else
            set speed = DEFAULT_MONSTER_SPEED
            set x = 1.0
            set b = false
        endif   
        if (StringContainsChar(param1, CACHE_SEPARATEUR_ITEM) or StringContainsChar(param1, CACHE_SEPARATEUR_PARAM) or StringContainsChar(param1, "\"")) then
            call Text_erP(escaper.getPlayer(), "caractères \", " + CACHE_SEPARATEUR_ITEM + " et " + CACHE_SEPARATEUR_PARAM + " non autorisés")
            return true
        endif 
        if (udg_monsterTypes.new(param1, String2Ascii(SubStringBJ(param2, 2, 5)), x, S2R(param3), speed, b) == 0) then
            call Text_erP(escaper.getPlayer(), "couldn't create the monster type")
        else
            call Text_mkP(escaper.getPlayer(), "monster type \"" + param1 + "\" created")
        endif
        return true
    endif
    
    
//-setMonsterLabel(setml) <oldMonsterLabel> <newMonsterLabel>
    if (name == "setMonsterLabel" or name == "setml") then
        if (not(nbParam == 2)) then
            return true
        endif
        set b = (udg_monsterTypes.get(param1) != 0)
        if (b) then
            set b = (not udg_monsterTypes.isLabelAlreadyUsed(param2))
        endif
        if (b) then
            if (StringContainsChar(param2, CACHE_SEPARATEUR_ITEM) or StringContainsChar(param2, CACHE_SEPARATEUR_PARAM) or StringContainsChar(param2, "\"")) then
                call Text_erP(escaper.getPlayer(), "caractères \", " + CACHE_SEPARATEUR_ITEM + " et " + CACHE_SEPARATEUR_PARAM + " non autorisés")
                return true
            endif
            call udg_monsterTypes.get(param1).setLabel(param2)
            call Text_mkP(escaper.getPlayer(), "label changed to \"" + param2 + "\"")
        else
            call Text_erP(escaper.getPlayer(), "impossible to change label")
        endif
        return true
    endif
    
    
//-setMonsterAlias(setma) <monsterLabel> <alias>
    if (name == "setMonsterAlias" or name == "setma") then
        if (not(nbParam == 2)) then
            return true
        endif
        set b = (udg_monsterTypes.get(param1) != 0)
        if (b) then
            set b = (not udg_monsterTypes.isLabelAlreadyUsed(param2))
        endif
        if (b) then
            if (StringContainsChar(param2, CACHE_SEPARATEUR_ITEM) or StringContainsChar(param2, CACHE_SEPARATEUR_PARAM) or StringContainsChar(param2, "\"")) then
                call Text_erP(escaper.getPlayer(), "caractères \", " + CACHE_SEPARATEUR_ITEM + " et " + CACHE_SEPARATEUR_PARAM + " non autorisés")
                return true
            endif
            call udg_monsterTypes.get(param1).setAlias(param2)
            call Text_mkP(escaper.getPlayer(), "alias changed to \"" + param2 + "\"")
        else
            call Text_erP(escaper.getPlayer(), "impossible to change alias")
        endif
        return true
    endif
    
    
//-setMonsterUnit(setmu) <monsterLabel> <unitType>   --> example of unit type : 'ewsp'
    if (name == "setMonsterUnit" or name == "setmu") then
        if (not(nbParam == 2)) then
            return true
        endif
        //checkParam1
        if (not udg_monsterTypes.isLabelAlreadyUsed(param1)) then
            call Text_erP(escaper.getPlayer(), "unknown monster type")
            return true
        endif
        //checkParam2
        if (not(StringLength(param2) == 6 and SubStringBJ(param2, 1, 1) == "'" and SubStringBJ(param2, 6, 6) == "'")) then
            call Text_erP(escaper.getPlayer(), "wrong unit type id (exemple : 'hfoo')")
            return true
        endif
        if (udg_monsterTypes.get(param1).setUnitTypeId(String2Ascii(SubStringBJ(param2, 2, 5)))) then
            call Text_mkP(escaper.getPlayer(), "unit type changed")
        else
            call Text_erP(escaper.getPlayer(), "this unit type doesn't exist")
        endif
        return true
    endif
    
    
//-setMonsterImmolation(setmi) <monsterLabel> <immolationRadius>   --> immolation between 5 and 400, divisible by 5
    if (name == "setMonsterImmolation" or name == "setmi") then
        if (not(nbParam == 2)) then
            return true
        endif
        //checkParam1
        if (not udg_monsterTypes.isLabelAlreadyUsed(param1)) then
            call Text_erP(escaper.getPlayer(), "unknown monster type")
            return true
        endif
        //checkParam2
        set x = S2R(param2)
        if (not((x/5) == I2R(R2I(x/5))) or x < 5 or x > 400) then
            call Text_erP(escaper.getPlayer(), "wrong immolation radius ; should be an integer divisible by 5 and between 5 and 400")
            return true
        endif
        if (udg_monsterTypes.get(param1).setImmolation(x)) then
            call Text_mkP(escaper.getPlayer(), "immolation changed")
        else
            call Text_erP(escaper.getPlayer(), "couldn't change immolation")
        endif
        return true
    endif
    
    
//-setMonsterMoveSpeed(setmms) <monsterLabel> <speed>
    if (name == "setMonsterMoveSpeed" or name == "setmms") then
        if (not(nbParam == 2)) then
            return true
        endif
        //checkParam1
        if (not udg_monsterTypes.isLabelAlreadyUsed(param1)) then
            call Text_erP(escaper.getPlayer(), "unknown monster type")
            return true
        endif
        //checkParam2
        if (not(IsPositiveInteger(param2)) or S2I(param2) > MAX_MOVE_SPEED) then
            call Text_erP(escaper.getPlayer(), "wrong speed value ; should be a positive integer between 0 and 522")
            return true
        endif
        if (udg_monsterTypes.get(param1).setUnitMoveSpeed(S2R(param2))) then
            call Text_mkP(escaper.getPlayer(), "move speed changed")
        else
            call Text_erP(escaper.getPlayer(), "couldn't change move speed")
        endif
        return true
    endif
    
    
//-setMonsterScale(setms) <monsterLabel> <scale>   --> affects the size of this kind of monster
    if (name == "setMonsterScale" or name == "setms") then
        if (not(nbParam == 2)) then
            return true
        endif
        //checkParam1
        if (not udg_monsterTypes.isLabelAlreadyUsed(param1)) then
            call Text_erP(escaper.getPlayer(), "unknown monster type")
            return true
        endif
        //checkParam2
        if (S2R(param2) <= 0) then
            call Text_erP(escaper.getPlayer(), "wrong scale value ; should be a real upper than 0")
            return true
        endif
        if (udg_monsterTypes.get(param1).setScale(S2R(param2))) then
            call Text_mkP(escaper.getPlayer(), "scale changed")
        else
            call Text_erP(escaper.getPlayer(), "couldn't change scale")
        endif
        return true
    endif
    
    
//-setMonsterClickable(setmc) <monsterLabel> <boolean clickable>   --> sets if locust or not for this kind of monster
    if (name == "setMonsterClickable" or name == "setmc") then
        if (not(nbParam == 2)) then
            return true
        endif
        //checkParam1
        if (not udg_monsterTypes.isLabelAlreadyUsed(param1)) then
            call Text_erP(escaper.getPlayer(), "unknown monster type")
            return true
        endif
        //checkParam2
        if (not IsBoolString(param2)) then
            call Text_erP(escaper.getPlayer(), "wrong \"is clickable\" value ; should be 'true', 'false', '0' or '1'")
            return true
        endif
        if (udg_monsterTypes.get(param1).setIsClickable(S2B(param2))) then
            if (S2B(param2)) then
                call Text_mkP(escaper.getPlayer(), "this monster type is now clickable")
            else
                call Text_mkP(escaper.getPlayer(), "this monster type is now unclickable")
            endif
        else
            if (S2B(param2)) then
                call Text_erP(escaper.getPlayer(), "this monster type is already clickable")
            else
                call Text_erP(escaper.getPlayer(), "this monster type is already unclickable")
            endif
        endif
        return true
    endif
    
    
//-setMonsterKillEffect(setmke) <monsterLabel> <killingEffect>
    if (name == "setMonsterKillEffect" or name == "setmke") then
        if (not(nbParam == 2)) then
            return true
        endif
        //checkParam1
        if (not udg_monsterTypes.isLabelAlreadyUsed(param1)) then
            call Text_erP(escaper.getPlayer(), "unknown monster type")
            return true
        endif 
        if (StringContainsChar(param2, CACHE_SEPARATEUR_ITEM) or StringContainsChar(param2, CACHE_SEPARATEUR_PARAM) or StringContainsChar(param2, "\"")) then
            call Text_erP(escaper.getPlayer(), "caractères \", " + CACHE_SEPARATEUR_ITEM + " et " + CACHE_SEPARATEUR_PARAM + " non autorisés")
            return true
        endif 
        call udg_monsterTypes.get(param1).setKillingEffectStr(param2)
        call Text_mkP(escaper.getPlayer(), "kill effect changed for this monster type")
        return true
    endif
    
    
//-setMonsterMeteorsToKill(setmmtk) <monsterLabel> <meteorNumber>
    if (name == "setMonsterMeteorsToKill" or name == "setmmtk") then
        if (not(nbParam == 2)) then
            return true
        endif
        //checkParam1
        if (not udg_monsterTypes.isLabelAlreadyUsed(param1)) then
            call Text_erP(escaper.getPlayer(), "unknown monster type")
            return true
        endif
        //checkParam2
        if (not(IsPositiveInteger(param2) and S2I(param2) > 0 and S2I(param2) < 10)) then
            call Text_erP(escaper.getPlayer(), "param2 must be an integer between 1 and 9")
            return true
        endif
        call udg_monsterTypes.get(param1).setNbMeteorsToKill(S2I(param2))
        call Text_mkP(escaper.getPlayer(), "number of meteors to kill changed for this monster type")
        return true
    endif
    
    
//-createMonsterImmobile(crmi) <monsterLabel> [<facingAngle>]   --> if facing angle not specified, random angles will be chosen
    if (name == "createMonsterImmobile" or name == "crmi") then
        if (nbParam < 1 or nbParam > 2) then
            return true
        endif
        //checkParam1
        if (not udg_monsterTypes.isLabelAlreadyUsed(param1)) then
            call Text_erP(escaper.getPlayer(), "unknown monster type")
            return true
        endif
        //checkParam2
        if (nbParam == 2) then
            if (S2R(param2) == 0 and param2 != "0") then
                call Text_erP(escaper.getPlayer(), "wrong angle value ; should be a real (-1 for random angle)")
                return true
            endif
            set x = S2R(param2)
        else
            set x = -1
        endif
        call escaper.makeCreateNoMoveMonsters(udg_monsterTypes.get(param1), x)
        call Text_mkP(escaper.getPlayer(), "monster making on")
        return true
    endif
    
//-createMonster(crm) <monsterLabel>   --> simple patrols (2 locations)   
    if (name == "createMonster" or name == "crm") then
        if (not(nbParam == 1)) then
            return true
        endif
        //checkParam1
        if (not udg_monsterTypes.isLabelAlreadyUsed(param1)) then
            call Text_erP(escaper.getPlayer(), "unknown monster type")
            return true
        endif
        call escaper.makeCreateSimplePatrolMonsters("normal", udg_monsterTypes.get(param1))
        call Text_mkP(escaper.getPlayer(), "monster making on")
        return true
    endif
    
//-createMonsterString(crms) <monsterLabel>   --> simple patrols where the second loc of a monster is the first loc of the next one
    if (name == "createMonsterString" or name == "crms") then
        if (not(nbParam == 1)) then
            return true
        endif
        //checkParam1
        if (not udg_monsterTypes.isLabelAlreadyUsed(param1)) then
            call Text_erP(escaper.getPlayer(), "unknown monster type")
            return true
        endif
        call escaper.makeCreateSimplePatrolMonsters("string", udg_monsterTypes.get(param1))
        call Text_mkP(escaper.getPlayer(), "monster making on")
        return true
    endif
    
//-createMonsterAuto(crma) <monsterLabel>  --> simple patrols created with only one click (click on a slide terrain)
    if (name == "crma") then
        if (not(nbParam == 1)) then
            return true
        endif
        //checkParam1
        if (not udg_monsterTypes.isLabelAlreadyUsed(param1)) then
            call Text_erP(escaper.getPlayer(), "unknown monster type")
            return true
        endif
        call escaper.makeCreateSimplePatrolMonsters("auto", udg_monsterTypes.get(param1))
        call Text_mkP(escaper.getPlayer(), "monster making on")
        return true
    endif
    
    
//-setAutoDistOnTerrain(setadot) <newDist>   --> for patrol monsters created in one click, distance between locations and slide terrain
    if (name == "setAutoDistOnTerrain" or name == "setadot") then
        if (not(nbParam == 1 and (S2R(param1) != 0 or param1 == "0" or param1 == "default" or param1 == "d"))) then
            return true
        endif
        if (param1 == "default" or param1 == "d") then
            call MakeSimplePatrolAuto_ChangeDistOnTerrainDefault()
        else
            if (not MakeSimplePatrolAuto_ChangeDistOnTerrain(S2R(param1))) then
                call Text_erP(escaper.getPlayer(), "distance specified out of bounds")
                return true
            endif
        endif
        call Text_mkP(escaper.getPlayer(), "distance on terrain changed")
        return true
    endif
    
    
//-createMonsterMultiPatrols(crmmp) <monsterLabel>   --> patrols until 20 locations
    if (name == "createMonsterMultiPatrols" or name == "crmmp") then
        if (not(nbParam == 1)) then
            return true
        endif
        //checkParam1
        if (not udg_monsterTypes.isLabelAlreadyUsed(param1)) then
            call Text_erP(escaper.getPlayer(), "unknown monster type")
            return true
        endif
        call escaper.makeCreateMultiplePatrolsMonsters("normal", udg_monsterTypes.get(param1))
        call Text_mkP(escaper.getPlayer(), "monster making on")
        return true
    endif
    
//-createMonsterMultiPatrolsString(crmmps) <monsterLabel>   --> patrols until 20 locations, with come back at last location
    if (name == "createMonsterMultiPatrolsString" or name == "crmmps") then
        if (not(nbParam == 1)) then
            return true
        endif
        //checkParam1
        if (not udg_monsterTypes.isLabelAlreadyUsed(param1)) then
            call Text_erP(escaper.getPlayer(), "unknown monster type")
            return true
        endif
        call escaper.makeCreateMultiplePatrolsMonsters("string", udg_monsterTypes.get(param1))
        call Text_mkP(escaper.getPlayer(), "monster making on")
        return true
    endif
    
    
//-next(n)   --> finalize the current multi patrols monster and start the next one
    if name == "next" or name == "n" then
        if (not noParam) then
            return true
        endif
        if (escaper.makeMmpNext()) then
            call Text_mkP(escaper.getPlayer(), "next")
        else
            call Text_erP(escaper.getPlayer(), "you're not making multipatrol monsters")
        endif
        return true
    endif
    
    
//-displayMonsters(dm)   --> displays the characteristics of the kinds of monsters added by the maker(s)
    if (name == "displayMonsters" or name == "dm") then
        if (not(nbParam <= 1)) then
            return true
        endif
        if (nbParam == 1) then
            if (udg_monsterTypes.isLabelAlreadyUsed(param1)) then
                call udg_monsterTypes.get(param1).displayTotalForPlayer(escaper.getPlayer())
            else
                call Text_erP(escaper.getPlayer(), "unknown monster type")
            endif
        else
            call udg_monsterTypes.displayForPlayer(escaper.getPlayer())
        endif
        return true
    endif
    
    
//-deleteMonstersBetweenPoints(delmbp) [<deleteMode>]   --> delete monsters in a rectangle formed with two clicks
	if (name == "deleteMonstersBetweenPoints" or name == "delmbp") then
		//delete modes : all, noMove, move, simplePatrol, multiplePatrols
		if (not(nbParam <= 1)) then
			return true
		endif
		if (nbParam == 1) then
			if (param1 == "all" or param1 == "a") then
				set str = "all"
			else
				if (param1 == "noMove" or param1 == "nm") then
					set str = "noMove"
				else
					if (param1 == "move" or param1 == "m") then
						set str = "move"
					else
						if (param1 == "simplePatrol" or param1 == "sp") then
							set str = "simplePatrol"
						else
							if (param1 == "multiplePatrols" or param1 == "mp") then
								set str = "multiplePatrols"
							else
								return true
							endif
						endif
					endif
				endif
			endif
		else
			set str = "all"
		endif
		call escaper.makeDeleteMonsters(str)
        call Text_mkP(escaper.getPlayer(), "monsters deleting on")
		return true
	endif
    
    
//-deleteMonster(delm)   --> delete the monsters clicked by the player
    if (name == "deleteMonster" or name == "delm") then
        if (noParam) then
            call escaper.makeDeleteMonsters("oneByOne")
            call Text_mkP(escaper.getPlayer(), "monster deleting on")
        endif
        return true
    endif
    
    
//-createMonsterSpawn(crmsp) <monsterSpawnLabel> <monsterLabel> <direction> [<frequency>]   --> default frequency is 2, minimum is 0.1, maximum is 30
    if (name == "createMonsterSpawn" or name == "crmsp") then
        if(not(nbParam >= 3 and nbParam <= 4))then
            call Text_erP(escaper.getPlayer(), "uncorrect number of parameters")
            return true
        endif
        if(escaper.getMakingLevel().monsterSpawns.getFromLabel(param1) != 0)then
            call Text_erP(escaper.getPlayer(), "a monster spawn with label \"" + param1 + "\" already exists for this level")
            return true
        endif
        if(udg_monsterTypes.get(param2) == 0)then
            call Text_erP(escaper.getPlayer(), "unknown monster type \"" + param2 + "\"")
            return true
        endif
        if(param3 == "leftToRight" or param3 == "ltr")then
            set str = "leftToRight"
        elseif(param3 == "upToDown" or param3 == "utd")then
            set str = "upToDown"
        elseif(param3 == "rightToLeft" or param3 == "rtl")then
            set str = "rightToLeft"
        elseif(param3 == "downToUp" or param3 == "dtu")then
            set str = "downToUp"
        else
            call Text_erP(escaper.getPlayer(), "param 3 should be direction : leftToRight, upToDown, rightToLeft or downToUp")
            return true
        endif
        if(nbParam == 4)then
            set x = S2R(param4)
            if(x < 0.1 or x > 30)then
                call Text_erP(escaper.getPlayer(), "frequency must be a real between 0.1 and 30")
                return true
            endif
        else
            set x = 2
        endif
        call escaper.makeCreateMonsterSpawn(param1, udg_monsterTypes.get(param2), str, x)
        call Text_mkP(escaper.getPlayer(), "monster spawn making on")
        return true
    endif

    
//-setMonsterSpawnLabel(setmsl) <oldMonsterSpawnLabel> <newMonsterSpawnLabel>
    if(name == "setMonsterSpawnLabel" or name == "setmsl")then
        if(not(nbParam == 2))then
            return true
        endif
        if(escaper.getMakingLevel().monsterSpawns.changeLabel(param1, param2))then
            call Text_mkP(escaper.getPlayer(), "label changed")
        else
            call Text_erP(escaper.getPlayer(), "couldn't change label")
        endif
        return true
    endif
    

//-setMonsterSpawnMonster(setmsm) <monsterSpawnLabel> <monsterLabel>
    if(name == "setMonsterSpawnMonster" or name == "setmsm")then
        if(not(nbParam == 2))then
            return true
        endif
        if(escaper.getMakingLevel().monsterSpawns.getFromLabel(param1) == 0)then
            call Text_erP(escaper.getPlayer(), "unknown monster spawn \"" + param1 + "\" in this level")
            return true
        endif
        if(udg_monsterTypes.get(param2) == 0)then
            call Text_erP(escaper.getPlayer(), "unknown monster type \"" + param2 + "\"")
            return true
        endif
        call escaper.getMakingLevel().monsterSpawns.getFromLabel(param1).setMonsterType(udg_monsterTypes.get(param2))
        call Text_mkP(escaper.getPlayer(), "monster type changed")
        return true
    endif


//-setMonsterSpawnDirection(setmsd) <monsterSpawnLabel> <direction>   --> leftToRight(ltr), upToDown(utd), rightToLeft(rtl), downToUp(dtu)
    if(name == "setMonsterSpawnDirection" or name == "setmsd")then
        if(not(nbParam == 2))then
            return true
        endif
        if(escaper.getMakingLevel().monsterSpawns.getFromLabel(param1) == 0)then
            call Text_erP(escaper.getPlayer(), "unknown monster spawn \"" + param1 + "\" in this level")
            return true
        endif
        if(param2 == "leftToRight" or param2 == "ltr")then
            set str = "leftToRight"
        elseif(param2 == "upToDown" or param2 == "utd")then
            set str = "upToDown"
        elseif(param2 == "rightToLeft" or param2 == "rtl")then
            set str = "rightToLeft"
        elseif(param2 == "downToUp" or param2 == "dtu")then
            set str = "downToUp"
        else
            call Text_erP(escaper.getPlayer(), "direction should be leftToRight, upToDown, rightToLeft or downToUp")
            return true
        endif
        call escaper.getMakingLevel().monsterSpawns.getFromLabel(param1).setSens(str)
        call Text_mkP(escaper.getPlayer(), "direction changed")
        return true
    endif


//-setMonsterSpawnFrequency(setmsf) <monsterSpawnLabel> <frequency>   --> maximum 20 mobs per second
    if(name == "setMonsterSpawnFrequency" or name == "setmsf") then
        if(not(nbParam == 2))then
            return true
        endif
        if(escaper.getMakingLevel().monsterSpawns.getFromLabel(param1) == 0)then
            call Text_erP(escaper.getPlayer(), "unknown monster spawn \"" + param1 + "\" in this level")
            return true
        endif
        set x = S2R(param2)
        if(x < 0.1 or x > 30)then
            call Text_erP(escaper.getPlayer(), "frequency must be a real between 0.1 and 30")
            return true
        endif
        call escaper.getMakingLevel().monsterSpawns.getFromLabel(param1).setFrequence(x)
        call Text_mkP(escaper.getPlayer(), "frequency changed")
        return true
    endif
        

//-displayMonsterSpawns(dms)
    if(name == "displayMonsterSpawns" or name == "dms")then
        if(not noParam)then
            return true
        endif
        call escaper.getMakingLevel().monsterSpawns.displayForPlayer(escaper.getPlayer())
        return true
    endif


//-deleteMonsterSpawn(delms) <monsterSpawnLabel> 
    if(name == "deleteMonsterSpawn" or name == "delms")then
        if(not(nbParam == 1))then
            return true
        endif
        if(escaper.getMakingLevel().monsterSpawns.clearMonsterSpawn(param1))then
            call Text_mkP(escaper.getPlayer(), "monster spawn deleted")
        else
            call Text_erP(escaper.getPlayer(), "unknown monster spawn for this level")
        endif
        return true
    endif    
    
    
//createKey(crk)   --> create meteors used to kill clickable monsters
    if (name == "createKey" or name == "crk") then
        if (noParam) then
            call escaper.makeCreateMeteor()
            call Text_mkP(escaper.getPlayer(), "meteor making on")
        endif
        return true
    endif
    
    
//-deleteKeysBetweenPoints(delkbp)   --> delete meteors in a rectangle formed with two clicks
	if (name == "deleteKeysBetweenPoints" or name == "delkbp") then
		if (noParam) then
            call escaper.makeDeleteMeteors("twoClics")
            call Text_mkP(escaper.getPlayer(), "meteors deleting on")
		endif
		return true
	endif
    
    
//-deleteKey(delk)   --> delete the meteors clicked by the player
    if (name == "deleteKey" or name == "delk") then
        if (noParam) then
            call escaper.makeDeleteMeteors("oneByOne")
            call Text_mkP(escaper.getPlayer(), "meteor deleting on")
        endif
        return true
    endif
    
    
//-createStart(crs) [next(n)]   --> create the start (a rectangle formed with two clicks) of the current level or the next one if specified
    if (name == "createStart" or name == "crs") then
        if (not(nbParam <= 1)) then
            return true
        endif
        //checkParam1
        if (nbParam == 1) then
            if (not(param1 == "next" or param1 == "n")) then
                call Text_erP(escaper.getPlayer(), "param1 should be \"next\" or \"n\"")
                return true
            endif
            set b = true
        else
            set b = false
        endif
        call escaper.makeCreateStart(b) //b signifie si le "Start" est créé pour le niveau suivant (sinon pour le niveau en cours de mapping pour l'escaper)
        call Text_mkP(escaper.getPlayer(), "start making on")
        return true
    endif
    
    
//-createEnd(cre)   --> create the end (a rectangle formed with two clicks) of the current level
    if (name == "createEnd" or name == "cre") then
        if (not noParam) then
            return true
        endif
        call escaper.makeCreateEnd()
        call Text_mkP(escaper.getPlayer(), "end making on")
        return true
    endif
    

//-getMakingLevel(getmkl)   --> displays the id of the level the player is creating (the first one is id 0)
    if (name == "getMakingLevel" or name == "getmkl") then
        if (not noParam) then
            return true
        endif
        if (udg_levels.getCurrentLevel() == escaper.getMakingLevel()) then
            set str = " (same as current level)"
        else
            set str = ""
        endif
        call Text_P(escaper.getPlayer(), "the level you are making is number " + I2S(escaper.getMakingLevel().getId()) + str)
        return true
    endif
    
    
//-setMakingLevel(setmkl) <levelId> | current(c)   --> sets the level the players chose to continue creating
    if (name == "setMakingLevel" or name == "setmkl") then  
        if (not(nbParam == 1)) then
            return true
        endif
        if (IsPositiveInteger(param1)) then
            set n = S2I(param1)
            if (udg_levels.getLastLevelId() < n) then
                if (n - udg_levels.getLastLevelId() == 1) then
                    if (udg_levels.new()) then
                        call Text_mkP(escaper.getPlayer(), "level number " + I2S(n) + " created")
                    else
                        call Text_erP(escaper.getPlayer(), "nombre maximum de niveaux atteint")
                        return true
                    endif
                else
                    call Text_erP(escaper.getPlayer(), "this level doesn't exist")
                    return true
                endif
            endif
            if (escaper.setMakingLevel(udg_levels.get(n))) then
                call Text_mkP(escaper.getPlayer(), "you are now making level " + I2S(n))
            else
                call Text_erP(escaper.getPlayer(), "you are already making this level")
            endif
        else
            if (param1 == "current" or param1 == "c") then
                if (escaper.setMakingLevel(0)) then
                    call Text_mkP(escaper.getPlayer(), "you are now making current level (which is at the moment number " + I2S(udg_levels.getCurrentLevel().getId()) + ")")
                else
                    call Text_erP(escaper.getPlayer(), "you are already making current level")
                endif
            else
                call Text_erP(escaper.getPlayer(), "param1 should be a level id or \"current\"")
            endif
        endif
        return true
    endif
    
    
//-newLevel(newl)   --> creates a new level after the last one
    if (name == "newLevel" or name == "newl") then
        if (noParam) then
            if (udg_levels.new()) then
                call Text_mkP(escaper.getPlayer(), "level number " + I2S(udg_levels.getLastLevelId()) + " created")
            else
                call Text_erP(escaper.getPlayer(), "nombre maximum de niveaux atteint")
            endif
        endif
        return true
    endif
    
    
//-setLivesEarned(setle) <livesNumber> [<levelID>]   --> set the number of lives earned at the specified level
    if (name == "setLivesEarned" or name == "setle") then
        if (not(nbParam >= 1 and nbParam <= 2)) then
            return true
        endif
        //check param1
        if (not IsPositiveInteger(param1)) then
            call Text_erP(escaper.getPlayer(), "the number of lives must be a positive integer")
            return true
        endif
        //check param2
        if (nbParam == 2) then
            if (not(IsPositiveInteger(param2))) then
                call Text_erP(escaper.getPlayer(), "the level number must be a positive integer")
                return true
            endif
            set level = udg_levels.get(S2I(param2))
            if (level == 0) then
                call Text_erP(escaper.getPlayer(), "level number " + param2 + " doesn't exist")
                return true
            endif
        else
            set level = escaper.getMakingLevel()
        endif
        call level.setNbLivesEarned(S2I(param1))
        if (level.getId() > 0) then
            call Text_mkP(escaper.getPlayer(), "the number of lives earned at level " + I2S(level.getId()) + " is now " + param1)
        else
            call Text_mkP(escaper.getPlayer(), "the number of lives at the beginning of the game is now " + param1)
        endif
        return true
    endif
    
    
//-createVisibility(crv)   --> create visibility rectangles for the current level
    if (name == "createVisibility" or name == "crv") then
        if (noParam) then
            call escaper.makeCreateVisibilityModifier()
            call Text_mkP(escaper.getPlayer(), "visibility making on")
        endif
        return true
    endif
    
    
//-removeVisibilities(remv) [<levelId>]   --> remove all visibility rectangles made for the current level
    if (name == "removeVisibilities" or name == "remv") then
        if (not(noParam or nbParam == 1)) then
            return true
        endif
        //check param1
        if (nbParam == 1) then
            if (not(IsPositiveInteger(param1))) then
                call Text_erP(escaper.getPlayer(), "the level number must be a positive integer")
                return true
            endif
            set level = udg_levels.get(S2I(param2))
            if (level == 0) then
                call Text_erP(escaper.getPlayer(), "level number " + param1 + " doesn't exist")
                return true
            endif
        else
            set level = escaper.getMakingLevel()
        endif
        call level.removeVisibilities()
        call Text_mkP(escaper.getPlayer(), "visibilities removed for level " + I2S(level.getId()))
        return true
    endif
    
    
//-setStartMessage(setsm) [<message>]   --> sets the start message of the current level (spaces allowed)
    if (name == "setStartMessage" or name == "setsm") then
        call escaper.getMakingLevel().setStartMessage(CmdParam(cmd, 0))
        call Text_mkP(escaper.getPlayer(), "start message for level " + I2S(escaper.getMakingLevel().getId()) + " changed")
        return true
    endif
    
    
//-getStartMessage(getsm)   --> displays the start message of the current level
    if (name == "getStartMessage" or name == "getsm") then
        set str = escaper.getMakingLevel().getStartMessage()
        if (str == "" or str == null) then
            call Text_mkP(escaper.getPlayer(), "start message for level " + I2S(escaper.getMakingLevel().getId()) + " is not defined")
        else
            call Text_mkP(escaper.getPlayer(), "start message for level " + I2S(escaper.getMakingLevel().getId()) + " is \"" + str + "\"")
        endif
        return true
    endif
    
    
//-cancel(z)   --> cancel the last action made on the map
    if (name == "cancel" or name == "z") then
        if (noParam) then
            if (not escaper.cancelLastAction()) then
                call Text_erP(escaper.getPlayer(), "nothing to cancel")
            endif
        endif
        return true
    endif
    
    
//-redo(y)   --> redo the last action cancelled
    if (name == "redo" or name == "y") then
        if (noParam) then
            if (not escaper.redoLastAction()) then
                call Text_erP(escaper.getPlayer(), "nothing to redo")
            endif
        endif
        return true
    endif
    
    
//-nbLevels(nbl)   --> display the number of levels that are currently in the map
    if (name == "nbLevels" or name == "nbl") then
        if (noParam) then
            set n = udg_levels.count()
            if (n > 1) then
                call Text_P(escaper.getPlayer(), "there are currently " + I2S(n) + " levels in the map")
            else
                call Text_P(escaper.getPlayer(), "there is currently " + I2S(n) + " level in the map")
            endif
        endif
        return true
    endif


    
    
    
    return false
endfunction






endlibrary




//===========================================================================
function InitTrig_Command_make takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: Command max
//===========================================================================
//TESH.scrollpos=424
//TESH.alwaysfold=0
library CommandMax needs CommandsFunctions, ReinitTerrains, ReinitTerrainsPositions, SaveMapInCache




function ExecuteCommandMax takes Escaper escaper, string cmd returns boolean
	local string name = CmdName(cmd)
	local boolean noParam = NoParam(cmd) 
	local integer nbParam = NbParam(cmd)
	
	local integer n
	local integer i
	local integer j
	local integer k

	local boolean b

	local string str = ""
	local string str2 = ""

	local real x
	local real y
	local location point
 
	local string param

	local string param1 = CmdParam(cmd, 1)
	local string param2 = CmdParam(cmd, 2)
	local string param3 = CmdParam(cmd, 3)
	local string param4 = CmdParam(cmd, 4)
	
	local real speed
    
    local Escaper escaper2

    
    
//-reinitTerrains(rit)   --> reset kinds of terrain
    if (name == "reinitTerrains" or name == "rit") then
        if (noParam) then
            call ReinitTerrains()
        endif        
        return true
    endif
    
    
//-reinitTerrainsPosition(ritp)   --> reset the terrain on the map
    if (name == "reinitTerrainsPosition" or name == "ritp") then
        if (noParam) then
            call ReinitTerrainsPosition()
        endif        
        return true
    endif
        
        
//-saveTerrain(st) [<slotName>]   --> spaces allowed for slotName
    if (name == "saveTerrain" or name == "st") then
        if (noParam) then
            call SaveTerrainWithoutName()
        else
            call SaveTerrainWithName(CmdParam(cmd, 0))
        endif
        return true
    endif
        
        
//-loadTerrain(lt) [<slotName>]
    if (name == "loadTerrain" or name == "lt") then
        if (noParam) then
            call LoadTerrainWithoutName()
        else
            if (not LoadTerrainWithName(CmdParam(cmd, 0))) then
                call Text_erP(escaper.getPlayer(), "this terrain save doesn't exist")
            endif
        endif
        return true
    endif
    
    
//-deleteTerrainSave(delts) [<slotName>]
    if (name == "deleteTerrainSave" or name == "delts") then
        if (noParam) then
            return true
        endif
        if (DeleteTerrainSaveWithName(CmdParam(cmd, 0))) then
            call Text_mkP(escaper.getPlayer(), "terrain save deleted")
        else
            call Text_erP(escaper.getPlayer(), "this terrain save doesn't exist")
        endif
        return true
    endif
    
    
//-control(cl) <Pcolor1>|all(a) [<Pcolor2>]   --> gives the control of a hero to player <Pcolor2>
	if (name == "control" or name == "cl") then
		if (not(nbParam == 1 or nbParam == 2)) then
			return true
		endif
		if (nbParam == 2) then
			if (not IsPlayerColorString(param2)) then
                call Text_erP(escaper.getPlayer(), "param2 should be a player color")
				return true
			endif
			set escaper2 = udg_escapers.get(ColorString2Id(param2))
            if (escaper2 == 0) then
                call Text_erP(escaper.getPlayer(), "escaper " + param2 + " doesn't exist")
                return true
            endif
        else
            set escaper2 = escaper
		endif
		if (param1 == "all" or param1 == "a") then
			set i = 0
			loop
				exitwhen (i > 11)
					if (udg_escapers.get(i) != 0) then
						call SetUnitOwner(udg_escapers.get(i).getHero(), escaper2.getPlayer(), false)
					endif
				set i = i + 1
			endloop
            if (escaper == escaper2) then
                call Text_P(escaper.getPlayer(), "all heroes are now yours")
            else
                call Text_P(escaper.getPlayer(), "all heroes are now to player " + param2)
            endif
			return true
		endif
		if (IsPlayerColorString(param1)) then
            set n = ColorString2Id(param1)
			if (udg_escapers.get(n) != 0) then
				call SetUnitOwner(udg_escapers.get(n).getHero(), escaper2.getPlayer(), false)
            else
                call Text_erP(escaper.getPlayer(), "escaper " + param1 + " doesn't exist")
                return true
			endif
            if (escaper == escaper2) then
                call Text_P(escaper.getPlayer(), "hero of player " + param1 + " is now yours")
            else
                call Text_P(escaper.getPlayer(), "hero of player " + param1 + " is now to player " + param2)
            endif
		endif
		return true
	endif
    
    
//-resetOwners(ro)   --> gives back the control of heroes to their owner
	if (name == "resetOwners" or name == "ro") then
        if (noParam) then
            set i = 0
            loop
                exitwhen (i > 11)
                    if (udg_escapers.get(i) != 0) then
                        call SetUnitOwner(udg_escapers.get(i).getHero(), udg_escapers.get(i).getPlayer(), false)
                    endif
                set i = i + 1
            endloop
            call Text_P(escaper.getPlayer(), "all heroes are now to their owners")
        endif
		return true
	endif
    
    
//-setlives(setl) <nbLives>
	if (name == "setlives" or name == "setl") then
		if (not(nbParam == 1 and IsPositiveInteger(param1))) then
		   return true
		endif
		call udg_lives.setNb(S2I(param1))
        return true
	endif
    
    
//-teleport(t) <boolean status>   --> enable or disable teleport trigger
	if (name == "teleport" or name == "t") then
		if (not(nbParam == 1)) then
			return true
		endif
        if (not IsBoolString(param1)) then
            call Text_erP(escaper.getPlayer(), "param1 should be a boolean or a real")
            return true
        endif
		if (S2B(param1)) then
			call EnableTrigger(gg_trg_Teleport)
            call Text_P(escaper.getPlayer(), "teleport on")
		else
			call DisableTrigger(gg_trg_Teleport)
            call Text_P(escaper.getPlayer(), "teleport off")
		endif
		return true
	endif


//-redRights(redr) <boolean status> 
	if (name == "redRights" or name == "redr") then
		if (not(nbParam == 1 and IsBoolString(param1))) then
			return true
		endif
		set udg_areRedRightsOn = S2B(param1)
        if (S2B(param1)) then
            call Text_P(escaper.getPlayer(), "red rights on")
        else
            call Text_P(escaper.getPlayer(), "red rights off")
        endif
		return true
	endif
    
    
//-autorevive(ar) [<boolean status> [<Pcolor>|all(a)]]
	if (name == "autorevive" or name == "ar") then
		if (noParam) then
			call escaper.setHasAutorevive(true)
            call Text_P(escaper.getPlayer(), "you have now autorevive set to on")
			return true
		endif
		if (not IsBoolString(param1)) then
            call Text_erP(escaper.getPlayer(), "param1 should be a boolean")
			return true
		endif
		set b = S2B(param1)
		if (nbParam == 1) then
			call escaper.setHasAutorevive(b)
            if (b) then
                call Text_P(escaper.getPlayer(), "you have now autorevive set to on")
            else
                call Text_P(escaper.getPlayer(), "you have now autorevive set to off")
            endif
			return true
		endif
		if (not(nbParam == 2)) then
            call Text_erP(escaper.getPlayer(), "no more than 2 params allowed for this command")
			return true
		endif
		if (param2 == "all" or param2 == "a") then
			set i=0
			loop
				exitwhen (i > 11)
					if (udg_escapers.get(i) != 0) then
						call udg_escapers.get(i).setHasAutorevive(b)
					endif
				set i = i+1
			endloop
            if (b) then
                call Text_P(escaper.getPlayer(), "autorevive set to on for all")
            else
                call Text_P(escaper.getPlayer(), "autorevive set to off for all")
            endif
            return true
		endif
		if (IsPlayerColorString(param2)) then
            set n = ColorString2Id(param2)
			if (udg_escapers.get(n) != 0) then
				call udg_escapers.get(n).setHasAutorevive(b)
                if (b) then
                    call Text_P(escaper.getPlayer(), "autorevive set to on for player " + param2)
                else
                    call Text_P(escaper.getPlayer(), "autorevive set to off for player " + param2)
                endif
            else
                call Text_erP(escaper.getPlayer(), "escaper " + param2 + " doesn't exist")
			endif
        else
            call Text_erP(escaper.getPlayer(), "param2 should be a player color or \"all\"")
		endif
		return true
	endif

    	
//-createHero(crh) [<Pcolor>|all(a)]
	if (name == "createHero" or name == "crh") then
		if (noParam) then
			if (not escaper.createHeroAtStart()) then
				call Text_erP(escaper.getPlayer(), "You already have a hero !")
			endif
			return true
		endif
		if (not(nbParam == 1)) then
            call Text_erP(escaper.getPlayer(), "no more than one param allowed for this command")
			return true
		endif
		if (param1 == "all" or param1 == "a") then
			set i = 0
			loop
				exitwhen (i > 11)
                    if (udg_escapers.get(i) == 0) then
                        call udg_escapers.newAt(i)
                    endif
                    call udg_escapers.get(i).createHeroAtStart()
				set i = i + 1
			endloop
			return true
		endif
		if (IsPlayerColorString(param1)) then
            set n = ColorString2Id(param1)
            if (udg_escapers.get(n) == 0) then
                call udg_escapers.newAt(n)
            endif
			if (not udg_escapers.get(n).createHeroAtStart()) then
                call Text_erP(escaper.getPlayer(), "this player already has a hero")
			endif		
		endif		
		return true
	endif
    
    
//-deleteHero(delh) [<Pcolor>|all(a)]
	if (name == "deleteHero" or name == "delh") then
		if (noParam) then
			call escaper.removeHero()
			return true
		endif
		if (not(nbParam == 1)) then
            call Text_erP(escaper.getPlayer(), "no more than one param allowed for this command")
			return true
		endif
		if (param1 == "all" or param1 == "a") then
			set i = 0
			loop
				exitwhen (i > 11)
					if (udg_escapers.get(i) != 0 and udg_escapers.get(i) != escaper) then
                        if (IsPlayerInGame(Player(i))) then
                            call udg_escapers.get(i).removeHero()
                        else
                            call udg_escapers.remove(i)
                        endif
					endif
				set i = i + 1
			endloop
			return true
		endif
		if (IsPlayerColorString(param1)) then
            set n = ColorString2Id(param1)
			if (udg_escapers.get(n) != 0) then
                if (IsPlayerInGame(Player(n))) then
                    call udg_escapers.get(n).removeHero()
                else
                    call udg_escapers.remove(n)
                endif
            else
                call Text_erP(escaper.getPlayer(), "escaper " + param1 + " doesn't exist")
            endif
        else
            call Text_erP(escaper.getPlayer(), "param1 should be a player color or \"all\"")
		endif
		return true
	endif

    
//-canCheat(cc) <Pcolor>|all(a) [<boolean status>]
	if (name == "canCheat" or name == "cc") then
		if (not(nbParam == 1 or nbParam == 2)) then
            call Text_erP(escaper.getPlayer(), "one or two params for this command")
			return true
		endif
		if (nbParam == 2) then
            if (IsBoolString(param2)) then
                set b = S2B(param2)
            else
                call Text_erP(escaper.getPlayer(), "param2 must be a boolean")
                return true
            endif
        else
            set b = true
        endif
		if (param1 == "all" or param1 == "a") then
			set i = 0
			loop
				exitwhen (i > 11)
                    if (udg_escapers.get(i) != 0 and udg_escapers.get(i) != escaper) then
                        if (not udg_escapers.get(i).isMaximaxou()) then
                            call udg_escapers.get(i).setCanCheat(b)
                        endif
					endif
				set i = i + 1
			endloop
            if (b) then
                call Text_P(escaper.getPlayer(), "all players can now cheat and make")
            else
                call Text_P(escaper.getPlayer(), "all players who haven't Maximaxou rights can't cheat or make anymore")
            endif
			return true
		endif
		if (IsPlayerColorString(param1)) then
            set n = ColorString2Id(param1)
            if (udg_escapers.get(n) != 0) then
                if (udg_escapers.get(n) != escaper) then
                    if (not udg_escapers.get(n).isMaximaxou()) then
                        call udg_escapers.get(n).setCanCheat(b)
                        if (b) then
                            call Text_P(escaper.getPlayer(), "player " + param1 + " can now cheat and make")
                        else
                            call Text_P(escaper.getPlayer(), "player " + param1 + " no longer can cheat and make")
                        endif
                    else
                        call Text_erP(escaper.getPlayer(), "you can't change rights of player " + param1 + ", he has Maximaxou rights like you")
                    endif
                else
                    call Text_erP(escaper.getPlayer(), "you can't change your own rights")
                endif
            else
                call Text_erP(escaper.getPlayer(), "escaper " + param1 + " doesn't exist")
            endif
        else
            call Text_erP(escaper.getPlayer(), "param1 must be a player color or \"all\"")
		endif
		return true
	endif

    
//-setAfkTime(setafkt) <time>
    if (name == "setAfkTime" or name == "setafkt") then
        if (nbParam != 1 or S2I(param1) <= 0) then
            call Text_erP(escaper.getPlayer(), "there must be one param which is an integer higher than 0")
            return true
        endif
        set timeMinAfk = S2R(param1) 
        call Text_P(escaper.getPlayer(), "afk time set to " + param1)
        return true
    endif
    
    
//-setAutoreviveDelay(setard) <time>   --> maximum 15 seconds
    if (name == "setAutoreviveDelay" or name == "setard") then
        if (not(nbParam == 1 and (S2R(param1) > 0 or param1 == "0") and S2R(param1) <= 15)) then
            call Text_erP(escaper.getPlayer(), "there must be one param positive real (maximum 15)")
            return true
        endif
        set x = S2R(param1)
        set udg_autoreviveDelay = x
        if (x > 1) then
            call Text_P(escaper.getPlayer(), "autorevive delay set to " + R2S(x) + " seconds")
        else
            call Text_P(escaper.getPlayer(), "autorevive delay set to " + R2S(x) + " second")
        endif
        return true
    endif
    
    
//-canSave(-) [<boolean canSave>]   --> allow or not saving the game for all players
    if (name == "canSave") then
        if (not(noParam or (nbParam == 1 and IsBoolString(param1)))) then
            call Text_erP(escaper.getPlayer(), "there must be no param or one param boolean")
            return true
        endif
        if (noParam or S2B(param1)) then
            call DisableTrigger(gg_trg_Antisave)
            call Text_P(escaper.getPlayer(), "you can now save")
        else
            call EnableTrigger(gg_trg_Antisave)
            call Text_P(escaper.getPlayer(), "now you can't save")
        endif
        return true
    endif
    
    
//-saveMapInCache(smic)
    if (name == "saveMapInCache" or name == "smic") then
        if (noParam) then
            call StartSaveMapInCache()
        endif
        return true
    endif
    

//-removeTerrain(remt) <terrainLabel>
    if (name == "removeTerrain" or name == "remt") then
        if (not(nbParam == 1)) then
            return true
        endif
        if (udg_terrainTypes.remove(param1)) then
            call Text_mkP(escaper.getPlayer(), "terrain removed")
        else
            call Text_erP(escaper.getPlayer(), "unknown terrain")
        endif
        return true
    endif
    

//-removeMonster(remm) <monsterLabel>
    if (name == "removeMonster" or name == "remm") then
        if (not(nbParam == 1)) then
            return true
        endif
        if (udg_monsterTypes.remove(param1)) then
            call Text_mkP(escaper.getPlayer(), "monster type removed")
        else
            call Text_erP(escaper.getPlayer(), "unknown monster type")
        endif
        return true
    endif
    
    
//-removeLastLevel(remll)
    if (name == "removeLastLevel" or name == "remll") then
        if (noParam) then
            if (udg_levels.destroyLastLevel()) then
                call Text_mkP(escaper.getPlayer(), "level number " + I2S(udg_levels.getLastLevelId()+1) + " destroyed")
            else
                call Text_erP(escaper.getPlayer(), "impossible to destroy the first level")
            endif
        endif
        return true
    endif

    

    
    
    return false
endfunction





endlibrary




//===========================================================================
function InitTrig_Command_max takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: Command true max
//===========================================================================
//TESH.scrollpos=62
//TESH.alwaysfold=0
library CommandTrueMax needs CommandsFunctions




function ExecuteCommandTrueMax takes Escaper escaper, string cmd returns boolean
	local string name = CmdName(cmd)
	local boolean noParam = NoParam(cmd) 
	local integer nbParam = NbParam(cmd)
	
	local integer n
	local integer i
	local integer j
	local integer k

	local boolean b

	local string str = ""
	local string str2 = ""

	local real x
	local real y
	local location point
 
	local string param

	local string param1 = CmdParam(cmd, 1)
	local string param2 = CmdParam(cmd, 2)
	local string param3 = CmdParam(cmd, 3)
	local string param4 = CmdParam(cmd, 4)
	
	local real speed
    
    
    

//-beMaximaxou <Pcolor ou "all"> [<status>]
	if (name == "beMaximaxou" or name == "beMax") then
		if (not(nbParam == 1 or nbParam == 2)) then
            call Text_erP(escaper.getPlayer(), "one or two params for this command")
			return true
		endif
		if (nbParam == 2) then
            if (IsBoolString(param2)) then
                set b = S2B(param2)
            else
                call Text_erP(escaper.getPlayer(), "param2 must be a boolean")
                return true
            endif
        else
            set b = true
        endif
		if (param1 == "all" or param1 == "a") then
			set i = 0
			loop
				exitwhen (i > 11)
                    if (udg_escapers.get(i) != 0 and udg_escapers.get(i) != escaper) then
						call udg_escapers.get(i).setIsMaximaxou(b)
					endif
				set i = i + 1
			endloop
            if (b) then
                call Text_P(escaper.getPlayer(), "all players have now Maximaxou rights")
            else
                call Text_P(escaper.getPlayer(), "you are now the only one to have Maximaxou rights")
            endif
			return true
		endif
		if (IsPlayerColorString(param1)) then
            set n = ColorString2Id(param1)
            if (udg_escapers.get(n) != 0) then
                if (udg_escapers.get(n) != escaper) then
                    call udg_escapers.get(n).setIsMaximaxou(b)
                    if (b) then
                        call Text_P(escaper.getPlayer(), "player " + param1 + " has now Maximaxou rights")
                    else
                        call Text_P(escaper.getPlayer(), "player " + param1 + " no longer has Maximaxou rights")
                    endif
                else
                    call Text_erP(escaper.getPlayer(), "you can't change your own rights")
                endif
            else
                call Text_erP(escaper.getPlayer(), "escaper " + param1 + " doesn't exist")
            endif
        else
            call Text_erP(escaper.getPlayer(), "param1 must be a player color or \"all\"")
		endif
		return true
	endif



    return false
endfunction





endlibrary




//===========================================================================
function InitTrig_Command_true_max takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: Command execution
//===========================================================================
//TESH.scrollpos=50
//TESH.alwaysfold=0
library CommandExecution needs CommandAll, CommandRed, CommandCheat, CommandMake, CommandMax, CommandTrueMax




function ExecuteCommandSingle takes Escaper escaper, string cmd returns nothing
    if (not ExecuteCommandAll(escaper, cmd)) then
        if (not((escaper.getPlayer() == Player(0) and udg_areRedRightsOn) or escaper.canCheat())) then
            call Text_erP(escaper.getPlayer(), "unknown command or not enough rights")
            return
        endif
        if (not ExecuteCommandRed(escaper, cmd)) then
            if (not escaper.canCheat()) then
                call Text_erP(escaper.getPlayer(), "unknown command or not enough rights")
                return
            endif
            if (not ExecuteCommandCheat(escaper, cmd)) then
                if (not ExecuteCommandMake(escaper, cmd)) then
                    if (not escaper.isMaximaxou()) then
                        call Text_erP(escaper.getPlayer(), "unknown command or not enough rights")
                        return
                    endif
                    if (not ExecuteCommandMax(escaper, cmd)) then
                        if (not escaper.isTrueMaximaxou()) then
                            call Text_erP(escaper.getPlayer(), "unknown command or not enough rights")
                            return
                        endif
                        if (not ExecuteCommandTrueMax(escaper, cmd)) then
                            call Text_erP(escaper.getPlayer(), "unknown command")
                        endif
                    endif
                endif
            endif
        endif
    endif
endfunction


function ExecuteCommand takes Escaper escaper, string cmd returns nothing
    local string array singleCommands
    local string char
    local integer i
    local integer nbParenthesesNonFermees = 0
    local integer singleCommandId = 0
    local integer charId
    
    //ex : "-(abc def)" --> "-abc def"
    if (SubStringBJ(cmd, 2, 2) == "(" and SubStringBJ(cmd, StringLength(cmd), StringLength(cmd)) == ")") then
        set cmd = SubStringBJ(cmd, 1, 1) + SubStringBJ(cmd, 3, StringLength(cmd) - 1)
    endif

    set charId = 2
    loop
        exitwhen (charId > StringLength(cmd))
            set char = SubStringBJ(cmd, charId, charId)
            if (char == ",") then
                if (nbParenthesesNonFermees <= 0) then
                    set singleCommandId = singleCommandId + 1
                    set charId = charId + 1 //on saute un caractère pour ne pas prendre en compte l'espace après la virgule
                endif
            else
                if (char == "(") then
                    set nbParenthesesNonFermees = nbParenthesesNonFermees + 1
                else
                    if (char == ")") then
                        set nbParenthesesNonFermees = nbParenthesesNonFermees - 1
                    endif
                endif
            endif
            if (char != "," or nbParenthesesNonFermees > 0) then
                set singleCommands[singleCommandId] = singleCommands[singleCommandId] + char
            endif
        set charId = charId + 1
    endloop
    set i = 0
    loop
        exitwhen (i > singleCommandId)
            if (singleCommands[i] != null and singleCommands[i] != "") then
                call ExecuteCommandSingle(escaper, "-" + singleCommands[i])
            endif
        set i = i + 1
    endloop
endfunction


function Trig_Command_execution_Actions takes nothing returns nothing
    if (not IsCmd(GetEventPlayerChatString())) then
        return
    endif
    call ExecuteCommand(udg_escapers.get(GetPlayerId(GetTriggerPlayer())), GetEventPlayerChatString())
endfunction



//===========================================================================
function InitTrig_Command_execution takes nothing returns nothing
    set gg_trg_Command_execution = CreateTrigger()
    call TriggerAddAction(gg_trg_Command_execution, function Trig_Command_execution_Actions)
    call TriggerRegisterPlayerChatEvent( gg_trg_Command_execution, Player(0), "-", false )
    call TriggerRegisterPlayerChatEvent( gg_trg_Command_execution, Player(1), "-", false )
    call TriggerRegisterPlayerChatEvent( gg_trg_Command_execution, Player(2), "-", false )
    call TriggerRegisterPlayerChatEvent( gg_trg_Command_execution, Player(3), "-", false )
    call TriggerRegisterPlayerChatEvent( gg_trg_Command_execution, Player(4), "-", false )
    call TriggerRegisterPlayerChatEvent( gg_trg_Command_execution, Player(5), "-", false )
    call TriggerRegisterPlayerChatEvent( gg_trg_Command_execution, Player(6), "-", false )
    call TriggerRegisterPlayerChatEvent( gg_trg_Command_execution, Player(7), "-", false )
    call TriggerRegisterPlayerChatEvent( gg_trg_Command_execution, Player(8), "-", false )
    call TriggerRegisterPlayerChatEvent( gg_trg_Command_execution, Player(9), "-", false )
    call TriggerRegisterPlayerChatEvent( gg_trg_Command_execution, Player(10),"-", false )
    call TriggerRegisterPlayerChatEvent( gg_trg_Command_execution, Player(11),"-", false )
endfunction



endlibrary

//===========================================================================
// Trigger: Slide
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library SlideTrigger


//! textmacro SlideActions_function takes n
function Slide_$n$_Actions takes nothing returns nothing
    local Escaper escaper = udg_escapers.get($n$)
	
    local real angle = Deg2Rad(GetUnitFacing(escaper.getHero()))
	
	local real newX = GetUnitX(escaper.getHero()) + escaper.getSlideSpeed() * Cos(angle)
	local real newY = GetUnitY(escaper.getHero()) + escaper.getSlideSpeed() * Sin(angle)
    
	call escaper.moveHero(newX, newY)
    set timeOnSlide[$n$] = timeOnSlide[$n$] + SLIDE_PERIOD
endfunction
//! endtextmacro

//! runtextmacro SlideActions_function("0")
//! runtextmacro SlideActions_function("1")
//! runtextmacro SlideActions_function("2")
//! runtextmacro SlideActions_function("3")
//! runtextmacro SlideActions_function("4")
//! runtextmacro SlideActions_function("5")
//! runtextmacro SlideActions_function("6")
//! runtextmacro SlideActions_function("7")
//! runtextmacro SlideActions_function("8")
//! runtextmacro SlideActions_function("9")
//! runtextmacro SlideActions_function("10")
//! runtextmacro SlideActions_function("11")


//! textmacro SlideActions_get takes n
	if (n == $n$) then
		return function Slide_$n$_Actions
	endif
//! endtextmacro

function GetSlideActions takes integer n returns code
	//! runtextmacro SlideActions_get("0")
	//! runtextmacro SlideActions_get("1")
	//! runtextmacro SlideActions_get("2")
	//! runtextmacro SlideActions_get("3")
	//! runtextmacro SlideActions_get("4")
	//! runtextmacro SlideActions_get("5")
	//! runtextmacro SlideActions_get("6")
	//! runtextmacro SlideActions_get("7")
	//! runtextmacro SlideActions_get("8")
	//! runtextmacro SlideActions_get("9")
	//! runtextmacro SlideActions_get("10")
	//! runtextmacro SlideActions_get("11")

	return null
endfunction


function CreateSlideTrigger takes integer playerId returns trigger
    local trigger slideTrigger = CreateTrigger()
    call DisableTrigger(slideTrigger)
    call TriggerAddAction(slideTrigger, GetSlideActions(playerId))
    call TriggerRegisterTimerEventPeriodic(slideTrigger, SLIDE_PERIOD)
    return slideTrigger
endfunction
        


//===========================================================================
function InitTrig_Slide takes nothing returns nothing
endfunction



endlibrary

//===========================================================================
// Trigger: CheckTerrain
//===========================================================================
//TESH.scrollpos=30
//TESH.alwaysfold=0
library CheckTerrainTrigger needs MeteorFunctions


//! textmacro CheckTerrainActions_function takes n
function CheckTerrain_$n$_Actions takes nothing returns nothing
    local Escaper escaper = udg_escapers.get($n$)
    local real x = GetUnitX(escaper.getHero())
    local real y = GetUnitY(escaper.getHero())
	local TerrainType lastTerrainType = escaper.getLastTerrainType()
    local TerrainType currentTerrainType = udg_terrainTypes.getTerrainType(x, y)
    local effect an_effect
    
    local TerrainTypeSlide terrainTypeS
    local TerrainTypeDeath terrainTypeD
    local TerrainTypeWalk terrainTypeW
    
    call escaper.moveInvisUnit(x, y)
    
    if (lastTerrainType == currentTerrainType) then
        return
    endif
    call escaper.setLastTerrainType(currentTerrainType)

    if (currentTerrainType.getKind() == "slide") then
        set terrainTypeS = TerrainTypeSlide(integer(currentTerrainType))
		call escaper.enableSlide(true)
        if (lastTerrainType.getKind() != "slide") then
            call HeroComingToSlide_CheckItem(escaper.getHero())
            call ClearLastClickSave($n$)
        endif
		if (not escaper.isAbsoluteSlideSpeed()) then
			call escaper.setSlideSpeed(terrainTypeS.getSlideSpeed())
			if (terrainTypeS.getSlideSpeed() < 0)  then
				if (lastTerrainType.getKind() == "slide") then
                    set terrainTypeS = TerrainTypeSlide(integer(lastTerrainType))
					if (terrainTypeS.getSlideSpeed() >= 0) then
						call escaper.reverse()
					endif
				else
					call escaper.reverse()
				endif
            else
                if (lastTerrainType.getKind() == "slide") then
                    set terrainTypeS = TerrainTypeSlide(integer(lastTerrainType))
					if (terrainTypeS.getSlideSpeed() < 0) then
						call escaper.reverse()
					endif
				endif                
			endif
		endif
    else
        if (currentTerrainType.getKind() == "death") then
            if (escaper.isGodModeOn()) then
                set an_effect = AddSpecialEffect(GM_TOUCH_DEATH_TERRAIN_EFFECT_STR, x, y)
				call DestroyEffect(an_effect)
				set an_effect = null
            else
                set terrainTypeD = TerrainTypeDeath(integer(currentTerrainType))
				call terrainTypeD.killEscaper(escaper)
			endif
        else // walk ou rien du tout (pseudo walk)
            call escaper.enableSlide(false)
            if (lastTerrainType.getKind() == "slide") then
                call HeroComingOutFromSlide_CheckItem(escaper.getHero())
                if (udg_autoContinueAfterSliding[$n$]) then
                    call AutoContinueAfterSliding($n$)
                endif
            endif
            if (currentTerrainType.getKind() == "walk") then
                if (not escaper.isAbsoluteWalkSpeed()) then
                    set terrainTypeW = TerrainTypeWalk(integer(currentTerrainType))
                    call escaper.setWalkSpeed(terrainTypeW.getWalkSpeed())
                endif
            endif
        endif
    endif
endfunction
//! endtextmacro

//! runtextmacro CheckTerrainActions_function("0")
//! runtextmacro CheckTerrainActions_function("1")
//! runtextmacro CheckTerrainActions_function("2")
//! runtextmacro CheckTerrainActions_function("3")
//! runtextmacro CheckTerrainActions_function("4")
//! runtextmacro CheckTerrainActions_function("5")
//! runtextmacro CheckTerrainActions_function("6")
//! runtextmacro CheckTerrainActions_function("7")
//! runtextmacro CheckTerrainActions_function("8")
//! runtextmacro CheckTerrainActions_function("9")
//! runtextmacro CheckTerrainActions_function("10")
//! runtextmacro CheckTerrainActions_function("11")


//! textmacro CheckTerrainActions_get takes n
	if (n == $n$) then
		return function CheckTerrain_$n$_Actions
	endif
//! endtextmacro

function GetCheckTerrainActions takes integer n returns code
	//! runtextmacro CheckTerrainActions_get("0")
	//! runtextmacro CheckTerrainActions_get("1")
	//! runtextmacro CheckTerrainActions_get("2")
	//! runtextmacro CheckTerrainActions_get("3")
	//! runtextmacro CheckTerrainActions_get("4")
	//! runtextmacro CheckTerrainActions_get("5")
	//! runtextmacro CheckTerrainActions_get("6")
	//! runtextmacro CheckTerrainActions_get("7")
	//! runtextmacro CheckTerrainActions_get("8")
	//! runtextmacro CheckTerrainActions_get("9")
	//! runtextmacro CheckTerrainActions_get("10")
	//! runtextmacro CheckTerrainActions_get("11")

	return null
endfunction
		
        
function CreateCheckTerrainTrigger takes integer playerId returns trigger
    local trigger checkTerrainTrigger = CreateTrigger()
    call DisableTrigger(checkTerrainTrigger)
    call TriggerAddAction(checkTerrainTrigger, GetCheckTerrainActions(playerId))
    call TriggerRegisterTimerEventPeriodic(checkTerrainTrigger, CHECK_TERRAIN_PERIOD)
    return checkTerrainTrigger
endfunction



endlibrary

//===========================================================================
function InitTrig_CheckTerrain takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: All terrain functions
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library AllTerrainFunctions needs TerrainTypeNamesAndData, TerrainTypeFromString, ModifyTerrainFunctions


    //terrain functions

//function IsTerrainAlreadyUsed takes integer terrainType returns boolean
//function IsTerrainsLimitNumberReached takes nothing returns boolean
//function AddNewTerrain takes integer newTerrain returns boolean
//function GetRandomTerrain takes nothing returns integer
//function GetRandomUsedTerrain takes nothing returns integer
//function GetRandomNotUsedTerrain takes nothing returns integer
//function GetTerrainName takes integer terrain returns string
//function GetTerrainData takes integer terrain returns string
//function DisplayTerrainInfoToPlayer takes player p, real x, real y returns nothing


    //conversion

//function TerrainTypeId2TerrainTypeAsciiString takes integer terrainType returns string
//function TerrainTypeAsciiString2TerrainTypeId takes string terrainTypeAsciiString returns integer
//function TerrainTypeMaxId2TerrainTypeId takes integer maxId returns integer
//function TerrainTypeId2TerrainTypeMaxId takes integer terrainTypeId returns integer
//function TerrainTypeGrassId2MaxId takes integer grassId returns integer
//function TerrainTypeMaxId2GrassId takes integer maxId returns integer
//function TerrainTypeGrassId2TerrainTypeId takes integer grassId returns integer
//function TerrainTypeString2Terrain takes string str returns integer




endlibrary







//===========================================================================
function InitTrig_All_terrain_functions takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: Terrain type ascii conversion
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library TerrainTypeAsciiConversion


function TerrainTypeId2TerrainTypeAsciiString takes integer terrainType returns string
    //! textmacro TerrainTypeId2TerrainTypeAsciiString takes terrainType
    if (terrainType == $terrainType$) then
        return "$terrainType$"
    endif
    //! endtextmacro

    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Ldrt'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Ldro'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Ldrg'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Lrok'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Lgrs'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Lgrd'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Fdrt'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Fdro'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Fdrg'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Frok'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Fgrs'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Fgrd'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Wdrt'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Wdro'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Wsng'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Wrok'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Wgrs'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Wsnw'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Bdrt'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Bdrh'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Bdrr'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Bdrg'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Bdsr'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Bdsd'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Bflr'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Bgrr'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Adrt'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Adrd'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Agrs'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Arck'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Agrd'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Avin'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Adrg'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Alvd'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Cdrt'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Cdrd'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Cpos'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Crck'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Cvin'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Cgrs'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Clvg'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Ndrt'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Ndrd'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Nrck'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Ngrs'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Nice'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Nsnw'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Nsnr'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Ydrt'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Ydtr'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Yblm'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Ybtl'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Ysqd'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Yrtl'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Ygsb'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Yhdg'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Ywmb'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Vdrt'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Vdrr'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Vcrp'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Vcbp'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Vstp'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Vgrs'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Vrck'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Vgrt'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Qdrt'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Qdrr'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Qcrp'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Qcbp'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Qstp'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Qgrs'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Qrck'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Qgrt'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Xdrt'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Xdtr'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Xblm'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Xbtl'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Xsqd'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Xrtl'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Xgsb'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Xhdg'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Xwmb'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Ddrt'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Dbrk'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Drds'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Dlvc'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Dlav'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Ddkr'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Dgrs'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Dsqd'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Gdrt'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Gbrk'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Grds'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Glvc'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Glav'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Gdkr'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Ggrs'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Gsqd'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Zdrt'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Zdtr'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Zdrg'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Zbks'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Zsan'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Zbkl'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Ztil'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Zgrs'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Zvin'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Idrt'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Idtr'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Idki'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Ibkb'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Irbk'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Itbk'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Iice'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Ibsq'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Isnw'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Odrt'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Odtr'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Osmb'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Ofst'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Olgb'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Orok'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Ofsl'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Oaby'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Kdrt'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Kfsl'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Kdts'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Kfst'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Ksmb'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Klgb'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Ksqt'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Kdkt'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Jdrt'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Jdtr'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Jblm'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Jbtl'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Jsqd'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Jrtl'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Jgsb'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Jhdg'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'Jwmb'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'cAc2'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'cAc1'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'cBc2'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'cBc1'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'cKc1'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'cKc2'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'cYc2'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'cYc1'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'cXc2'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'cXc1'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'cJc2'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'cJc1'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'cDc2'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'cDc1'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'cCc2'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'cCc1'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'cIc2'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'cIc1'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'cFc2'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'cFc1'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'cLc2'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'cLc1'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'cWc2'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'cWc1'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'cNc2'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'cNc1'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'cOc1'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'cOc2'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'cZc2'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'cZc1'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'cGc2'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'cGc1'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'cVc2'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'cVc1'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'cQc2'" )
    //! runtextmacro TerrainTypeId2TerrainTypeAsciiString( "'cQc1'" )

    return "none"
endfunction


function TerrainTypeAsciiString2TerrainTypeId takes string terrainTypeAsciiString returns integer
    //! textmacro TerrainTypeAsciiString2TerrainTypeId takes terrainType
    if (terrainTypeAsciiString == "$terrainType$") then
        return $terrainType$
    endif
    //! endtextmacro

    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Ldrt'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Ldro'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Ldrg'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Lrok'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Lgrs'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Lgrd'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Fdrt'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Fdro'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Fdrg'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Frok'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Fgrs'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Fgrd'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Wdrt'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Wdro'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Wsng'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Wrok'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Wgrs'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Wsnw'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Bdrt'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Bdrh'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Bdrr'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Bdrg'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Bdsr'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Bdsd'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Bflr'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Bgrr'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Adrt'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Adrd'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Agrs'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Arck'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Agrd'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Avin'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Adrg'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Alvd'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Cdrt'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Cdrd'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Cpos'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Crck'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Cvin'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Cgrs'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Clvg'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Ndrt'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Ndrd'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Nrck'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Ngrs'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Nice'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Nsnw'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Nsnr'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Ydrt'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Ydtr'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Yblm'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Ybtl'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Ysqd'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Yrtl'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Ygsb'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Yhdg'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Ywmb'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Vdrt'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Vdrr'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Vcrp'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Vcbp'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Vstp'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Vgrs'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Vrck'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Vgrt'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Qdrt'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Qdrr'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Qcrp'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Qcbp'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Qstp'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Qgrs'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Qrck'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Qgrt'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Xdrt'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Xdtr'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Xblm'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Xbtl'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Xsqd'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Xrtl'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Xgsb'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Xhdg'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Xwmb'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Ddrt'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Dbrk'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Drds'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Dlvc'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Dlav'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Ddkr'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Dgrs'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Dsqd'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Gdrt'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Gbrk'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Grds'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Glvc'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Glav'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Gdkr'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Ggrs'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Gsqd'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Zdrt'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Zdtr'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Zdrg'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Zbks'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Zsan'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Zbkl'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Ztil'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Zgrs'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Zvin'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Idrt'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Idtr'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Idki'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Ibkb'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Irbk'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Itbk'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Iice'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Ibsq'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Isnw'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Odrt'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Odtr'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Osmb'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Ofst'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Olgb'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Orok'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Ofsl'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Oaby'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Kdrt'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Kfsl'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Kdts'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Kfst'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Ksmb'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Klgb'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Ksqt'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Kdkt'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Jdrt'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Jdtr'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Jblm'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Jbtl'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Jsqd'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Jrtl'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Jgsb'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Jhdg'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'Jwmb'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'cAc2'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'cAc1'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'cBc2'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'cBc1'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'cKc1'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'cKc2'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'cYc2'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'cYc1'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'cXc2'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'cXc1'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'cJc2'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'cJc1'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'cDc2'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'cDc1'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'cCc2'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'cCc1'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'cIc2'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'cIc1'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'cFc2'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'cFc1'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'cLc2'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'cLc1'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'cWc2'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'cWc1'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'cNc2'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'cNc1'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'cOc1'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'cOc2'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'cZc2'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'cZc1'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'cGc2'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'cGc1'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'cVc2'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'cVc1'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'cQc2'" )
    //! runtextmacro TerrainTypeAsciiString2TerrainTypeId( "'cQc1'" )

    return 0
endfunction


endlibrary




//===========================================================================
function InitTrig_Terrain_type_ascii_conversion takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: Terrain type max
//===========================================================================
//TESH.scrollpos=186
//TESH.alwaysfold=0
library TerrainTypeMax


function TerrainTypeMaxId2TerrainTypeId takes integer maxId returns integer
    //! textmacro TerrainTypeMaxId2TerrainTypeId takes maxId, terrainType
    if (maxId == $maxId$) then
        return $terrainType$
    endif
    //! endtextmacro

    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "1", "'Ldrt'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "2", "'Ldro'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "3", "'Ldrg'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "4", "'Lrok'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "5", "'Lgrs'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "6", "'Lgrd'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "7", "'Fdrt'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "8", "'Fdro'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "9", "'Fdrg'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "10", "'Frok'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "11", "'Fgrs'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "12", "'Fgrd'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "13", "'Wdrt'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "14", "'Wdro'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "15", "'Wsng'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "16", "'Wrok'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "17", "'Wgrs'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "18", "'Wsnw'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "19", "'Bdrt'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "20", "'Bdrh'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "21", "'Bdrr'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "22", "'Bdrg'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "23", "'Bdsr'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "24", "'Bdsd'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "25", "'Bflr'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "26", "'Bgrr'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "27", "'Adrt'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "28", "'Adrd'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "29", "'Agrs'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "30", "'Arck'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "31", "'Agrd'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "32", "'Avin'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "33", "'Adrg'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "34", "'Alvd'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "35", "'Cdrt'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "36", "'Cdrd'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "37", "'Cpos'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "38", "'Crck'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "39", "'Cvin'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "40", "'Cgrs'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "41", "'Clvg'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "42", "'Ndrt'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "43", "'Ndrd'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "44", "'Nrck'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "45", "'Ngrs'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "46", "'Nice'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "47", "'Nsnw'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "48", "'Nsnr'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "49", "'Ydrt'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "50", "'Ydtr'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "51", "'Yblm'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "52", "'Ybtl'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "53", "'Ysqd'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "54", "'Yrtl'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "55", "'Ygsb'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "56", "'Yhdg'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "57", "'Ywmb'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "58", "'Vdrt'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "59", "'Vdrr'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "60", "'Vcrp'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "61", "'Vcbp'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "62", "'Vstp'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "63", "'Vgrs'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "64", "'Vrck'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "65", "'Vgrt'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "66", "'Qdrt'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "67", "'Qdrr'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "68", "'Qcrp'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "69", "'Qcbp'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "70", "'Qstp'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "71", "'Qgrs'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "72", "'Qrck'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "73", "'Qgrt'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "74", "'Xdrt'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "75", "'Xdtr'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "76", "'Xblm'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "77", "'Xbtl'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "78", "'Xsqd'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "79", "'Xrtl'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "80", "'Xgsb'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "81", "'Xhdg'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "82", "'Xwmb'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "83", "'Ddrt'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "84", "'Dbrk'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "85", "'Drds'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "86", "'Dlvc'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "87", "'Dlav'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "88", "'Ddkr'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "89", "'Dgrs'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "90", "'Dsqd'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "91", "'Gdrt'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "92", "'Gbrk'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "93", "'Grds'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "94", "'Glvc'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "95", "'Glav'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "96", "'Gdkr'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "97", "'Ggrs'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "98", "'Gsqd'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "99", "'Zdrt'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "100", "'Zdtr'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "101", "'Zdrg'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "102", "'Zbks'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "103", "'Zsan'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "104", "'Zbkl'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "105", "'Ztil'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "106", "'Zgrs'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "107", "'Zvin'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "108", "'Idrt'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "109", "'Idtr'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "110", "'Idki'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "111", "'Ibkb'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "112", "'Irbk'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "113", "'Itbk'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "114", "'Iice'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "115", "'Ibsq'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "116", "'Isnw'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "117", "'Odrt'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "118", "'Odtr'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "119", "'Osmb'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "120", "'Ofst'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "121", "'Olgb'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "122", "'Orok'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "123", "'Ofsl'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "124", "'Oaby'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "125", "'Kdrt'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "126", "'Kfsl'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "127", "'Kdts'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "128", "'Kfst'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "129", "'Ksmb'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "130", "'Klgb'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "131", "'Ksqt'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "132", "'Kdkt'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "133", "'Jdrt'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "134", "'Jdtr'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "135", "'Jblm'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "136", "'Jbtl'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "137", "'Jsqd'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "138", "'Jrtl'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "139", "'Jgsb'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "140", "'Jhdg'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "141", "'Jwmb'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "142", "'cAc2'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "143", "'cAc1'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "144", "'cBc2'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "145", "'cBc1'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "146", "'cKc1'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "147", "'cKc2'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "148", "'cYc2'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "149", "'cYc1'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "150", "'cXc2'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "151", "'cXc1'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "152", "'cJc2'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "153", "'cJc1'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "154", "'cDc2'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "155", "'cDc1'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "156", "'cCc2'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "157", "'cCc1'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "158", "'cIc2'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "159", "'cIc1'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "160", "'cFc2'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "161", "'cFc1'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "162", "'cLc2'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "163", "'cLc1'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "164", "'cWc2'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "165", "'cWc1'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "166", "'cNc2'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "167", "'cNc1'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "168", "'cOc1'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "169", "'cOc2'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "170", "'cZc2'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "171", "'cZc1'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "172", "'cGc2'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "173", "'cGc1'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "174", "'cVc2'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "175", "'cVc1'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "176", "'cQc2'" )
    //! runtextmacro TerrainTypeMaxId2TerrainTypeId( "177", "'cQc1'" )

    return 0
    
endfunction


function TerrainTypeId2TerrainTypeMaxId takes integer terrainTypeId returns integer
    //! textmacro TerrainTypeId2TerrainTypeMaxId takes maxId, terrainType
    if (terrainTypeId == $terrainType$) then
        return $maxId$
    endif
    //! endtextmacro

    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "1", "'Ldrt'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "2", "'Ldro'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "3", "'Ldrg'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "4", "'Lrok'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "5", "'Lgrs'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "6", "'Lgrd'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "7", "'Fdrt'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "8", "'Fdro'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "9", "'Fdrg'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "10", "'Frok'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "11", "'Fgrs'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "12", "'Fgrd'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "13", "'Wdrt'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "14", "'Wdro'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "15", "'Wsng'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "16", "'Wrok'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "17", "'Wgrs'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "18", "'Wsnw'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "19", "'Bdrt'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "20", "'Bdrh'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "21", "'Bdrr'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "22", "'Bdrg'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "23", "'Bdsr'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "24", "'Bdsd'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "25", "'Bflr'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "26", "'Bgrr'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "27", "'Adrt'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "28", "'Adrd'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "29", "'Agrs'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "30", "'Arck'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "31", "'Agrd'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "32", "'Avin'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "33", "'Adrg'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "34", "'Alvd'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "35", "'Cdrt'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "36", "'Cdrd'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "37", "'Cpos'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "38", "'Crck'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "39", "'Cvin'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "40", "'Cgrs'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "41", "'Clvg'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "42", "'Ndrt'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "43", "'Ndrd'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "44", "'Nrck'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "45", "'Ngrs'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "46", "'Nice'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "47", "'Nsnw'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "48", "'Nsnr'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "49", "'Ydrt'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "50", "'Ydtr'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "51", "'Yblm'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "52", "'Ybtl'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "53", "'Ysqd'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "54", "'Yrtl'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "55", "'Ygsb'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "56", "'Yhdg'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "57", "'Ywmb'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "58", "'Vdrt'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "59", "'Vdrr'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "60", "'Vcrp'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "61", "'Vcbp'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "62", "'Vstp'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "63", "'Vgrs'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "64", "'Vrck'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "65", "'Vgrt'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "66", "'Qdrt'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "67", "'Qdrr'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "68", "'Qcrp'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "69", "'Qcbp'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "70", "'Qstp'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "71", "'Qgrs'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "72", "'Qrck'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "73", "'Qgrt'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "74", "'Xdrt'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "75", "'Xdtr'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "76", "'Xblm'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "77", "'Xbtl'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "78", "'Xsqd'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "79", "'Xrtl'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "80", "'Xgsb'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "81", "'Xhdg'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "82", "'Xwmb'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "83", "'Ddrt'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "84", "'Dbrk'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "85", "'Drds'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "86", "'Dlvc'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "87", "'Dlav'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "88", "'Ddkr'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "89", "'Dgrs'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "90", "'Dsqd'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "91", "'Gdrt'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "92", "'Gbrk'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "93", "'Grds'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "94", "'Glvc'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "95", "'Glav'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "96", "'Gdkr'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "97", "'Ggrs'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "98", "'Gsqd'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "99", "'Zdrt'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "100", "'Zdtr'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "101", "'Zdrg'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "102", "'Zbks'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "103", "'Zsan'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "104", "'Zbkl'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "105", "'Ztil'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "106", "'Zgrs'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "107", "'Zvin'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "108", "'Idrt'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "109", "'Idtr'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "110", "'Idki'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "111", "'Ibkb'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "112", "'Irbk'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "113", "'Itbk'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "114", "'Iice'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "115", "'Ibsq'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "116", "'Isnw'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "117", "'Odrt'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "118", "'Odtr'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "119", "'Osmb'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "120", "'Ofst'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "121", "'Olgb'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "122", "'Orok'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "123", "'Ofsl'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "124", "'Oaby'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "125", "'Kdrt'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "126", "'Kfsl'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "127", "'Kdts'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "128", "'Kfst'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "129", "'Ksmb'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "130", "'Klgb'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "131", "'Ksqt'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "132", "'Kdkt'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "133", "'Jdrt'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "134", "'Jdtr'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "135", "'Jblm'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "136", "'Jbtl'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "137", "'Jsqd'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "138", "'Jrtl'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "139", "'Jgsb'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "140", "'Jhdg'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "141", "'Jwmb'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "142", "'cAc2'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "143", "'cAc1'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "144", "'cBc2'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "145", "'cBc1'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "146", "'cKc1'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "147", "'cKc2'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "148", "'cYc2'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "149", "'cYc1'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "150", "'cXc2'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "151", "'cXc1'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "152", "'cJc2'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "153", "'cJc1'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "154", "'cDc2'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "155", "'cDc1'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "156", "'cCc2'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "157", "'cCc1'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "158", "'cIc2'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "159", "'cIc1'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "160", "'cFc2'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "161", "'cFc1'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "162", "'cLc2'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "163", "'cLc1'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "164", "'cWc2'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "165", "'cWc1'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "166", "'cNc2'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "167", "'cNc1'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "168", "'cOc1'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "169", "'cOc2'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "170", "'cZc2'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "171", "'cZc1'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "172", "'cGc2'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "173", "'cGc1'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "174", "'cVc2'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "175", "'cVc1'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "176", "'cQc2'" )
    //! runtextmacro TerrainTypeId2TerrainTypeMaxId( "177", "'cQc1'" )

    return 0
endfunction



endlibrary



//===========================================================================
function InitTrig_Terrain_type_max takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: Terrain type grass
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library TerrainTypeGrass needs TerrainTypeMax


function TerrainTypeGrassId2MaxId takes integer grassId returns integer
	//! textmacro TerrainTypeGrassId2MaxId takes grassId, maxId
	if (grassId == $grassId$) then
		return $maxId$
	endif
	//! endtextmacro
	
	//! runtextmacro TerrainTypeGrassId2MaxId( "1", "5" )
	//! runtextmacro TerrainTypeGrassId2MaxId( "2", "11" )
	//! runtextmacro TerrainTypeGrassId2MaxId( "3", "12" )
	//! runtextmacro TerrainTypeGrassId2MaxId( "4", "17" )
	//! runtextmacro TerrainTypeGrassId2MaxId( "5", "26" )
	//! runtextmacro TerrainTypeGrassId2MaxId( "6", "29" )
	//! runtextmacro TerrainTypeGrassId2MaxId( "7", "40" )
	//! runtextmacro TerrainTypeGrassId2MaxId( "8", "45" )
	//! runtextmacro TerrainTypeGrassId2MaxId( "9", "55" )
	//! runtextmacro TerrainTypeGrassId2MaxId( "10", "63" )
	//! runtextmacro TerrainTypeGrassId2MaxId( "11", "65" )
	//! runtextmacro TerrainTypeGrassId2MaxId( "12", "71" )
	//! runtextmacro TerrainTypeGrassId2MaxId( "13", "73" )
	//! runtextmacro TerrainTypeGrassId2MaxId( "14", "80" )
	//! runtextmacro TerrainTypeGrassId2MaxId( "15", "106" )
	//! runtextmacro TerrainTypeGrassId2MaxId( "16", "107" )
	//! runtextmacro TerrainTypeGrassId2MaxId( "17", "139" )

    return 0
endfunction


function TerrainTypeMaxId2GrassId takes integer maxId returns integer
	//! textmacro TerrainTypeMaxId2GrassId takes grassId, maxId
	if (maxId == $maxId$) then
		return $grassId$
	endif
	//! endtextmacro
	
	//! runtextmacro TerrainTypeMaxId2GrassId( "1", "5" )
	//! runtextmacro TerrainTypeMaxId2GrassId( "2", "11" )
	//! runtextmacro TerrainTypeMaxId2GrassId( "3", "12" )
	//! runtextmacro TerrainTypeMaxId2GrassId( "4", "17" )
	//! runtextmacro TerrainTypeMaxId2GrassId( "5", "26" )
	//! runtextmacro TerrainTypeMaxId2GrassId( "6", "29" )
	//! runtextmacro TerrainTypeMaxId2GrassId( "7", "40" )
	//! runtextmacro TerrainTypeMaxId2GrassId( "8", "45" )
	//! runtextmacro TerrainTypeMaxId2GrassId( "9", "55" )
	//! runtextmacro TerrainTypeMaxId2GrassId( "10", "63" )
	//! runtextmacro TerrainTypeMaxId2GrassId( "11", "65" )
	//! runtextmacro TerrainTypeMaxId2GrassId( "12", "71" )
	//! runtextmacro TerrainTypeMaxId2GrassId( "13", "73" )
	//! runtextmacro TerrainTypeMaxId2GrassId( "14", "80" )
	//! runtextmacro TerrainTypeMaxId2GrassId( "15", "106" )
	//! runtextmacro TerrainTypeMaxId2GrassId( "16", "107" )
	//! runtextmacro TerrainTypeMaxId2GrassId( "17", "139" )

    return 0
endfunction


function TerrainTypeGrassId2TerrainTypeId takes integer grassId returns integer
    return TerrainTypeMaxId2TerrainTypeId(TerrainTypeGrassId2MaxId(grassId))
endfunction



endlibrary


//===========================================================================
function InitTrig_Terrain_type_grass takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: Terrain type names and data
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library TerrainTypeNamesAndData needs TerrainTypeAsciiConversion, TerrainTypeMax, TerrainTypeGrass


globals
    string array TERRAIN_TYPE_NAMES
    string array TERRAIN_TYPE_DATA
    integer NB_TERRAINS_TOTAL = 177
endglobals




function InitTrig_Terrain_type_names_and_data takes nothing returns nothing
    local integer maxId
    local integer terrain
    local integer grassId
    local string S

    set TERRAIN_TYPE_NAMES[  1] = "Eté de Lordaeron - Terre"
    set TERRAIN_TYPE_NAMES[  2] = "Eté de Lordaeron - Terre rocailleuse"
    set TERRAIN_TYPE_NAMES[  3] = "Eté de Lordaeron - Terre herbeuse"
    set TERRAIN_TYPE_NAMES[  4] = "Eté de Lordaeron - Rochers"
    set TERRAIN_TYPE_NAMES[  5] = "Eté de Lordaeron - Herbe"
    set TERRAIN_TYPE_NAMES[  6] = "Eté de Lordaeron - Herbe sombre"
    set TERRAIN_TYPE_NAMES[  7] = "Automne de Lordaeron - Terre"
    set TERRAIN_TYPE_NAMES[  8] = "Automne de Lordaeron - Terre rocailleuse"
    set TERRAIN_TYPE_NAMES[  9] = "Automne de Lordaeron - Terre herbeuse"
    set TERRAIN_TYPE_NAMES[ 10] = "Automne de Lordaeron - Rochers"
    set TERRAIN_TYPE_NAMES[ 11] = "Automne de Lordaeron - Herbe"
    set TERRAIN_TYPE_NAMES[ 12] = "Automne de Lordaeron - Herbe sombre"
    set TERRAIN_TYPE_NAMES[ 13] = "Hiver de Lordaeron - Terre"
    set TERRAIN_TYPE_NAMES[ 14] = "Hiver de Lordaeron - Terre rocailleuse"
    set TERRAIN_TYPE_NAMES[ 15] = "Hiver de Lordaeron - Terre herbeuse"
    set TERRAIN_TYPE_NAMES[ 16] = "Hiver de Lordaeron - Rochers"
    set TERRAIN_TYPE_NAMES[ 17] = "Hiver de Lordaeron - Herbe"
    set TERRAIN_TYPE_NAMES[ 18] = "Hiver de Lordaeron - Herbe sombre"
    set TERRAIN_TYPE_NAMES[ 19] = "Barrens - Terre"
    set TERRAIN_TYPE_NAMES[ 20] = "Barrens - Terre rocailleuse"
    set TERRAIN_TYPE_NAMES[ 21] = "Barrens - Cailloux"
    set TERRAIN_TYPE_NAMES[ 22] = "Barrens - Terre herbeuse"
    set TERRAIN_TYPE_NAMES[ 23] = "Barrens - Désert"
    set TERRAIN_TYPE_NAMES[ 24] = "Barrens - Désert sombre"
    set TERRAIN_TYPE_NAMES[ 25] = "Barrens - Rochers"
    set TERRAIN_TYPE_NAMES[ 26] = "Barrens - Herbe"
    set TERRAIN_TYPE_NAMES[ 27] = "Ashenvale - Terre"
    set TERRAIN_TYPE_NAMES[ 28] = "Ashenvale - Terre rocailleuse"
    set TERRAIN_TYPE_NAMES[ 29] = "Ashenvale - Herbe"
    set TERRAIN_TYPE_NAMES[ 30] = "Ashenvale - Rochers"
    set TERRAIN_TYPE_NAMES[ 31] = "Ashenvale - Touffes d'herbe"
    set TERRAIN_TYPE_NAMES[ 32] = "Ashenvale - Vignes"
    set TERRAIN_TYPE_NAMES[ 33] = "Ashenvale - Terre herbeuse"
    set TERRAIN_TYPE_NAMES[ 34] = "Ashenvale - Feuilles"
    set TERRAIN_TYPE_NAMES[ 35] = "Felwood - Terre"
    set TERRAIN_TYPE_NAMES[ 36] = "Felwood - Terre rocailleuse"
    set TERRAIN_TYPE_NAMES[ 37] = "Felwood - Poison"
    set TERRAIN_TYPE_NAMES[ 38] = "Felwood - Rochers"
    set TERRAIN_TYPE_NAMES[ 39] = "Felwood - Vignes"
    set TERRAIN_TYPE_NAMES[ 40] = "Felwood - Herbe"
    set TERRAIN_TYPE_NAMES[ 41] = "Felwood - Feuilles"
    set TERRAIN_TYPE_NAMES[ 42] = "Northrend - Terre"
    set TERRAIN_TYPE_NAMES[ 43] = "Northrend - Terre sombre"
    set TERRAIN_TYPE_NAMES[ 44] = "Northrend - Rochers"
    set TERRAIN_TYPE_NAMES[ 45] = "Northrend - Herbe"
    set TERRAIN_TYPE_NAMES[ 46] = "Northrend - Glace"
    set TERRAIN_TYPE_NAMES[ 47] = "Northrend - Neige"
    set TERRAIN_TYPE_NAMES[ 48] = "Northrend - Neige rocailleuse"
    set TERRAIN_TYPE_NAMES[ 49] = "Ville - Terre"
    set TERRAIN_TYPE_NAMES[ 50] = "Ville - Terre rocailleuse"
    set TERRAIN_TYPE_NAMES[ 51] = "Ville - Marbre noir"
    set TERRAIN_TYPE_NAMES[ 52] = "Ville - Briques"
    set TERRAIN_TYPE_NAMES[ 53] = "Ville - Dalles carrées"
    set TERRAIN_TYPE_NAMES[ 54] = "Ville - Dalles rondes"
    set TERRAIN_TYPE_NAMES[ 55] = "Ville - Herbe"
    set TERRAIN_TYPE_NAMES[ 56] = "Ville - Jardin"
    set TERRAIN_TYPE_NAMES[ 57] = "Ville - Marbre blanc"
    set TERRAIN_TYPE_NAMES[ 58] = "Village - Terre"
    set TERRAIN_TYPE_NAMES[ 59] = "Village - Terre rocailleuse"
    set TERRAIN_TYPE_NAMES[ 60] = "Village - Champs"
    set TERRAIN_TYPE_NAMES[ 61] = "Village - Chemin caillouteux"
    set TERRAIN_TYPE_NAMES[ 62] = "Village - Chemin pavé"
    set TERRAIN_TYPE_NAMES[ 63] = "Village - Herbe courte"
    set TERRAIN_TYPE_NAMES[ 64] = "Village - Rochers"
    set TERRAIN_TYPE_NAMES[ 65] = "Village - Herbe épaisse"
    set TERRAIN_TYPE_NAMES[ 66] = "Village automne - Terre"
    set TERRAIN_TYPE_NAMES[ 67] = "Village automne - Terre rocailleuse"
    set TERRAIN_TYPE_NAMES[ 68] = "Village automne - Champs"
    set TERRAIN_TYPE_NAMES[ 69] = "Village automne - Chemin caillouteux"
    set TERRAIN_TYPE_NAMES[ 70] = "Village automne - Chemin pavé"
    set TERRAIN_TYPE_NAMES[ 71] = "Village automne - Herbe courte"
    set TERRAIN_TYPE_NAMES[ 72] = "Village automne - Rochers"
    set TERRAIN_TYPE_NAMES[ 73] = "Village automne - Herbe épaisse"
    set TERRAIN_TYPE_NAMES[ 74] = "Dalaran - Terre"
    set TERRAIN_TYPE_NAMES[ 75] = "Dalaran - Terre rocailleuse"
    set TERRAIN_TYPE_NAMES[ 76] = "Dalaran - Marbre noir"
    set TERRAIN_TYPE_NAMES[ 77] = "Dalaran - Briques"
    set TERRAIN_TYPE_NAMES[ 78] = "Dalaran - Dalles carrées"
    set TERRAIN_TYPE_NAMES[ 79] = "Dalaran - Dalles rondes"
    set TERRAIN_TYPE_NAMES[ 80] = "Dalaran - Herbe"
    set TERRAIN_TYPE_NAMES[ 81] = "Dalaran - Jardin"
    set TERRAIN_TYPE_NAMES[ 82] = "Dalaran - Marbre blanc"
    set TERRAIN_TYPE_NAMES[ 83] = "Donjon - Terre"
    set TERRAIN_TYPE_NAMES[ 84] = "Donjon - Briques"
    set TERRAIN_TYPE_NAMES[ 85] = "Donjon - Pierres rouges"
    set TERRAIN_TYPE_NAMES[ 86] = "Donjon - Fissures de lave"
    set TERRAIN_TYPE_NAMES[ 87] = "Donjon - Lave"
    set TERRAIN_TYPE_NAMES[ 88] = "Donjon - Rochers noirs"
    set TERRAIN_TYPE_NAMES[ 89] = "Donjon - Pierres grises"
    set TERRAIN_TYPE_NAMES[ 90] = "Donjon - Dalles carrées"
    set TERRAIN_TYPE_NAMES[ 91] = "Souterrain - Terre"
    set TERRAIN_TYPE_NAMES[ 92] = "Souterrain - Briques"
    set TERRAIN_TYPE_NAMES[ 93] = "Souterrain - Pierres rouges"
    set TERRAIN_TYPE_NAMES[ 94] = "Souterrain - Fissures de lave"
    set TERRAIN_TYPE_NAMES[ 95] = "Souterrain - Lave"
    set TERRAIN_TYPE_NAMES[ 96] = "Souterrain - Rochers noirs"
    set TERRAIN_TYPE_NAMES[ 97] = "Souterrain - Pierres grises"
    set TERRAIN_TYPE_NAMES[ 98] = "Souterrain - Dalles carrées"
    set TERRAIN_TYPE_NAMES[ 99] = "Ruines englouties - Terre"
    set TERRAIN_TYPE_NAMES[100] = "Ruines englouties - Terre rocailleuse"
    set TERRAIN_TYPE_NAMES[101] = "Ruines englouties - Terre herbeuse"
    set TERRAIN_TYPE_NAMES[102] = "Ruines englouties - Petites briques"
    set TERRAIN_TYPE_NAMES[103] = "Ruines englouties - Sable"
    set TERRAIN_TYPE_NAMES[104] = "Ruines englouties - Grandes briques"
    set TERRAIN_TYPE_NAMES[105] = "Ruines englouties - Dalles rondes"
    set TERRAIN_TYPE_NAMES[106] = "Ruines englouties - Herbe"
    set TERRAIN_TYPE_NAMES[107] = "Ruines englouties - Herbe sombre"
    set TERRAIN_TYPE_NAMES[108] = "Glacier d'Icecrown - Terre"
    set TERRAIN_TYPE_NAMES[109] = "Glacier d'Icecrown - Terre rocailleuse"
    set TERRAIN_TYPE_NAMES[110] = "Glacier d'Icecrown - Glace sombre"
    set TERRAIN_TYPE_NAMES[111] = "Glacier d'Icecrown - Briques noires"
    set TERRAIN_TYPE_NAMES[112] = "Glacier d'Icecrown - Briques runiques"
    set TERRAIN_TYPE_NAMES[113] = "Glacier d'Icecrown - Briques empilées"
    set TERRAIN_TYPE_NAMES[114] = "Glacier d'Icecrown - Glace"
    set TERRAIN_TYPE_NAMES[115] = "Glacier d'Icecrown - Carrés noirs"
    set TERRAIN_TYPE_NAMES[116] = "Glacier d'Icecrown - Neige"
    set TERRAIN_TYPE_NAMES[117] = "Outland - Terre"
    set TERRAIN_TYPE_NAMES[118] = "Outland - Terre claire"
    set TERRAIN_TYPE_NAMES[119] = "Outland - rocailleuse"
    set TERRAIN_TYPE_NAMES[120] = "Outland - Terre craquelée"
    set TERRAIN_TYPE_NAMES[121] = "Outland - Pierres plates"
    set TERRAIN_TYPE_NAMES[122] = "Outland - Rochers"
    set TERRAIN_TYPE_NAMES[123] = "Outland - Pierres plates claires"
    set TERRAIN_TYPE_NAMES[124] = "Outland - Abysse"
    set TERRAIN_TYPE_NAMES[125] = "Citadelle noire - Terre"
    set TERRAIN_TYPE_NAMES[126] = "Citadelle noire - Terre claire"
    set TERRAIN_TYPE_NAMES[127] = "Citadelle noire - Terre rocailleuse"
    set TERRAIN_TYPE_NAMES[128] = "Citadelle noire - Pierres plates"
    set TERRAIN_TYPE_NAMES[129] = "Citadelle noire - Petites briques"
    set TERRAIN_TYPE_NAMES[130] = "Citadelle noire - Grandes briques"
    set TERRAIN_TYPE_NAMES[131] = "Citadelle noire - Dalles carrées"
    set TERRAIN_TYPE_NAMES[132] = "Citadelle noire - Dalles sombres"
    set TERRAIN_TYPE_NAMES[133] = "Ruines de Dalaran - Terre"
    set TERRAIN_TYPE_NAMES[134] = "Ruines de Dalaran - Terre rocailleuse"
    set TERRAIN_TYPE_NAMES[135] = "Ruines de Dalaran - Marbre noir"
    set TERRAIN_TYPE_NAMES[136] = "Ruines de Dalaran - Dalles en brique"
    set TERRAIN_TYPE_NAMES[137] = "Ruines de Dalaran - Dalles carrées"
    set TERRAIN_TYPE_NAMES[138] = "Ruines de Dalaran - Dalles rondes"
    set TERRAIN_TYPE_NAMES[139] = "Ruines de Dalaran - Herbe"
    set TERRAIN_TYPE_NAMES[140] = "Ruines de Dalaran - Jardin"
    set TERRAIN_TYPE_NAMES[141] = "Ruines de Dalaran - Marbre blanc"
    set TERRAIN_TYPE_NAMES[142] = "Ashenvale - Falaise"
    set TERRAIN_TYPE_NAMES[143] = "Ashenvale - Falaise herbeuse"
    set TERRAIN_TYPE_NAMES[144] = "Barrens - Falaise désertique"
    set TERRAIN_TYPE_NAMES[145] = "Barrens - Falaise herbeuse"
    set TERRAIN_TYPE_NAMES[146] = "Catacombes - Falaise"
    set TERRAIN_TYPE_NAMES[147] = "Catacombes - Falaise de tuiles noires"
    set TERRAIN_TYPE_NAMES[148] = "Cité - Falaise"
    set TERRAIN_TYPE_NAMES[149] = "Cité - Falaise de tuiles carrées"
    set TERRAIN_TYPE_NAMES[150] = "Dalaran - Falaise"
    set TERRAIN_TYPE_NAMES[151] = "Dalaran - Falaise de tuiles carrées"
    set TERRAIN_TYPE_NAMES[152] = "Ruines de Dalaran - Falaise"
    set TERRAIN_TYPE_NAMES[153] = "Ruines de Dalaran - Falaise de tuiles carrées"
    set TERRAIN_TYPE_NAMES[154] = "Donjon - Falaise"
    set TERRAIN_TYPE_NAMES[155] = "Donjon - Falaise de tuiles carrées"
    set TERRAIN_TYPE_NAMES[156] = "Felwood - Falaise"
    set TERRAIN_TYPE_NAMES[157] = "Felwood - Falaise herbeuse"
    set TERRAIN_TYPE_NAMES[158] = "Glacier d'Icecrown - Falaise de briques runiques"
    set TERRAIN_TYPE_NAMES[159] = "Glacier d'Icecrown - Falaise enneigée"
    set TERRAIN_TYPE_NAMES[160] = "Automne de Lordaeron - Falaise"
    set TERRAIN_TYPE_NAMES[161] = "Automne de Lordaeron - Falaise herbeuse"
    set TERRAIN_TYPE_NAMES[162] = "Eté de Lordaeron - Falaise"
    set TERRAIN_TYPE_NAMES[163] = "Eté de Lordaeron - Falaise herbeuse"
    set TERRAIN_TYPE_NAMES[164] = "Hiver de Lordaeron - Falaise herbeuse"
    set TERRAIN_TYPE_NAMES[165] = "Hiver de Lordaeron - Falaise enneigée"
    set TERRAIN_TYPE_NAMES[166] = "Northrend - Falaise"
    set TERRAIN_TYPE_NAMES[167] = "Northrend - Falaise enneigée"
    set TERRAIN_TYPE_NAMES[168] = "Terres dévastées - Falaise abyssale"
    set TERRAIN_TYPE_NAMES[169] = "Terres dévastées - Falaise ardue"
    set TERRAIN_TYPE_NAMES[170] = "Ruines englouties - Falaise"
    set TERRAIN_TYPE_NAMES[171] = "Ruines englouties - Falaise de tuiles larges"
    set TERRAIN_TYPE_NAMES[172] = "Souterrain - Falaise"
    set TERRAIN_TYPE_NAMES[173] = "Souterrain - Falaise de tuiles carrées"
    set TERRAIN_TYPE_NAMES[174] = "Village - Falaise"
    set TERRAIN_TYPE_NAMES[175] = "Village - Falaise d'herbe épaisse"
    set TERRAIN_TYPE_NAMES[176] = "Village en automne - Falaise"
    set TERRAIN_TYPE_NAMES[177] = "Village en automne - Falaise d'herbe épaisse"
    
    
    set maxId = 1
    loop
        exitwhen (maxId > NB_TERRAINS_TOTAL)
            set terrain = TerrainTypeMaxId2TerrainTypeId(maxId)
            set S = TERRAIN_TYPE_NAMES[maxId] + " :    " + I2S(maxId) + "    " + TerrainTypeId2TerrainTypeAsciiString(terrain)
            set grassId = TerrainTypeMaxId2GrassId(maxId)
            if (grassId != 0) then
                set S = S + "    g" + I2S(grassId)
            endif
            set TERRAIN_TYPE_DATA[maxId] = S
        set maxId = maxId + 1
    endloop
endfunction




endlibrary
//===========================================================================
// Trigger: Terrain functions
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library TerrainFunctions needs TerrainTypeAsciiConversion, TerrainTypeMax, TerrainTypeGrass, TerrainTypeFunctions



function IsTerrainAlreadyUsed takes integer terrainType returns boolean
    local integer i = 0
    loop
        exitwhen (udg_used_terrain_types[i] == 0)
            if (udg_used_terrain_types[i] == terrainType) then
                return true
            endif
        set i = i + 1
    endloop
    return false
endfunction


function IsTerrainsLimitNumberReached takes nothing returns boolean
    return (udg_nb_used_terrains == NB_MAX_OF_TERRAINS)
endfunction


function AddNewTerrain takes integer newTerrain returns boolean
    if (IsTerrainsLimitNumberReached() or IsTerrainAlreadyUsed(newTerrain)) then
        return false
    endif
    set udg_used_terrain_types[udg_nb_used_terrains] = newTerrain
    set udg_nb_used_terrains = udg_nb_used_terrains + 1
    return true
endfunction

function CanUseTerrain takes integer terrainType returns boolean
    if (IsTerrainAlreadyUsed(terrainType)) then
        return true
    endif
    return AddNewTerrain(terrainType)
endfunction


function GetRandomTerrain takes nothing returns integer
    return TerrainTypeMaxId2TerrainTypeId(GetRandomInt(1, NB_TERRAINS_TOTAL))
endfunction


function GetRandomUsedTerrain takes nothing returns integer
    return udg_used_terrain_types[GetRandomInt(0, udg_nb_used_terrains-1)]
endfunction


function GetRandomNotUsedTerrain takes nothing returns integer
    local integer terrainType
    loop
        set terrainType = GetRandomTerrain()
        exitwhen (not IsTerrainAlreadyUsed(terrainType))
    endloop
    return terrainType  
endfunction


function GetTerrainName takes integer terrain returns string
    if (terrain > NB_TERRAINS_TOTAL) then
        return TERRAIN_TYPE_NAMES[TerrainTypeId2TerrainTypeMaxId(terrain)]
    endif
    if (terrain <= 0) then
        return null
    endif
    return TERRAIN_TYPE_NAMES[terrain]        
endfunction


function GetTerrainData takes integer terrain returns string
    //GetTerrainData('Nice') == "46 : Northrend - Glace    'Nice'"
    local string str
    local integer maxId
    local TerrainType terrainType
    
    if (terrain > NB_TERRAINS_TOTAL) then
        set maxId = TerrainTypeId2TerrainTypeMaxId(terrain)
    else
        if (terrain > 0) then
            set maxId = terrain
            set terrain = TerrainTypeMaxId2TerrainTypeId(maxId)
        else
            return null
        endif
    endif
    set str = udg_colorCode[RED] + TERRAIN_TYPE_DATA[maxId]
    
    set terrainType = TerrainTypeId2TerrainType(terrain)
    if (terrainType != 0) then
        if (terrainType.getKind() == "slide") then
            set str = str + COLOR_TERRAIN_SLIDE
        else 
            if (terrainType.getKind() == "walk") then
                set str = str + COLOR_TERRAIN_WALK
            else
                set str = str + COLOR_TERRAIN_DEATH
            endif
        endif
        set str = str + "        " + terrainType.label
        if (terrainType.alias != null) then
            set str = str + "  " + terrainType.alias
        endif
    endif
    
    return str
endfunction


function DisplayTerrainDataToPlayer takes player p, integer terrain returns nothing
    call DisplayTimedTextToPlayer(p, 0., 0., TERRAIN_DATA_DISPLAY_TIME, GetTerrainData(terrain))
endfunction





//===========================================================================
function InitTrig_Terrain_functions takes nothing returns nothing
endfunction


endlibrary

//===========================================================================
// Trigger: Terrain type from string
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library TerrainTypeFromString needs TerrainFunctions


function TerrainTypeString2TerrainTypeId takes string str returns integer
    if (IsPositiveInteger(str)) then
        return TerrainTypeMaxId2TerrainTypeId(S2I(str))
    endif
    if (SubStringBJ(str, 1, 1) == "g" and IsPositiveInteger(SubStringBJ(str, 2, StringLength(str)))) then
        return TerrainTypeGrassId2TerrainTypeId(S2I(SubStringBJ(str, 2, StringLength(str))))
    endif
    if (StringLength(str) == 6 and SubStringBJ(str, 1, 1) == "'" and SubStringBJ(str, 6, 6) == "'") then
        return TerrainTypeAsciiString2TerrainTypeId(str)
    endif
    if (str == "x") then
        return GetRandomTerrain()
    endif
    if (str == "xnk") then
        return GetRandomNotUsedTerrain()         
    endif
    if (str == "xak") then
        return GetRandomUsedTerrain()
    endif
    return 0
endfunction




endlibrary








//===========================================================================
function InitTrig_Terrain_type_from_string takes nothing returns nothing
endfunction



//===========================================================================
// Trigger: Modify terrain functions
//===========================================================================
//TESH.scrollpos=16
//TESH.alwaysfold=0
library ModifyTerrainFunctions needs TerrainFunctions




function GetNbCaseBetween takes real minX, real minY, real maxX, real maxY returns integer
    return (R2I((maxX - minX)/LARGEUR_CASE) * R2I((maxY - minY)/LARGEUR_CASE))
endfunction


function ChangeTerrainType takes real x, real y, integer terrainTypeId returns nothing
    call SetTerrainType(x, y, terrainTypeId, -1, 1, 0)   
endfunction


function ChangeTerrainBetween takes integer terrainType, real x1, real y1, real x2, real y2 returns boolean
    local real minX = RMinBJ(x1, x2)
    local real minY = RMinBJ(y1, y2)
    local real maxX = RMaxBJ(x1, x2)
    local real maxY = RMaxBJ(y1, y2)

    local real r
    local real x
    local real y

    //call Text.A( "nbCases == " + I2S( GetNbCaseBetween( minX, minY, maxX, maxY ) ) )
    //call Text.A( "changing terrain to : " + TerrainTypeId2TerrainTypeAsciiString( terrainType ) )
    
    if (GetNbCaseBetween(minX, minY, maxX, maxY) > NB_MAX_TILES_MODIFIED) then
        return false
    endif
    if (not CanUseTerrain(terrainType)) then
        return false
    endif
    
    set x = minX
    set y = minY

    loop
        exitwhen (y > maxY)
            loop
                exitwhen (x > maxX)
                    call ChangeTerrainType(x, y, terrainType)  
                set x = x + LARGEUR_CASE
            endloop
            set x = minX
        set y = y + LARGEUR_CASE
    endloop 
    
    //call Text.A( "terrain changed to : " + TerrainTypeId2TerrainTypeAsciiString( GetTerrainType( minX, minY ) ) )
    
    return true
endfunction







endlibrary








//===========================================================================
function InitTrig_Modify_terrain_functions takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: Terrain modifying
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library TerrainModifyingTrig



globals
    real y
    private boolean array wasCheckTerrainTriggerOn
    boolean terrainModifyWorking = false
    //constant integer TERRAIN_MODIFYING_NB_LINES_TO_DO = 5
    //maintenant on fait ligne par ligne (--> 1)
endglobals



function InitTrig_Terrain_modifying takes nothing returns nothing
    set gg_trg_Terrain_modifying = CreateTrigger()
    call DisableTrigger(gg_trg_Terrain_modifying)
    call TriggerRegisterTimerEvent(gg_trg_Terrain_modifying, LOW_PERIOD_FOR_WORK, true)
endfunction


function StopEnabledCheckTerrainTriggers takes nothing returns nothing
    local Escaper escaper
    local integer i = 0
    loop
        exitwhen (i > 11)
            set escaper = udg_escapers.get(i)
            if (escaper != 0) then
                if (escaper.doesCheckTerrain()) then
                    set wasCheckTerrainTriggerOn[i] = true
                    call escaper.enableCheckTerrain(false)
                else
                    set wasCheckTerrainTriggerOn[i] = false
                endif
            endif
        set i = i + 1
    endloop
endfunction


function RestartEnabledCheckTerrainTriggers takes nothing returns nothing
    local Escaper escaper
    local integer i = 0
    loop
        exitwhen (i > 11)
            set escaper = udg_escapers.get(i)
            if (escaper != 0) then
                if (wasCheckTerrainTriggerOn[i]) then
                    call escaper.enableCheckTerrain(true)
                endif
            endif
        set i = i + 1
    endloop
endfunction



endlibrary//===========================================================================
// Trigger: Change one terrain
//===========================================================================
//TESH.scrollpos=46
//TESH.alwaysfold=0
library ChangeOneTerrain needs AllTerrainFunctions, TerrainModifyingTrig


globals
    private integer oldTerrain
    private integer newTerrain
endglobals




function ChangeAppearanceOfOneTerrain_Actions takes nothing returns nothing
    local real x
    //local integer i = 1
    //loop
        //exitwhen (i > TERRAIN_MODIFYING_NB_LINES_TO_DO)
            set x = MAP_MIN_X
            loop
                exitwhen (x > MAP_MAX_X)
                    if (GetTerrainType(x, y) == oldTerrain) then
                        call ChangeTerrainType(x, y, newTerrain)
                    endif
                set x = x + LARGEUR_CASE
            endloop
            set y = y + LARGEUR_CASE
            if (y > MAP_MAX_Y) then
                call DisableTrigger(GetTriggeringTrigger())
                call RestartEnabledCheckTerrainTriggers()
                set terrainModifyWorking = false
                return
            endif
        //set i = i + 1
    //endloop
endfunction


private function StartTerrainModifying takes nothing returns nothing
    call StopEnabledCheckTerrainTriggers()
    call TriggerClearActions(gg_trg_Terrain_modifying)
    call TriggerAddAction(gg_trg_Terrain_modifying, function ChangeAppearanceOfOneTerrain_Actions)
    set y = MAP_MIN_Y
    call EnableTrigger(gg_trg_Terrain_modifying)
    set terrainModifyWorking = true
endfunction 


function ChangeOneTerrain takes string terrainTypeLabel, string newTerrainType returns string
    local TerrainType terrainType
    if (terrainModifyWorking) then
        call Text_erA("can't execute two commands of this type simultaneously !")
        return null
    endif
    
    set terrainType = udg_terrainTypes.get(terrainTypeLabel)
    if (terrainType == 0) then
        return null
    endif
    
    set oldTerrain = terrainType.getTerrainTypeId()
    set newTerrain = TerrainTypeString2TerrainTypeId(newTerrainType)
    if (newTerrain == 0) then
        return null
    endif
    if (udg_terrainTypes.isTerrainTypeIdAlreadyUsed(newTerrain)) then
        return null
    endif
    if (not terrainType.setTerrainTypeId(newTerrain)) then
        return null
    endif
    
    call StartTerrainModifying()   
    return GetTerrainData(newTerrain)
endfunction


    
    
//===========================================================================
function InitTrig_Change_one_terrain takes nothing returns nothing
endfunction


endlibrary



//===========================================================================
// Trigger: Change all terrains
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library ChangeAllTerrains needs AllTerrainFunctions, TerrainModifyingTrig


globals
    private integer array oldTerrainTypes
    private integer array newTerrainTypes  
    private integer lastTerrainArrayId  
    private integer nbNewTerrains
    private integer nbNewTerrainsAllowed
    boolean udg_changeAllTerrainsAtRevive = false
endglobals



function ChangeAllTerrains_Actions takes nothing returns nothing
    local real x
    local integer terrainTypeId
    local boolean done
    local integer j
    //local integer i = 1
    //loop
        //exitwhen (i > TERRAIN_MODIFYING_NB_LINES_TO_DO)
            set x = MAP_MIN_X
            loop
                exitwhen (x > MAP_MAX_X)
                    set terrainTypeId = GetTerrainType(x, y)
                    set done = false
                    set j = 0
                    loop
                        exitwhen (j > lastTerrainArrayId or done)
                            if (terrainTypeId == oldTerrainTypes[j]) then
                                call ChangeTerrainType(x, y, newTerrainTypes[j])
                                set done = true
                            endif
                        set j = j + 1
                    endloop
                set x = x + LARGEUR_CASE
            endloop
            set y = y + LARGEUR_CASE
            if (y > MAP_MAX_Y) then
                call DisableTrigger(GetTriggeringTrigger())
                call RestartEnabledCheckTerrainTriggers()
                set terrainModifyWorking = false
                return
            endif
        //set i = i + 1
    //endloop
endfunction


private function StartTerrainModifying takes nothing returns nothing
    set y = MAP_MIN_Y
    call StopEnabledCheckTerrainTriggers()
    call TriggerClearActions(gg_trg_Terrain_modifying)
    call TriggerAddAction(gg_trg_Terrain_modifying, function ChangeAllTerrains_Actions)
    call EnableTrigger(gg_trg_Terrain_modifying)
    set terrainModifyWorking = true
endfunction 


private function GetRandomTerrain_checked takes nothing returns integer
    local integer i
    local integer rdmTerrain
    local boolean alreadyUsed
    loop
        if (nbNewTerrains >= nbNewTerrainsAllowed) then
            set rdmTerrain = GetRandomUsedTerrain()
        else
            set rdmTerrain = GetRandomTerrain()
        endif
            set alreadyUsed = false
            set i = 0
            loop
                exitwhen (i > lastTerrainArrayId or alreadyUsed)
                    set alreadyUsed = (newTerrainTypes[i] == rdmTerrain)
                set i = i + 1
            endloop
        exitwhen (not alreadyUsed)
    endloop
    if (not IsTerrainAlreadyUsed(rdmTerrain)) then
        set nbNewTerrains = nbNewTerrains + 1
    endif
    return rdmTerrain
endfunction


private function GetRandomKnownTerrain_checked takes nothing returns integer
    local integer i
    local integer rdmTerrain
    local boolean alreadyUsed
    loop
        set rdmTerrain = GetRandomUsedTerrain()
            set alreadyUsed = false
            set i = 0
            loop
                exitwhen (i > lastTerrainArrayId or alreadyUsed)
                    set alreadyUsed = (newTerrainTypes[i] == rdmTerrain)
                set i = i + 1
            endloop
        exitwhen (not alreadyUsed)
    endloop
    return rdmTerrain
endfunction


private function GetRandomNotKnownTerrain_checked takes nothing returns integer
    local integer i
    local integer rdmTerrain
    local boolean alreadyUsed
    loop
        set rdmTerrain = GetRandomNotUsedTerrain()
            set alreadyUsed = false
            set i = 0
            loop
                exitwhen (i > lastTerrainArrayId or alreadyUsed)
                    set alreadyUsed = (newTerrainTypes[i] == rdmTerrain)
                set i = i + 1
            endloop
        exitwhen (not alreadyUsed)
    endloop
    return rdmTerrain
endfunction



function ChangeAllTerrains takes string mode returns boolean

//modes : normal, known, notKnown
    local TerrainType array terrainTypes
    local integer n
    local integer i
    
    if (terrainModifyWorking) then
        call Text_erA("can't execute two commands of this type simultaneously !")
        return false
    endif
    
    set n = 0
    set i = 0
    loop
            set terrainTypes[n] = udg_terrainTypes.getWalk(i)
        exitwhen (terrainTypes[n] == 0)
            set oldTerrainTypes[n] = terrainTypes[n].getTerrainTypeId()
            set n = n + 1
        set i = i + 1
    endloop
    set i = 0
    loop
            set terrainTypes[n] = udg_terrainTypes.getDeath(i)
        exitwhen (terrainTypes[n] == 0)
            set oldTerrainTypes[n] = terrainTypes[n].getTerrainTypeId()
            set n = n + 1
        set i = i + 1
    endloop
    set i = 0
    loop
            set terrainTypes[n] = udg_terrainTypes.getSlide(i)
        exitwhen (terrainTypes[n] == 0)
            set oldTerrainTypes[n] = terrainTypes[n].getTerrainTypeId()
            set n = n + 1
        set i = i + 1
    endloop
    
    set lastTerrainArrayId = n - 1
    set nbNewTerrainsAllowed = NB_MAX_OF_TERRAINS - udg_nb_used_terrains
    
    if (mode == "normal") then
        set nbNewTerrains = 0
        set i = 0
        loop
            exitwhen (i > lastTerrainArrayId)
                set newTerrainTypes[i] = GetRandomTerrain_checked()
            set i = i + 1
        endloop
    else
        if (mode == "known") then
            set i = 0
            loop
                exitwhen (i > lastTerrainArrayId)
                    set newTerrainTypes[i] = GetRandomKnownTerrain_checked()
                set i = i + 1
            endloop
        else
            if (mode == "notKnown") then
                set nbNewTerrains = lastTerrainArrayId + 1
                if (nbNewTerrains > nbNewTerrainsAllowed) then
                    return false
                endif
                set i = 0
                loop
                    exitwhen (i > lastTerrainArrayId)
                        set newTerrainTypes[i] = GetRandomNotKnownTerrain_checked()
                    set i = i + 1
                endloop
            endif
        endif
    endif
    
    call StartTerrainModifying() 
    
    set i = 0
    loop
        exitwhen (i > lastTerrainArrayId)
            call terrainTypes[i].setTerrainTypeId(newTerrainTypes[i])
            call AddNewTerrain(newTerrainTypes[i])
        set i = i + 1
    endloop
    
    //call DisplayTextToForce(GetPlayersAll(), " ")
    //call DisplayTextToForce(GetPlayersAll(), udg_colorCode[TEAL] + "       All terrains changed !")
    //set i = 0
    //loop
    //    exitwhen (i > lastTerrainArrayId)
    //        call Text_A(udg_colorCode[RED] + GetTerrainData(newTerrainTypes[i]))
    //    set i = i + 1
    //endloop

    return true
endfunction





//===========================================================================
function InitTrig_Change_all_terrains takes nothing returns nothing
endfunction


endlibrary//===========================================================================
// Trigger: Exchange terrains
//===========================================================================
//TESH.scrollpos=45
//TESH.alwaysfold=0
library ExchangeTerrains needs AllTerrainFunctions, TerrainModifyingTrig


globals
    private integer terrainA
    private integer terrainB
endglobals




function ExchangeTerrains_Actions takes nothing returns nothing
    local real x
    local integer terrainType
    //local integer i = 1
    //loop
        //exitwhen (i > TERRAIN_MODIFYING_NB_LINES_TO_DO)
            set x = MAP_MIN_X
            loop
                exitwhen (x > MAP_MAX_X)
                    set terrainType = GetTerrainType(x, y)
                    if (terrainType == terrainA) then
                        call ChangeTerrainType( x, y, terrainB )
                    else
                    if (terrainType == terrainB) then
                        call ChangeTerrainType( x, y, terrainA )
                    endif
                    endif
                set x = x + LARGEUR_CASE
            endloop
            set y = y + LARGEUR_CASE
            if (y > MAP_MAX_Y) then
                call DisableTrigger(GetTriggeringTrigger())
                call RestartEnabledCheckTerrainTriggers()
                set terrainModifyWorking = false
                return
            endif
        //set i = i + 1
    //endloop
endfunction


private function StartTerrainModifying takes nothing returns nothing
    call StopEnabledCheckTerrainTriggers()
    call TriggerClearActions(gg_trg_Terrain_modifying)
    call TriggerAddAction(gg_trg_Terrain_modifying, function ExchangeTerrains_Actions)
    set y = MAP_MIN_Y
    call EnableTrigger(gg_trg_Terrain_modifying)
    set terrainModifyWorking = true
endfunction 



function ExchangeTerrains takes string terrainTypeLabelA, string terrainTypeLabelB returns boolean
    local TerrainType terrainTypeA = udg_terrainTypes.get(terrainTypeLabelA)
    local TerrainType terrainTypeB = udg_terrainTypes.get(terrainTypeLabelB)
    if (terrainTypeA == terrainTypeB) then
        return false
    endif
    if (terrainModifyWorking) then
        call Text_erA("can't execute two commands of this type simultaneously !")
        return false
    endif
    
    set terrainA = terrainTypeA.getTerrainTypeId()
    set terrainB = terrainTypeB.getTerrainTypeId()
    
    call StartTerrainModifying()  
    
    call terrainTypeA.setTerrainTypeId(terrainB)
    call terrainTypeB.setTerrainTypeId(terrainA)
    return true
endfunction
    


    
//===========================================================================
function InitTrig_Exchange_terrains takes nothing returns nothing
endfunction


endlibrary//===========================================================================
// Trigger: Randomize terrains
//===========================================================================
//TESH.scrollpos=20
//TESH.alwaysfold=0
library RandomizeTerrains needs AllTerrainFunctions, TerrainModifyingTrig


globals
    private integer array oldTerrainTypes
    private integer array newTerrainTypes
    private integer lastTerrainArrayId
endglobals





function RandomizeTerrains_Actions takes nothing returns nothing
    local real x
    local integer terrainTypeId
    local boolean done
    local integer j
    local integer i = 1
    //loop
        //exitwhen (i > TERRAIN_MODIFYING_NB_LINES_TO_DO)
            set x = MAP_MIN_X
            loop
                exitwhen (x > MAP_MAX_X)
                    set terrainTypeId = GetTerrainType(x, y)
                    set done = false
                    set j = 0
                    loop
                        exitwhen (j > lastTerrainArrayId or done)
                            if (terrainTypeId == oldTerrainTypes[j]) then
                                call ChangeTerrainType(x, y, newTerrainTypes[j])
                                set done = true
                            endif
                        set j = j + 1
                    endloop
                set x = x + LARGEUR_CASE
            endloop
            set y = y + LARGEUR_CASE
            if (y > MAP_MAX_Y) then
                call DisableTrigger(GetTriggeringTrigger())
                call RestartEnabledCheckTerrainTriggers()
                set terrainModifyWorking = false
                return
            endif
        //set i = i + 1
    //endloop
endfunction


private function StartTerrainModifying takes nothing returns nothing
    call StopEnabledCheckTerrainTriggers()
    call TriggerClearActions(gg_trg_Terrain_modifying)
    call TriggerAddAction(gg_trg_Terrain_modifying, function RandomizeTerrains_Actions)
    set y = MAP_MIN_Y
    call EnableTrigger(gg_trg_Terrain_modifying)
    set terrainModifyWorking = true
endfunction 


function RandomizeTerrains takes nothing returns nothing
    local integer i
    local integer n
    local boolean array isTaken
    local TerrainType array terrainTypes
    
    if (terrainModifyWorking) then
        call Text_erA("can't execute two commands of this type simultaneously !")
        return
    endif
    
    set n = 0
    set i = 0
    loop
            set terrainTypes[n] = udg_terrainTypes.getWalk(i)
        exitwhen (terrainTypes[n] == 0)
            set oldTerrainTypes[n] = terrainTypes[n].getTerrainTypeId()
            set n = n + 1
        set i = i + 1
    endloop
    set i = 0
    loop
            set terrainTypes[n] = udg_terrainTypes.getDeath(i)
        exitwhen (terrainTypes[n] == 0)
            set oldTerrainTypes[n] = terrainTypes[n].getTerrainTypeId()
            set n = n + 1
        set i = i + 1
    endloop
    set i = 0
    loop
            set terrainTypes[n] = udg_terrainTypes.getSlide(i)
        exitwhen (terrainTypes[n] == 0)
            set oldTerrainTypes[n] = terrainTypes[n].getTerrainTypeId()
            set n = n + 1
        set i = i + 1
    endloop
    
    set lastTerrainArrayId = n - 1
    
    set i = 0
    loop
        exitwhen (i > lastTerrainArrayId)
            set isTaken[i] = false
        set i = i + 1
    endloop
    
    set i = 0
    loop
        exitwhen (i > lastTerrainArrayId)
            loop
                set n = GetRandomInt(0, lastTerrainArrayId)
                exitwhen (not isTaken[n])
            endloop
            set isTaken[n] = true
            set newTerrainTypes[i] = oldTerrainTypes[n]
        set i = i + 1
    endloop
    
    call StartTerrainModifying() 
    
    set i = 0
    loop
        exitwhen (i > lastTerrainArrayId)
            call terrainTypes[i].setTerrainTypeId(newTerrainTypes[i])
        set i = i + 1
    endloop
endfunction





//===========================================================================
function InitTrig_Randomize_terrains takes nothing returns nothing
endfunction


endlibrary//===========================================================================
// Trigger: Reinit terrains
//===========================================================================
//TESH.scrollpos=14
//TESH.alwaysfold=0
library ReinitTerrains needs AllTerrainFunctions, TerrainModifyingTrig



globals
    private TerrainType array terrainTypes
    private integer array terrainTypeIds
    private integer array terrainTypeIdsToReplace
endglobals


private function SaveTerrainConfig takes nothing returns nothing
    local integer n = 0
    local integer i = 0
    loop
        exitwhen (i >= udg_terrainTypes.numberOfWalk)
            set terrainTypes[n] = udg_terrainTypes.getWalk(i)
            set terrainTypeIds[n] = terrainTypes[n].getTerrainTypeId()
            set n = n + 1
        set i = i + 1
    endloop
    set i = 0
    loop
        exitwhen (i >= udg_terrainTypes.numberOfDeath)
            set terrainTypes[n] = udg_terrainTypes.getDeath(i)
            set terrainTypeIds[n] = terrainTypes[n].getTerrainTypeId()
            set n = n + 1
        set i = i + 1
    endloop
    set i = 0
    loop
        exitwhen (i >= udg_terrainTypes.numberOfSlide)
            set terrainTypes[n] = udg_terrainTypes.getSlide(i)
            set terrainTypeIds[n] = terrainTypes[n].getTerrainTypeId()
            set n = n + 1
        set i = i + 1
    endloop
endfunction


function InitTrig_Reinit_terrains takes nothing returns nothing
    local trigger trig = CreateTrigger()
    call TriggerAddAction(trig, function SaveTerrainConfig)
    call TriggerRegisterTimerEvent(trig, 0, false)
    set trig = null
endfunction






function ReinitTerrains_Actions takes nothing returns nothing
    local real x
    local integer terrainTypeId
    local boolean done
    local integer j
    //local integer i = 1
    //loop
        //exitwhen (i > TERRAIN_MODIFYING_NB_LINES_TO_DO)
            set x = MAP_MIN_X
            loop
                exitwhen (x > MAP_MAX_X)
                    set terrainTypeId = GetTerrainType(x, y)
                    set done = false
                    set j = 0
                    loop
                        exitwhen (terrainTypes[j] == 0 or done)
                            if (terrainTypeId == terrainTypeIdsToReplace[j]) then
                                call ChangeTerrainType(x, y, terrainTypeIds[j])
                                set done = true
                            endif
                        set j = j + 1
                    endloop
                set x = x + LARGEUR_CASE
            endloop
            set y = y + LARGEUR_CASE
            if (y > MAP_MAX_Y) then
                call DisableTrigger(GetTriggeringTrigger())
                call RestartEnabledCheckTerrainTriggers()
                set terrainModifyWorking = false
                call Text_mkA("Terrains reinitialized")
                return
            endif
        //set i = i + 1
    //endloop
endfunction


private function StartTerrainModifying takes nothing returns nothing
    call StopEnabledCheckTerrainTriggers()
    call TriggerClearActions(gg_trg_Terrain_modifying)
    call TriggerAddAction(gg_trg_Terrain_modifying, function ReinitTerrains_Actions)
    set y = MAP_MIN_Y
    call EnableTrigger(gg_trg_Terrain_modifying)
    set terrainModifyWorking = true
endfunction 


function ReinitTerrains takes nothing returns nothing
    local integer i 
    
    if (terrainModifyWorking) then
        call Text_erA("can't execute two commands of this type simultaneously !")
        return
    endif
    
    set i = 0
    loop
        exitwhen (terrainTypes[i] == 0)
            set terrainTypeIdsToReplace[i] = terrainTypes[i].getTerrainTypeId()
            call terrainTypes[i].setTerrainTypeId(terrainTypeIds[i])
        set i = i + 1
    endloop
    call StartTerrainModifying()
endfunction








endlibrary//===========================================================================
// Trigger: Reinit terrains position Change variations and ut at beginning
//===========================================================================
//TESH.scrollpos=85
//TESH.alwaysfold=0
library ReinitTerrainsPositions needs AllTerrainFunctions, TerrainModifyingTrig


globals
    private TerrainType array TERRAIN_SAVE [232000]
    private integer terrainSave_id
endglobals



    //save terrain at init
    


private function SaveTerrain_Actions takes nothing returns nothing
    local integer terrainType
    local real x = MAP_MIN_X
    loop
        exitwhen (x > MAP_MAX_X)
            set terrainType = GetTerrainType(x, y)
            //mise à jour used terrain (-ut)
            call AddNewTerrain(terrainType)
            //changer variations
            call ChangeTerrainType(x, y, terrainType)
            //sauvegarde du terrain
            set TERRAIN_SAVE[terrainSave_id] = TerrainTypeId2TerrainType(terrainType)
            set terrainSave_id = terrainSave_id + 1
        set x = x + LARGEUR_CASE
    endloop
    
    set y = y + LARGEUR_CASE
    if (y > MAP_MAX_Y) then
        set terrainModifyWorking = false
        call DisableTrigger(GetTriggeringTrigger())
        return
    endif
endfunction


private function StartSaveTerrain takes nothing returns nothing
    call TriggerClearActions(gg_trg_Terrain_modifying)
    call TriggerAddAction(gg_trg_Terrain_modifying, function SaveTerrain_Actions)
    set terrainSave_id = 0
    set y = MAP_MIN_Y
    call EnableTrigger(gg_trg_Terrain_modifying)
    set terrainModifyWorking = true
    call DestroyTrigger(GetTriggeringTrigger())
endfunction


function InitTrig_Reinit_terrains_position_Change_variations_and_ut_at_beginning takes nothing returns nothing
    local trigger trig = CreateTrigger()
    call TriggerAddAction(trig, function StartSaveTerrain)
    call TriggerRegisterTimerEvent(trig, 0, false)
    set trig = null
endfunction



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


    //reinitTerrainPositions
    
    
function ReinitTerrainsPosition_Actions takes nothing returns nothing
    local real x
    //local integer i = 1
    //loop
        //exitwhen (i > TERRAIN_MODIFYING_NB_LINES_TO_DO)
            set x = MAP_MIN_X
            loop
                exitwhen (x > MAP_MAX_X)
                    if (TERRAIN_SAVE[terrainSave_id] != 0 and TERRAIN_SAVE[terrainSave_id].getTerrainTypeId() != 0) then
                        call ChangeTerrainType(x, y, TERRAIN_SAVE[terrainSave_id].getTerrainTypeId())
                    endif
                    set terrainSave_id = terrainSave_id + 1
                set x = x + LARGEUR_CASE
            endloop
            set y = y + LARGEUR_CASE
            if (y > MAP_MAX_Y) then
                call Text_mkA("Terrains position reinitialized !")
                call DisableTrigger( GetTriggeringTrigger() )
                set terrainModifyWorking = false
                call RestartEnabledCheckTerrainTriggers()
                return
            endif
        //set i = i + 1
    //endloop
endfunction



private function StartTerrainModifying takes nothing returns nothing
    call TriggerClearActions(gg_trg_Terrain_modifying)
    call TriggerAddAction(gg_trg_Terrain_modifying, function ReinitTerrainsPosition_Actions)
    set terrainSave_id = 0
    set y = MAP_MIN_Y
    call EnableTrigger(gg_trg_Terrain_modifying)
    set terrainModifyWorking = true
    call StopEnabledCheckTerrainTriggers()
endfunction 





function ReinitTerrainsPosition takes nothing returns nothing
    if (terrainModifyWorking) then
        call Text_erA("can't execute two commands of this type simultaneously !")
        return
    endif
    call StartTerrainModifying()
endfunction






endlibrary//===========================================================================
// Trigger: Save load terrain without name
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library SaveLoadTerrainWithoutName needs AllTerrainFunctions, TerrainModifyingTrig


globals
    private TerrainType array terrainSave [232000]
    private integer terrainSave_id
endglobals



    //save terrain
    

private function SaveTerrain_Actions takes nothing returns nothing
    local real x = MAP_MIN_X
    loop
        exitwhen (x > MAP_MAX_X)
            set terrainSave[terrainSave_id] = udg_terrainTypes.getTerrainType(x, y)
            set terrainSave_id = terrainSave_id + 1
        set x = x + LARGEUR_CASE
    endloop
    
    set y = y + LARGEUR_CASE
    if (y > MAP_MAX_Y) then
        set terrainModifyWorking = false
        call DisableTrigger(GetTriggeringTrigger())
        call Text_mkA("Terrain saved")
        return
    endif
endfunction


function SaveTerrainWithoutName takes nothing returns nothing
    if (terrainModifyWorking) then
        call Text_erA("can't execute two commands of this type simultaneously !")
        return
    endif
    call TriggerClearActions(gg_trg_Terrain_modifying)
    call TriggerAddAction(gg_trg_Terrain_modifying, function SaveTerrain_Actions)
    set terrainSave_id = 0
    set y = MAP_MIN_Y
    call EnableTrigger(gg_trg_Terrain_modifying)
    set terrainModifyWorking = true
endfunction






    //load terrain
    
    
    
    
private function LoadTerrain_Actions takes nothing returns nothing
    local real x
    //local integer i = 1
    //loop
        //exitwhen (i > TERRAIN_MODIFYING_NB_LINES_TO_DO)
            set x = MAP_MIN_X
            loop
                exitwhen (x > MAP_MAX_X)
                    if (terrainSave[terrainSave_id] != 0) then
                        call ChangeTerrainType(x, y, terrainSave[terrainSave_id].getTerrainTypeId())
                    endif
                    set terrainSave_id = terrainSave_id + 1
                set x = x + LARGEUR_CASE
            endloop
            set y = y + LARGEUR_CASE
            if (y > MAP_MAX_Y) then
                call RestartEnabledCheckTerrainTriggers()
                call Text_mkA("Terrain loaded")
                call DisableTrigger(GetTriggeringTrigger())
                set terrainModifyWorking = false
                return
            endif
        //set i = i + 1
    //endloop    
endfunction



function LoadTerrainWithoutName takes nothing returns nothing
    if (terrainModifyWorking) then
        call Text_erA("can't execute two commands of this type simultaneously !")
        return
    endif
    call TriggerClearActions( gg_trg_Terrain_modifying )
    call TriggerAddAction( gg_trg_Terrain_modifying, function LoadTerrain_Actions )
    set terrainSave_id = 0
    set y = MAP_MIN_Y
    call EnableTrigger( gg_trg_Terrain_modifying )
    set terrainModifyWorking = true
    call StopEnabledCheckTerrainTriggers()
endfunction 








function InitTrig_Save_load_terrain_without_name takes nothing returns nothing
endfunction


endlibrary//===========================================================================
// Trigger: Save load terrain with name
//===========================================================================
//TESH.scrollpos=30
//TESH.alwaysfold=0
library SaveLoadTerrainWithName needs AllTerrainFunctions, TerrainModifyingTrig


globals
    private integer saveNameInt
    private hashtable terrainSaves = InitHashtable()
    private integer terrainSave_id
endglobals



    //save terrain
    

private function SaveTerrain_Actions takes nothing returns nothing
    local real x = MAP_MIN_X
    loop
        exitwhen (x > MAP_MAX_X)
        //call Text_A("avant")
            call SaveInteger(terrainSaves, saveNameInt, terrainSave_id, integer(udg_terrainTypes.getTerrainType(x, y)))
        //call Text_A("après")
            set terrainSave_id = terrainSave_id + 1
        set x = x + LARGEUR_CASE
    endloop
    
    set y = y + LARGEUR_CASE
    if (y > MAP_MAX_Y) then
        set terrainModifyWorking = false
        call DisableTrigger(GetTriggeringTrigger())
        call Text_mkA("Terrain saved")
        return
    endif
endfunction


function SaveTerrainWithName takes string saveName returns nothing
    if (terrainModifyWorking) then
        call Text_erA("can't execute two commands of this type simultaneously !")
        return
    endif
    set saveNameInt = StringHash(saveName)
    call TriggerClearActions(gg_trg_Terrain_modifying)
    call TriggerAddAction(gg_trg_Terrain_modifying, function SaveTerrain_Actions)
    set terrainSave_id = 0
    set y = MAP_MIN_Y
    call EnableTrigger(gg_trg_Terrain_modifying)
    set terrainModifyWorking = true
endfunction


function DeleteTerrainSaveWithName takes string saveName returns boolean
    if (terrainModifyWorking) then
        call Text_erA("can't execute two commands of this type simultaneously !")
        return false
    endif
    set saveNameInt = StringHash(saveName)
    if (not HaveSavedInteger(terrainSaves, saveNameInt, 0)) then
        return false
    endif
    call FlushChildHashtable(terrainSaves, saveNameInt)
    return true
endfunction
    






    //load terrain
    
    
    
    
private function LoadTerrain_Actions takes nothing returns nothing
    local TerrainType terrainType
    local real x
    //local integer i = 1
    //loop
        //exitwhen (i > TERRAIN_MODIFYING_NB_LINES_TO_DO)
            set x = MAP_MIN_X
            loop
                exitwhen (x > MAP_MAX_X)
                    set terrainType = TerrainType(LoadInteger(terrainSaves, saveNameInt, terrainSave_id))
                    if (terrainType != 0) then
                        call ChangeTerrainType(x, y, terrainType.getTerrainTypeId())
                    endif
                    set terrainSave_id = terrainSave_id + 1
                set x = x + LARGEUR_CASE
            endloop
            set y = y + LARGEUR_CASE
            if (y > MAP_MAX_Y) then
                call RestartEnabledCheckTerrainTriggers()
                call Text_mkA("Terrain loaded")
                call DisableTrigger(GetTriggeringTrigger())
                set terrainModifyWorking = false
                return
            endif
        //set i = i + 1
    //endloop
endfunction



function LoadTerrainWithName takes string saveName returns boolean
    if (terrainModifyWorking) then
        call Text_erA("can't execute two commands of this type simultaneously !")
        return true
    endif
    set saveNameInt = StringHash(saveName)
    if (not HaveSavedInteger(terrainSaves, saveNameInt, 0)) then
        return false
    endif
    call TriggerClearActions(gg_trg_Terrain_modifying)
    call TriggerAddAction(gg_trg_Terrain_modifying, function LoadTerrain_Actions)
    set terrainSave_id = 0
    set y = MAP_MIN_Y
    call EnableTrigger(gg_trg_Terrain_modifying)
    set terrainModifyWorking = true
    call StopEnabledCheckTerrainTriggers()
    return true
endfunction 




function InitTrig_Save_load_terrain_with_name takes nothing returns nothing
endfunction


endlibrary//===========================================================================
// Trigger: struct StringArrayForCache
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library StringArrayForCache needs Text


globals    
    constant string CACHE_SEPARATEUR_ITEM = "("
    constant string CACHE_SEPARATEUR_PARAM = ","
    
    private constant integer MAX_STRING_LENGTH = 200
    StringArrayForCache stringArrayForCache = 0
endglobals


struct StringArrayForCache [8000]
    private string array stringArray [8000]
    private integer lastStringId
    private string category
    private string variableName
    private boolean avecSeparateur
    
    static method create takes string category, string variableName, boolean avecSeparateur returns StringArrayForCache
        local StringArrayForCache sa
        if (stringArrayForCache != 0) then
            call stringArrayForCache.destroy()
        endif
        set sa = StringArrayForCache.allocate()
        set sa.lastStringId = -1
        set sa.category = category
        set sa.variableName = variableName
        set sa.avecSeparateur = avecSeparateur
        return sa
    endmethod
    
    private method nextString takes nothing returns nothing
        set .lastStringId = .lastStringId + 1
        set .stringArray[.lastStringId] = ""
    endmethod
    
    method push takes string str returns nothing
        local integer length
        local integer nbCharsDispoForCurrentString
        if (.lastStringId == -1) then
            call .nextString()
        else
            if (StringLength(.stringArray[.lastStringId]) == MAX_STRING_LENGTH) then
                call .nextString()
            endif
            if (.avecSeparateur) then
                set .stringArray[.lastStringId] = .stringArray[.lastStringId] + CACHE_SEPARATEUR_ITEM
            endif
        endif
        set nbCharsDispoForCurrentString = MAX_STRING_LENGTH - StringLength(.stringArray[.lastStringId])
        set length = StringLength(str)
        loop
            exitwhen (length == 0)
                if (length > nbCharsDispoForCurrentString) then
                    set .stringArray[.lastStringId] = .stringArray[.lastStringId] + SubStringBJ(str, 1, nbCharsDispoForCurrentString)
                    call .nextString()
                    set str = SubStringBJ(str, nbCharsDispoForCurrentString + 1, length)
                else
                    set .stringArray[.lastStringId] = .stringArray[.lastStringId] + str
                    set str = ""
                endif
                set nbCharsDispoForCurrentString = MAX_STRING_LENGTH - StringLength(.stringArray[.lastStringId])
            set length = StringLength(str)
        endloop
    endmethod
    
    method writeInCache takes nothing returns nothing
        local integer i
        if (.lastStringId > 0) then
            set i = 0
            loop
                exitwhen (i > .lastStringId)
                    call StoreString(saveMap_cache, .category, .variableName + I2S(i), .stringArray[i])
                    //call Text_A(I2S(i) + " : " + .stringArray[i])
                    //call Text_A("longueur chaîne : " + I2S(StringLength(.stringArray[i])))
                set i = i + 1
            endloop
        else
            if (.lastStringId == 0) then
                call StoreString(saveMap_cache, .category, .variableName, .stringArray[0])
                call Text_A(.stringArray[0])
                call Text_A("longueur chaîne : " + I2S(StringLength(.stringArray[0])))
            endif
        endif
        call Text_A(.category + ", " + .variableName + " : finish write in cache")
    endmethod
endstruct



endlibrary




//===========================================================================
function InitTrig_struct_StringArrayForCache takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: Save terrain config
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library SaveTerrainConfigInCache needs Text




function SaveTerrainConfig takes nothing returns nothing
    call udg_terrainTypes.saveInCache()
    call Text_A("terrain configuration saved")
endfunction






endlibrary


//===========================================================================
function InitTrig_Save_terrain_config takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: Save terrain
//===========================================================================
//TESH.scrollpos=60
//TESH.alwaysfold=0
library SaveTerrain needs Text, SaveMonsterTypes


globals
    private real y
    private integer array terrainTypeIds //16 au max
    private integer nbTerrainTypesUsed
endglobals


private function SaveTerrainsUsed takes nothing returns nothing
    local integer i
    set stringArrayForCache = StringArrayForCache.create("terrain", "terrainsUsed", false)
    set i = 0
    loop
        exitwhen (i >= nbTerrainTypesUsed)
            call stringArrayForCache.push(Ascii2String(terrainTypeIds[i]))
        set i = i + 1
    endloop
    call stringArrayForCache.writeInCache()
    call Text_A("terrains used saved")
endfunction

private function SaveMapDimensions takes nothing returns nothing
    local integer largeurMap = R2I((MAP_MAX_X - MAP_MIN_X)/LARGEUR_CASE)
    local integer hauteurMap = R2I((MAP_MAX_Y - MAP_MIN_Y)/LARGEUR_CASE)
    set stringArrayForCache = StringArrayForCache.create("terrain", "largeur", false)
    call stringArrayForCache.push(I2S(largeurMap))
    call stringArrayForCache.writeInCache()
    set stringArrayForCache = StringArrayForCache.create("terrain", "hauteur", false)
    call stringArrayForCache.push(I2S(hauteurMap))
    call stringArrayForCache.writeInCache()
    call Text_A("map dimensions saved")
endfunction


private function I2HexaString takes integer n returns string
    if (n < 10) then
        return I2S(n)
    endif
    if (n == 10) then
        return "A"
    endif
    if (n == 11) then
        return "B"
    endif
    if (n == 12) then
        return "C"
    endif
    if (n == 13) then
        return "D"
    endif
    if (n == 14) then
        return "E"
    endif
    if (n == 15) then
        return "F"
    endif
    return "0"
endfunction

//crée si besoin une nouvelle instance dans le tableau et retourne l'id de cet élément de tableau
private function GetTerrainId takes real x, real y returns string
    local integer terrainTypeId = GetTerrainType(x, y)
    local integer i = 0
    loop
        exitwhen (i >= nbTerrainTypesUsed)
            if (terrainTypeId == terrainTypeIds[i]) then
                return I2S(i)
            endif
        set i = i + 1
    endloop
    set terrainTypeIds[nbTerrainTypesUsed] = terrainTypeId
    set nbTerrainTypesUsed = nbTerrainTypesUsed + 1
    return I2HexaString(nbTerrainTypesUsed - 1)
endfunction


private function SaveTerrain_Actions takes nothing returns nothing
    local real x
    if (y <= MAP_MAX_Y) then
        set x = MAP_MIN_X
        loop
            exitwhen (x > MAP_MAX_X)
                call stringArrayForCache.push(GetTerrainId(x, y))
            set x = x + LARGEUR_CASE
        endloop
        set y = y + LARGEUR_CASE
    else
        call DisableTrigger(GetTriggeringTrigger())
        call stringArrayForCache.writeInCache()
        call Text_A("terrain saved")
        call SaveTerrainsUsed()
        call SaveMapDimensions()
        call StartSaveMonsterTypes()
    endif
endfunction


function StartSaveTerrain takes nothing returns nothing
    set y = MAP_MIN_Y
    set nbTerrainTypesUsed = 0
    set stringArrayForCache = StringArrayForCache.create("terrain", "terrain", false)
    call TriggerClearActions(trigSaveMapInCache)
    call TriggerAddAction(trigSaveMapInCache, function SaveTerrain_Actions)
    call EnableTrigger(trigSaveMapInCache)
endfunction






endlibrary


//===========================================================================
function InitTrig_Save_terrain takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: Save monster types
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library SaveMonsterTypes needs Text, SaveLevels



function StartSaveMonsterTypes takes nothing returns nothing
    call udg_monsterTypes.saveInCache()
    call Text_A("monster types saved")
    call StartSaveLevels()
endfunction



endlibrary



//===========================================================================
function InitTrig_Save_monster_types takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: Save levels
//===========================================================================
//TESH.scrollpos=45
//TESH.alwaysfold=0
library SaveLevels needs Text

globals
    private integer levelId
    private Level level
    private integer visibilityId
    private integer monsterNoMoveId
    private integer monsterSimplePatrolId
    private integer monsterMultiplePatrolsId
    private integer meteorId
    private integer monsterSpawnId
    private constant integer NB_ITEM_TO_SAVE_EACH_TIME = 10
    private StartSaveNexLevel startSaveNexLevel
endglobals



//monsterSpawns
private function SaveMonsterSpawns_Actions takes nothing returns nothing
    local integer i = 0
    loop
        exitwhen (i >= NB_ITEM_TO_SAVE_EACH_TIME)
            if (monsterSpawnId > level.monsterSpawns.getLastInstanceId()) then
                call stringArrayForCache.writeInCache()
                call DisableTrigger(GetTriggeringTrigger())
                call startSaveNexLevel.go()
                return
            endif
            if (level.monsterSpawns.get(monsterSpawnId) != 0) then
                call stringArrayForCache.push(level.monsterSpawns.get(monsterSpawnId).toString())
            endif
            set monsterSpawnId = monsterSpawnId + 1
        set i = i + 1
    endloop
endfunction

private function StartSaveMonsterSpawns takes nothing returns nothing
    if (level.monsterSpawns.count() == 0) then
        call startSaveNexLevel.go()
    else
        set stringArrayForCache = StringArrayForCache.create("level" + I2S(levelId), "monsterSpawns", true)
        call TriggerClearActions(trigSaveMapInCache)
        call TriggerAddAction(trigSaveMapInCache, function SaveMonsterSpawns_Actions)
        call EnableTrigger(trigSaveMapInCache)
        set monsterSpawnId = 0
    endif
endfunction
///////////////////////////

//meteors
private function SaveMeteors_Actions takes nothing returns nothing
    local integer i = 0
    loop
        exitwhen (i >= NB_ITEM_TO_SAVE_EACH_TIME)
            if (meteorId > level.meteors.getLastInstanceId()) then
                call stringArrayForCache.writeInCache()
                call DisableTrigger(GetTriggeringTrigger())
                call StartSaveMonsterSpawns()
                return
            endif
            if (level.meteors.get(meteorId) != 0) then
                call stringArrayForCache.push(level.meteors.get(meteorId).toString())
            endif
            set meteorId = meteorId + 1
        set i = i + 1
    endloop
endfunction

private function StartSaveMeteors takes nothing returns nothing
    if (level.meteors.count() == 0) then
        call StartSaveMonsterSpawns()
    else
        set stringArrayForCache = StringArrayForCache.create("level" + I2S(levelId), "meteors", true)
        call TriggerClearActions(trigSaveMapInCache)
        call TriggerAddAction(trigSaveMapInCache, function SaveMeteors_Actions)
        call EnableTrigger(trigSaveMapInCache)
        set meteorId = 0
    endif
endfunction
///////////////////////////

//monsters multiple patrols
private function SaveMonstersMultiplePatrols_Actions takes nothing returns nothing
    local integer i = 0
    loop
        exitwhen (i >= NB_ITEM_TO_SAVE_EACH_TIME)
            if (monsterMultiplePatrolsId > level.monstersMultiplePatrols.getLastInstanceId()) then
                call stringArrayForCache.writeInCache()
                call DisableTrigger(GetTriggeringTrigger())
                call StartSaveMeteors()
                return
            endif
            if (level.monstersMultiplePatrols.get(monsterMultiplePatrolsId) != 0) then
                call stringArrayForCache.push(level.monstersMultiplePatrols.get(monsterMultiplePatrolsId).toString())
            endif
            set monsterMultiplePatrolsId = monsterMultiplePatrolsId + 1
        set i = i + 1
    endloop
endfunction

private function StartSaveMonstersMultiplePatrols takes nothing returns nothing
    if (level.monstersMultiplePatrols.count() == 0) then
        call StartSaveMeteors()
    else
        set stringArrayForCache = StringArrayForCache.create("level" + I2S(levelId), "monstersMultiplePatrols", true)
        call TriggerClearActions(trigSaveMapInCache)
        call TriggerAddAction(trigSaveMapInCache, function SaveMonstersMultiplePatrols_Actions)
        call EnableTrigger(trigSaveMapInCache)
        set monsterMultiplePatrolsId = 0
    endif
endfunction
///////////////////////////

//monsters simple patrol
private function SaveMonstersSimplePatrol_Actions takes nothing returns nothing
    local integer i = 0
    loop
        exitwhen (i >= NB_ITEM_TO_SAVE_EACH_TIME)
            if (monsterSimplePatrolId > level.monstersSimplePatrol.getLastInstanceId()) then
                call stringArrayForCache.writeInCache()
                call DisableTrigger(GetTriggeringTrigger())
                call StartSaveMonstersMultiplePatrols()
                return
            endif
            if (level.monstersSimplePatrol.get(monsterSimplePatrolId) != 0) then
                call stringArrayForCache.push(level.monstersSimplePatrol.get(monsterSimplePatrolId).toString())
            endif
            set monsterSimplePatrolId = monsterSimplePatrolId + 1
        set i = i + 1
    endloop
endfunction

private function StartSaveMonstersSimplePatrol takes nothing returns nothing
    if (level.monstersSimplePatrol.count() == 0) then
        call StartSaveMonstersMultiplePatrols()
    else
        set stringArrayForCache = StringArrayForCache.create("level" + I2S(levelId), "monstersSimplePatrol", true)
        call TriggerClearActions(trigSaveMapInCache)
        call TriggerAddAction(trigSaveMapInCache, function SaveMonstersSimplePatrol_Actions)
        call EnableTrigger(trigSaveMapInCache)
        set monsterSimplePatrolId = 0
    endif
endfunction
///////////////////////////

//monsters no move
private function SaveMonstersNoMove_Actions takes nothing returns nothing
    local integer i = 0
    loop
        exitwhen (i >= NB_ITEM_TO_SAVE_EACH_TIME)
            if (monsterNoMoveId > level.monstersNoMove.getLastInstanceId()) then
                call stringArrayForCache.writeInCache()
                call DisableTrigger(GetTriggeringTrigger())
                call StartSaveMonstersSimplePatrol()
                return
            endif
            if (level.monstersNoMove.get(monsterNoMoveId) != 0) then
                call stringArrayForCache.push(level.monstersNoMove.get(monsterNoMoveId).toString())
            endif
            set monsterNoMoveId = monsterNoMoveId + 1
        set i = i + 1
    endloop
endfunction

private function StartSaveMonstersNoMove takes nothing returns nothing
    if (level.monstersNoMove.count() == 0) then
        call StartSaveMonstersSimplePatrol()
    else
        set stringArrayForCache = StringArrayForCache.create("level" + I2S(levelId), "monstersNoMove", true)
        call TriggerClearActions(trigSaveMapInCache)
        call TriggerAddAction(trigSaveMapInCache, function SaveMonstersNoMove_Actions)
        call EnableTrigger(trigSaveMapInCache)
        set monsterNoMoveId = 0
    endif
endfunction
///////////////////////////

//visibilities
private function SaveVisibilities_Actions takes nothing returns nothing
    local integer i = 0
    loop
        exitwhen (i >= NB_ITEM_TO_SAVE_EACH_TIME)
            if (visibilityId > level.visibilities.getLastInstanceId()) then
                call stringArrayForCache.writeInCache()
                call DisableTrigger(GetTriggeringTrigger())
                call StartSaveMonstersNoMove()
                return
            endif
            if (level.visibilities.get(visibilityId) != 0) then
                call stringArrayForCache.push(level.visibilities.get(visibilityId).toString())
            endif
            set visibilityId = visibilityId + 1
        set i = i + 1
    endloop
endfunction

private function StartSaveVisibilities takes nothing returns nothing
    if (level.visibilities.count() == 0) then
        call StartSaveMonstersNoMove()
    else
        set stringArrayForCache = StringArrayForCache.create("level" + I2S(levelId), "visibilities", true)
        call TriggerClearActions(trigSaveMapInCache)
        call TriggerAddAction(trigSaveMapInCache, function SaveVisibilities_Actions)
        call EnableTrigger(trigSaveMapInCache)
        set visibilityId = 0
    endif
endfunction
///////////////////////////




private function EndSaveLevel takes nothing returns nothing
    call Text_A("all levels saved")
    call SaveGameCache(saveMap_cache)
    call Text_A("SAVING MAP FINISHED")
endfunction

private function StartSaveLevel takes nothing returns nothing
    set level = udg_levels.get(levelId)
    if (level == 0) then
        call EndSaveLevel()
    else
        //start message
        if (level.getStartMessage() != null and level.getStartMessage() != "") then
            set stringArrayForCache = StringArrayForCache.create("level" + I2S(levelId), "startMessage", false)
            call stringArrayForCache.push(level.getStartMessage())
            call stringArrayForCache.writeInCache()
        endif
        //nb lives earned
        set stringArrayForCache = StringArrayForCache.create("level" + I2S(levelId), "nbLives", false)
        call stringArrayForCache.push(I2S(level.getNbLives()))
        call stringArrayForCache.writeInCache()
        //start
        if (level.getStart() != 0) then
            set stringArrayForCache = StringArrayForCache.create("level" + I2S(levelId), "start", false)
            call stringArrayForCache.push(level.getStart().toString())
            call stringArrayForCache.writeInCache()
        endif
        //end
        if (level.getEnd() != 0) then
            set stringArrayForCache = StringArrayForCache.create("level" + I2S(levelId), "end", false)
            call stringArrayForCache.push(level.getEnd().toString())
            call stringArrayForCache.writeInCache()
        endif
        //reste :      //visibilities  
        //monstersNoMove  //monstersSimplePatrol  //monstersMultiplePatrols  //meteors  //monsterSpawns
        call StartSaveVisibilities()        
    endif
endfunction

function StartSaveLevels takes nothing returns nothing
    local integer i = 0
    loop
        exitwhen (i > 11)
            if (udg_escapers.get(i) != 0) then
                call udg_escapers.get(i).destroyMake()
                call udg_escapers.get(i).destroyAllSavedActions()
            endif
        set i = i + 1
    endloop
    set levelId = 0
    call StartSaveLevel()
endfunction


struct StartSaveNexLevel
    method go takes nothing returns nothing
        set levelId = levelId + 1
        call StartSaveLevel()
    endmethod
endstruct



//===========================================================================
function InitTrig_Save_levels takes nothing returns nothing
    set startSaveNexLevel = StartSaveNexLevel.create()
endfunction


endlibrary
//===========================================================================
// Trigger: SAVE MAP in cache
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library SaveMapInCache needs SaveTerrainConfigInCache, SaveTerrain




globals
    gamecache saveMap_cache
    trigger trigSaveMapInCache
endglobals



function StartSaveMapInCache takes nothing returns nothing
    local integer i
    call Text_A("starting saving map in gamecache \"epicSlide\"...")
    call FlushStoredMission(saveMap_cache, "terrain")
    call FlushStoredMission(saveMap_cache, "monsterTypes")
    set i = 0
    loop
        exitwhen (i >= NB_MAX_LEVELS)
            call FlushStoredMission(saveMap_cache, "level" + I2S(i))
        set i = i + 1
    endloop
    call SaveTerrainConfig()
    call StartSaveTerrain()
endfunction




//===========================================================================
function InitTrig_SAVE_MAP_in_cache takes nothing returns nothing
    set saveMap_cache = InitGameCache("epicSlide")
    set trigSaveMapInCache = CreateTrigger()
    call DisableTrigger(trigSaveMapInCache)
    call TriggerRegisterTimerEvent(trigSaveMapInCache, LOW_PERIOD_FOR_WORK, true)
endfunction



endlibrary//===========================================================================
// Trigger: Init lives
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
globals
    Lives udg_lives = 0
endglobals


function Trig_init_lives_Actions takes nothing returns nothing
    set udg_lives = Lives.create()
endfunction



//===========================================================================
function InitTrig_Init_lives takes nothing returns nothing
    set gg_trg_Init_lives = CreateTrigger()
    call TriggerAddAction(gg_trg_Init_lives, function Trig_init_lives_Actions)
    call TriggerRegisterTimerEvent(gg_trg_Init_lives, 0.0001, false)
endfunction

//===========================================================================
// Trigger: Init escapers
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
globals
    EscaperArray udg_escapers = 0
endglobals




//===========================================================================
function InitTrig_Init_escapers takes nothing returns nothing
    set udg_escapers = EscaperArray.create()
endfunction

//===========================================================================
// Trigger: Init terrain types
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
globals
	TerrainTypeArray udg_terrainTypes = 0
endglobals


function InitTrig_Init_terrain_types takes nothing returns nothing
	if (udg_terrainTypes == 0) then
		set udg_terrainTypes = TerrainTypeArray.create()
		call udg_terrainTypes.newSlide("slide", 'Nice', 550).setAlias("s")
		call udg_terrainTypes.newSlide("slideLent", 'Nsnw', 300).setAlias("sl")
		call udg_terrainTypes.newSlide("slideRapide", 'Idki', 850).setAlias("sr")
		call udg_terrainTypes.newWalk("walk", 'cQc1', 522).setAlias("w")
		call udg_terrainTypes.newDeath("death", 'Arck', "Abilities\\Spells\\Orc\\Ensnare\\ensnareTarget.mdl", 2.000).setAlias("d")
	endif
endfunction//===========================================================================
// Trigger: Init monster types
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
globals
	MonsterTypeArray udg_monsterTypes = 0
endglobals


function InitTrig_Init_monster_types takes nothing returns nothing
	if (udg_monsterTypes == 0) then
		set udg_monsterTypes = MonsterTypeArray.create()
		call udg_monsterTypes.new("crabe", 'nscb', 1.000, 50, 400.000, false).setAlias("c").setKillingEffectStr("Abilities\\Spells\\NightElf\\FanOfKnives\\FanOfKnivesCaster.mdl")
		call udg_monsterTypes.new("ogre", 'nogn', 1.000, 85, 400.000, false).setAlias("o").setKillingEffectStr("Abilities\\Spells\\Undead\\FrostNova\\FrostNovaTarget.mdl")
		call udg_monsterTypes.new("geant", 'emtg', 1.000, 105, 225.000, false).setAlias("g").setKillingEffectStr("Abilities\\Spells\\Orc\\WarStomp\\WarStompCaster.mdl")
		call udg_monsterTypes.new("indomptable", 'nowk', 3.000, 200, 400.000, true).setNbMeteorsToKill(3)
		call udg_monsterTypes.new("ancien", 'nsqa', 2.500, 150, 400.000, true)
	endif
endfunction//===========================================================================
// Trigger: Init struct levels
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
globals
    LevelArray udg_levels = 0
endglobals

//===========================================================================
function InitTrig_Init_struct_levels takes nothing returns nothing
    if (udg_levels == 0) then
        set udg_levels = LevelArray.create()
    endif
endfunction

//===========================================================================
// Trigger: Init levels
//===========================================================================
//TESH.scrollpos=1214
//TESH.alwaysfold=0
function Init_level0_Actions takes nothing returns nothing
	local Level level = ForceGetLevel(0)

//start message

//lives earned
	call level.setNbLivesEarned(5)

//start location
	call level.newStart(-10656, 10176, -10208, 10624)

//end location
	call level.newEnd(-5150, 9705, -5081, 10778)

//visibilities
	call level.newVisibilityModifier(-4979, 9513, -11943, 11968)
	call level.newVisibilityModifier(-6318, 8998, -11995, 9588)
	call level.newVisibilityModifier(-6483, 8921, -5656, 9577)

//monsters no move

//monsters simple patrol
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -8864, 10610, -8864, 9997, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -8119, 9997, -8119, 10610, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), -8468, 9996, -8468, 10609, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -9385, 9868, -9385, 10737, false)

//monsters multiple patrols

//monster spawns

//meteors

	call level.activate(true)
endfunction


function Init_level1_Actions takes nothing returns nothing
	local Level level = ForceGetLevel(1)

//start message

//lives earned

//start location
	call level.newStart(-5087, 9877, -4476, 10603)

//end location
	call level.newEnd(-8857, 4803, -7791, 4958)

//visibilities
	call level.newVisibilityModifier(-5305, 11186, -2699, 8052)
	call level.newVisibilityModifier(-2797, 11188, -2327, 7923)
	call level.newVisibilityModifier(-11456, 9275, -3613, 6837)
	call level.newVisibilityModifier(-5662, 9505, -5319, 9212)
	call level.newVisibilityModifier(-9910, 7207, -6345, 5737)
	call level.newVisibilityModifier(-9442, 5865, -6902, 4609)

//monsters no move
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), -4164, 8931, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), -3258, 9389, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), -4699, 7817, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), -7544, 7346, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), -7795, 7061, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), -8933, 6896, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), -8315, 5379, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), -9208, 6908, -1, false)

//monsters simple patrol
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -3201, 10253, -3201, 10738, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), -3781, 8461, -3781, 8946, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -4269, 9923, -3895, 10297, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), -6555, 6931, -6884, 7248, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -3058, 9925, -2701, 9925, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), -8050, 8333, -7437, 8333, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -4521, 8972, -4521, 9585, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), -8691, 5191, -7950, 5191, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -4879, 8845, -5188, 9269, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -2958, 9218, -3571, 9218, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -4995, 7564, -4995, 8049, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -5554, 6925, -5554, 7538, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -5829, 6925, -5829, 7538, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -7795, 7804, -7054, 7804, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -8846, 7457, -9331, 7457, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -8973, 6229, -9330, 6229, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -8756, 5517, -8756, 6002, false)

//monsters multiple patrols

//monster spawns

//meteors

endfunction


function Init_level2_Actions takes nothing returns nothing
	local Level level = ForceGetLevel(2)

//start message

//lives earned

//start location
	call level.newStart(-8624, 4335, -8001, 4871)

//end location
	call level.newEnd(-11416, 970, -10355, 1153)

//visibilities
	call level.newVisibilityModifier(-11576, 6996, -6871, 1320)
	call level.newVisibilityModifier(-11698, 1476, -9827, 788)

//monsters no move
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), -9987, 4376, -1, false)

//monsters simple patrol
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -9583, 3534, -8086, 3505, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -9596, 3266, -8099, 3275, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -9583, 2951, -8094, 2951, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -9582, 2653, -8083, 2656, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -9997, 2448, -10354, 2448, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -9998, 3200, -10355, 3200, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -9870, 3977, -10227, 3977, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -10994, 3357, -10509, 3357, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -10510, 3645, -10995, 3645, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -10230, 4734, -10710, 5220, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -10638, 2812, -10995, 2812, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -9581, 3824, -8082, 3828, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -10637, 1557, -11122, 1557, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -10765, 2430, -11250, 2430, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -8084, 3698, -9592, 3684, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -8087, 3430, -9586, 3383, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -8087, 3177, -9580, 3139, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -8083, 2865, -9581, 2809, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), -10254, 4424, -10739, 4424, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), -10766, 1922, -11123, 1922, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -8081, 2549, -9578, 2532, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), -8563, 3818, -8078, 3818, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), -8589, 2877, -9074, 2877, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), -9101, 3302, -9586, 3302, false)

//monsters multiple patrols

//monster spawns

//meteors

endfunction


function Init_level3_Actions takes nothing returns nothing
	local Level level = ForceGetLevel(3)

//start message

//lives earned

//start location
	call level.newStart(-11237, 541, -10532, 1225)

//end location
	call level.newEnd(-10815, -6979, -9648, -6892)

//visibilities
	call level.newVisibilityModifier(-11721, 1319, -7746, -3373)
	call level.newVisibilityModifier(-9034, -3226, -11776, -6344)
	call level.newVisibilityModifier(-11886, -6324, -9494, -7880)

//monsters no move
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), -10602, -3385, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), -10706, -1200, -1, false)

//monsters simple patrol
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -10619, -127, -11122, -109, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -10637, -595, -11122, -595, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -9230, -318, -9715, -318, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -9714, -671, -9229, -671, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -9229, -1019, -9714, -1019, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), -8562, -1738, -8077, -1738, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), -8078, -2105, -8563, -2105, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -10604, -2190, -10604, -2803, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -10893, -3161, -11250, -3161, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -9362, -1934, -9362, -3059, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -9068, -3059, -9068, -1934, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -10099, -1934, -10099, -3059, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), -9731, -3043, -9721, -1972, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), -9547, -3008, -9548, -1978, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -9773, -243, -9773, 241, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -10766, -2854, -11251, -2854, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), -9949, -3043, -9945, -1953, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -10485, -6523, -9995, -6532, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -10481, -2802, -10481, -2189, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -10444, -1038, -10444, -1523, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -9742, -395, -10483, -395, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -9729, -896, -10479, -912, false)

//monsters multiple patrols

//monster spawns
	call level.monsterSpawns.new("crabe1", udg_monsterTypes.get("c"), "leftToRight", 1.800, -11439, -6057, -9377, -4539, false)
	call level.monsterSpawns.new("crabe2", udg_monsterTypes.get("c"), "rightToLeft", 1.800, -11078, -6075, -9067, -4557, false)

//meteors

endfunction


function Init_level4_Actions takes nothing returns nothing
	local Level level = ForceGetLevel(4)

//start message

//lives earned
	call level.setNbLivesEarned(2)

//start location
	call level.newStart(-10613, -7534, -9875, -6806)

//end location
	call level.newEnd(-3419, 5622, -3307, 6855)

//visibilities
	call level.newVisibilityModifier(-9743, -7936, -8401, -5489)
	call level.newVisibilityModifier(-9290, -3252, -7810, -7145)
	call level.newVisibilityModifier(-8063, -6512, -7136, -5339)
	call level.newVisibilityModifier(-8032, -5559, -6393, -3144)
	call level.newVisibilityModifier(-8437, -4125, -4733, 7134)
	call level.newVisibilityModifier(-2268, 3609, -5289, -1255)
	call level.newVisibilityModifier(-3295, 3340, -5042, 8364)

//monsters no move
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), -7734, -4994, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), -7484, -5152, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), -7306, -4673, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), -7618, -4514, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), -5531, -1944, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), -5788, -2091, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), -6271, -1746, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), -6421, -2116, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), -6343, -3042, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), -5795, -2974, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), -5459, -3125, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), -6118, -3453, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), -4468, -641, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), -4159, -650, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), -4574, 6125, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), -5548, -2468, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), -6204, -2578, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), -6259, 107, 0, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), -6388, 89, 180, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), -3989, 2550, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), -5455, 3504, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), -4758, 4462, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), -4445, 4339, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), -3603, 23, -45, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), -3779, 198, 135, false)

//monsters simple patrol
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -6040, 909, -6040, 1394, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -5111, -2965, -6776, -2187, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -6782, -2727, -5104, -2060, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -5748, -3709, -6778, -2940, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -6771, -1757, -5119, -2174, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -5111, -1886, -6780, -2828, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), -9595, -7411, -9595, -6926, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), -9000, -6541, -9000, -7026, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), -8727, -6542, -8727, -7027, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), -8205, -6221, -8690, -6221, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), -8109, -6131, -8109, -5518, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), -7039, -4466, -7039, -3853, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), -6541, -3746, -7026, -3746, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -5261, 3390, -5874, 3390, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -6029, 307, -6642, 307, false)
endfunction

function Init_level4_part2_Actions takes nothing returns nothing
	local Level level = ForceGetLevel(4)


//monsters simple patrol
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -6030, -80, -6643, -80, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -5658, -3699, -5129, -2833, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -5123, -2233, -6773, -1947, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -6758, -1854, -5117, -1663, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -5985, 397, -5985, 754, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -6764, -2340, -5128, -2311, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -5687, 652, -5687, 1265, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -5262, 502, -5619, 502, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -5158, -2664, -6772, -3200, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -5085, 369, -5085, -115, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -4978, -399, -4621, -399, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -4321, -397, -4321, -882, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -5165, -3682, -6743, -2607, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -3598, -115, -4083, -115, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -2958, 810, -3827, 810, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -3215, 1165, -3215, 1650, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -3567, 668, -3208, 1017, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -2930, 2253, -2445, 2253, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -3039, 2317, -3039, 2802, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -3425, 2700, -3425, 3441, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -3538, 2701, -3538, 3442, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -3705, 3441, -3705, 2700, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -4141, 2674, -4141, 2189, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), -4514, 2316, -4514, 2929, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), -4758, 2930, -4758, 2317, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), -4946, 2317, -4946, 2930, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), -5195, 2930, -5195, 2317, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -5517, 4221, -5874, 4221, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -5082, 4594, -5082, 4109, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -4595, 5352, -4238, 5352, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), -4723, 4770, -4238, 4770, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), -7181, -5001, -7918, -4714, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), -5747, -1106, -5262, -1106, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), -6029, -1102, -6514, -1102, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), -6509, -1462, -5270, -1475, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -4595, 5156, -4238, 5156, false)

//monsters multiple patrols

//monster spawns

//meteors

endfunction


function Init_level5_Actions takes nothing returns nothing
	local Level level = ForceGetLevel(5)

//start message

//lives earned
	call level.setNbLivesEarned(2)

//start location
	call level.newStart(-3543, 5919, -2827, 6641)

//end location
	call level.newEnd(5139, 8499, 5293, 9428)

//visibilities
	call level.newVisibilityModifier(3220, 5335, -5973, 12018)
	call level.newVisibilityModifier(-3660, 5465, 879, 2088)
	call level.newVisibilityModifier(455, 3553, 4132, 5843)
	call level.newVisibilityModifier(3947, 4383, 5628, 5882)
	call level.newVisibilityModifier(5873, 8030, -432, 12051)

//monsters no move
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 2216, 6036, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 2498, 6124, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 1833, 6287, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 3308, 4497, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 3959, 5305, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), -468, 4712, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 451, 2970, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), -550, 5449, 0, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), -323, 5462, 180, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), -2290, 6275, 180, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), -1919, 6644, -135, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), -2658, 5920, 45, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), -1929, 5915, 135, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), -2659, 6620, -45, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 822, 6382, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 355, 6136, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), -17, 6408, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("indomptable"), 4927, 8966, 180, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 1878, 8623, 0, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 1798, 8690, 90, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 1711, 8591, 180, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 1800, 8511, 270, false)

//monsters simple patrol
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 2060, 6636, 2914, 6081, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 2749, 6583, 2174, 5919, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 1960, 6004, 2437, 6801, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 2914, 6369, 2441, 5778, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 2408, 6731, 2911, 6279, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 2445, 5275, 3058, 5275, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 2444, 5093, 3057, 5093, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -1021, 9494, -1337, 10050, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -1614, 3469, -1614, 3826, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 2102, 4183, 2436, 3782, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), -656, 4239, -618, 3052, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 3084, 4657, 4337, 4657, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 3385, 4849, 3385, 3980, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 2701, 4036, 3442, 4036, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 3724, 5082, 4337, 5082, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 3852, 4859, 4337, 4859, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 4428, 5618, 4428, 5133, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 4699, 5132, 4699, 5617, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -856, 7215, -421, 7608, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -1280, 8058, -1616, 7597, false)
endfunction

function Init_level5_part2_Actions takes nothing returns nothing
	local Level level = ForceGetLevel(5)


//monsters simple patrol
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -1335, 7478, -981, 7993, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -1529, 4471, -1889, 4827, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -1522, 4229, -1882, 3869, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -957, 3853, -957, 4210, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -269, 6752, -626, 6752, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -341, 4209, -341, 3852, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -627, 6868, -270, 6868, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 268, 3854, 625, 3854, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -948, 3085, -948, 3442, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -304, 3442, -304, 3085, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -1293, 8194, -1650, 8194, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 243, 3071, 600, 3425, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 1792, 9245, 2309, 8913, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 1262, 7958, 1766, 7609, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -1528, 9228, -1528, 9713, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -1603, 3442, -1603, 3085, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), -850, 9485, -850, 9970, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), -607, 9485, -607, 9970, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), -327, 9485, -327, 9970, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), 2189, 4800, 2802, 4800, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -1760, 6025, -1453, 6528, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -1453, 6528, -1253, 6022, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -1253, 6022, -967, 6523, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -967, 6523, -758, 6019, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -793, 3468, -793, 3825, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -478, 3825, -478, 3468, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -1268, 3853, -1268, 4210, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -1260, 3826, -1260, 3469, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -1277, 3084, -1277, 3441, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 57, 3442, 57, 3085, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 57, 3469, 57, 3826, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 43, 3853, 43, 4210, false)

//monsters multiple patrols
	call MonsterMultiplePatrols.storeNewLoc(2580, 10008)
	call MonsterMultiplePatrols.storeNewLoc(2698, 9455)
	call MonsterMultiplePatrols.storeNewLoc(2308, 9461)
	call level.monstersMultiplePatrols.new(udg_monsterTypes.get("g"), "normal", false)

	call MonsterMultiplePatrols.storeNewLoc(-1384, 8313)
	call MonsterMultiplePatrols.storeNewLoc(-1947, 8329)
	call MonsterMultiplePatrols.storeNewLoc(-1940, 9090)
	call MonsterMultiplePatrols.storeNewLoc(-1387, 9064)
	call level.monstersMultiplePatrols.new(udg_monsterTypes.get("g"), "normal", false)

	call MonsterMultiplePatrols.storeNewLoc(3132, 8723)
	call MonsterMultiplePatrols.storeNewLoc(3343, 9231)
	call MonsterMultiplePatrols.storeNewLoc(3466, 8707)
	call MonsterMultiplePatrols.storeNewLoc(3628, 9228)
	call MonsterMultiplePatrols.storeNewLoc(3746, 8709)
	call MonsterMultiplePatrols.storeNewLoc(3895, 9224)
	call MonsterMultiplePatrols.storeNewLoc(4013, 8707)
	call MonsterMultiplePatrols.storeNewLoc(4226, 9228)
	call MonsterMultiplePatrols.storeNewLoc(4367, 8701)
	call level.monstersMultiplePatrols.new(udg_monsterTypes.get("c"), "string", false)

	call MonsterMultiplePatrols.storeNewLoc(1658, 7040)
	call MonsterMultiplePatrols.storeNewLoc(1427, 7203)
	call MonsterMultiplePatrols.storeNewLoc(1167, 7056)
	call level.monstersMultiplePatrols.new(udg_monsterTypes.get("c"), "string", false)

	call MonsterMultiplePatrols.storeNewLoc(1667, 6900)
	call MonsterMultiplePatrols.storeNewLoc(1419, 6762)
	call MonsterMultiplePatrols.storeNewLoc(1159, 6900)
	call level.monstersMultiplePatrols.new(udg_monsterTypes.get("c"), "string", false)

	call MonsterMultiplePatrols.storeNewLoc(2058, 8330)
	call MonsterMultiplePatrols.storeNewLoc(1534, 8316)
	call MonsterMultiplePatrols.storeNewLoc(1527, 8827)
	call MonsterMultiplePatrols.storeNewLoc(2064, 8805)
	call level.monstersMultiplePatrols.new(udg_monsterTypes.get("g"), "normal", false)

//monster spawns

//meteors
	call level.meteors.new(-776, 2557, false)
	call level.meteors.new(5191, 5388, false)
	call level.meteors.new(185, 9722, false)

endfunction


function Init_level6_Actions takes nothing returns nothing
	local Level level = ForceGetLevel(6)

//start message

//lives earned
	call level.setNbLivesEarned(2)

//start location
	call level.newStart(5488, 8602, 6138, 9361)

//end location
	call level.newEnd(7176, 2593, 8195, 2682)

//visibilities
	call level.newVisibilityModifier(1413, 5427, 11888, 11617)
	call level.newVisibilityModifier(8660, 5630, 6725, 2679)

//monsters no move
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 10086, 8922, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 9778, 8352, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 10118, 7943, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 9831, 7551, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 10249, 6995, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 9861, 6776, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 9439, 9453, -135, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 9522, 9342, -135, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 9597, 9244, -135, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 9681, 9139, -135, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 9608, 9667, 45, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 9680, 9586, 45, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 9756, 9501, 45, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 9823, 9408, 45, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 9873, 9317, 45, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 10085, 8353, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 10147, 7315, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 5661, 6549, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 6398, 7285, 0, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 5588, 7300, 0, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 5226, 7598, 0, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 4758, 7275, 0, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 6981, 7554, 0, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 7536, 7220, 0, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 7468, 4047, -80, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 7915, 4052, -120, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 4349, 6414, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 6230, 6389, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 5998, 6319, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 4071, 6866, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 4339, 6665, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 4513, 6504, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 4745, 6270, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 5160, 6531, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 5412, 6403, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 5697, 6272, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 5004, 6330, -1, false)

//monsters simple patrol
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 8689, 6469, 8076, 6469, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 6397, 6132, 6689, 6515, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 6864, 6324, 6571, 5950, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 6770, 5782, 7073, 6117, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 7265, 5939, 6930, 5597, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 7097, 5419, 7433, 5781, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 7547, 5637, 7255, 5275, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 7366, 5157, 7710, 5482, false)
endfunction

function Init_level6_part2_Actions takes nothing returns nothing
	local Level level = ForceGetLevel(6)


//monsters simple patrol
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 7431, 5088, 7927, 5269, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 8077, 4720, 7295, 4732, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 7424, 4877, 7938, 4879, false)

//monsters multiple patrols
	call MonsterMultiplePatrols.storeNewLoc(8402, 5529)
	call MonsterMultiplePatrols.storeNewLoc(8726, 6022)
	call MonsterMultiplePatrols.storeNewLoc(8835, 5505)
	call MonsterMultiplePatrols.storeNewLoc(9030, 6024)
	call MonsterMultiplePatrols.storeNewLoc(9156, 5529)
	call MonsterMultiplePatrols.storeNewLoc(9223, 6013)
	call MonsterMultiplePatrols.storeNewLoc(9521, 5524)
	call level.monstersMultiplePatrols.new(udg_monsterTypes.get("c"), "string", false)

	call MonsterMultiplePatrols.storeNewLoc(9522, 5529)
	call MonsterMultiplePatrols.storeNewLoc(9213, 6019)
	call MonsterMultiplePatrols.storeNewLoc(9150, 5527)
	call MonsterMultiplePatrols.storeNewLoc(9045, 6022)
	call MonsterMultiplePatrols.storeNewLoc(8870, 5512)
	call MonsterMultiplePatrols.storeNewLoc(8711, 6017)
	call MonsterMultiplePatrols.storeNewLoc(8397, 5529)
	call level.monstersMultiplePatrols.new(udg_monsterTypes.get("c"), "string", false)

	call MonsterMultiplePatrols.storeNewLoc(9519, 5559)
	call MonsterMultiplePatrols.storeNewLoc(9458, 6159)
	call MonsterMultiplePatrols.storeNewLoc(9836, 5864)
	call MonsterMultiplePatrols.storeNewLoc(9737, 6303)
	call MonsterMultiplePatrols.storeNewLoc(10205, 6254)
	call level.monstersMultiplePatrols.new(udg_monsterTypes.get("c"), "string", false)

	call MonsterMultiplePatrols.storeNewLoc(8076, 6103)
	call MonsterMultiplePatrols.storeNewLoc(8388, 5955)
	call MonsterMultiplePatrols.storeNewLoc(8702, 6118)
	call level.monstersMultiplePatrols.new(udg_monsterTypes.get("c"), "string", false)

	call MonsterMultiplePatrols.storeNewLoc(8694, 6385)
	call MonsterMultiplePatrols.storeNewLoc(8415, 6228)
	call MonsterMultiplePatrols.storeNewLoc(8073, 6371)
	call level.monstersMultiplePatrols.new(udg_monsterTypes.get("c"), "string", false)

	call MonsterMultiplePatrols.storeNewLoc(8079, 6578)
	call MonsterMultiplePatrols.storeNewLoc(8384, 6748)
	call MonsterMultiplePatrols.storeNewLoc(8707, 6590)
	call level.monstersMultiplePatrols.new(udg_monsterTypes.get("c"), "string", false)

	call MonsterMultiplePatrols.storeNewLoc(7681, 3745)
	call MonsterMultiplePatrols.storeNewLoc(8051, 3728)
	call MonsterMultiplePatrols.storeNewLoc(8163, 3947)
	call MonsterMultiplePatrols.storeNewLoc(7686, 3968)
	call level.monstersMultiplePatrols.new(udg_monsterTypes.get("c"), "normal", false)

	call MonsterMultiplePatrols.storeNewLoc(7675, 3739)
	call MonsterMultiplePatrols.storeNewLoc(7689, 3971)
	call MonsterMultiplePatrols.storeNewLoc(7229, 3885)
	call MonsterMultiplePatrols.storeNewLoc(7330, 3697)
	call level.monstersMultiplePatrols.new(udg_monsterTypes.get("c"), "normal", false)

	call MonsterMultiplePatrols.storeNewLoc(7684, 4253)
	call MonsterMultiplePatrols.storeNewLoc(7684, 4493)
	call MonsterMultiplePatrols.storeNewLoc(7042, 4364)
	call MonsterMultiplePatrols.storeNewLoc(7172, 4088)
	call level.monstersMultiplePatrols.new(udg_monsterTypes.get("c"), "normal", false)

	call MonsterMultiplePatrols.storeNewLoc(7687, 4482)
	call MonsterMultiplePatrols.storeNewLoc(7692, 4241)
	call MonsterMultiplePatrols.storeNewLoc(7173, 4090)
	call MonsterMultiplePatrols.storeNewLoc(7040, 4351)
	call level.monstersMultiplePatrols.new(udg_monsterTypes.get("c"), "normal", false)

	call MonsterMultiplePatrols.storeNewLoc(7684, 4486)
	call MonsterMultiplePatrols.storeNewLoc(7688, 4241)
	call MonsterMultiplePatrols.storeNewLoc(8190, 4084)
	call MonsterMultiplePatrols.storeNewLoc(8329, 4345)
	call level.monstersMultiplePatrols.new(udg_monsterTypes.get("c"), "normal", false)

	call MonsterMultiplePatrols.storeNewLoc(7689, 4241)
	call MonsterMultiplePatrols.storeNewLoc(7684, 4479)
	call MonsterMultiplePatrols.storeNewLoc(8327, 4345)
	call MonsterMultiplePatrols.storeNewLoc(8204, 4090)
	call level.monstersMultiplePatrols.new(udg_monsterTypes.get("c"), "normal", false)

//monster spawns
	call level.monsterSpawns.new("geants", udg_monsterTypes.get("g"), "upToDown", 2.000, 6553, 8585, 8321, 10241, false)
	call level.monsterSpawns.new("crabes1", udg_monsterTypes.get("c"), "downToUp", 2.000, 8487, 9076, 9262, 10276, false)
	call level.monsterSpawns.new("crabes2", udg_monsterTypes.get("c"), "rightToLeft", 4.000, 9345, 6494, 10867, 9100, false)
	call level.monsterSpawns.new("geants2", udg_monsterTypes.get("g"), "rightToLeft", 1.500, 3792, 7029, 8900, 7784, false)

//meteors

endfunction


function Init_level7_Actions takes nothing returns nothing
	local Level level = ForceGetLevel(7)

//start message

//lives earned
	call level.setNbLivesEarned(3)

//start location
	call level.newStart(7334, 1841, 8059, 2364)

//end location
	call level.newEnd(-370, 375, 1038, 498)

//visibilities
	call level.newVisibilityModifier(11864, 5940, 3792, -3664)
	call level.newVisibilityModifier(-3375, 235, 4319, 3698)
	call level.newVisibilityModifier(9482, -3578, 8796, -3816)
	call level.newVisibilityModifier(4473, -3505, 9167, -4127)
	call level.newVisibilityModifier(2956, -785, 4143, 372)

//monsters no move
	call level.monstersNoMove.new(udg_monsterTypes.get("ancien"), 4865, -1329, 0, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 9822, -812, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 9521, -828, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 7440, -248, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 7316, -259, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 9730, -223, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 9939, -399, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 9409, -456, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 7137, -3856, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 5292, -2494, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 3618, -23, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 8157, -1676, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 10312, -1898, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 5440, -911, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 4817, -3658, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 6210, -1127, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 3851, 133, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 3348, -178, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("ancien"), 3146, 2695, -90, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 6870, 884, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 6434, 831, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 6103, 923, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 6079, 563, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 6013, 199, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 5556, 323, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 5319, 177, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 5029, 469, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 5235, 737, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 5037, 1016, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 5191, 1253, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 4853, 1350, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 4506, 1715, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 4275, 1607, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 4118, 2240, -90, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 3965, 2220, -90, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 3737, 2187, -90, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 4049, 1899, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 2832, 1375, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 2475, 1246, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 2402, 1882, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 2933, 2199, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 2985, 3104, -1, false)
endfunction

function Init_level7_part2_Actions takes nothing returns nothing
	local Level level = ForceGetLevel(7)


//monsters simple patrol
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 8437, -242, 8437, 626, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 8326, 626, 8326, -242, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 8170, -243, 8170, 625, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 8989, -755, 8989, 241, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 8787, -754, 8787, 242, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 9210, -1139, 9210, 241, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 8872, 241, 8872, -755, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 10125, 2032, 9729, 2453, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 6531, 3052, 5359, 3088, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 5374, 2966, 6528, 2945, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 9740, 4687, 10225, 4687, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 6529, 2827, 5378, 2835, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 5381, 2704, 6536, 2722, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), 6475, 3246, 5403, 3287, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 9328, -1267, 9328, 241, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 9440, 242, 9440, -1394, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 9564, -1522, 9564, 242, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), 5728, 2289, 5728, 1932, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 9641, -1522, 9641, 242, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 9768, 241, 9768, -1523, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), 6156, 3618, 6513, 3618, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 9855, -1522, 9855, 242, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 5942, 4209, 5942, 3724, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 9740, 2543, 10225, 2543, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 10225, 2745, 9740, 2745, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 9740, 2932, 10225, 2932, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 10226, 3085, 9741, 3085, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 9741, 3243, 10226, 3243, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 10226, 3402, 9741, 3402, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 10216, -1523, 10216, -1038, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 9949, 241, 9949, -1523, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 9741, 3589, 10226, 3589, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 10225, 3761, 9740, 3761, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 9741, 3958, 10226, 3958, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 10225, 4159, 9740, 4159, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 9741, 4353, 10226, 4353, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 10226, 4528, 9741, 4528, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 10253, -1557, 10866, -1557, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 10206, -1677, 10206, -2162, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 9787, -1934, 9787, -2419, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 9656, -2418, 9656, -1933, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 6163, 3724, 6163, 4209, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), 5179, 3724, 5179, 4209, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 4908, 4209, 4908, 3724, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), 5677, 3724, 5677, 4209, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 9473, -1934, 9473, -2419, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), 6112, 2289, 6112, 1932, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), 6456, 2289, 6456, 1932, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 5438, 3725, 5438, 4210, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 8972, -2162, 8972, -1421, false)
endfunction

function Init_level7_part3_Actions takes nothing returns nothing
	local Level level = ForceGetLevel(7)


//monsters simple patrol
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 8835, -1421, 8835, -2162, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 8679, -2162, 8679, -1421, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 8434, -1971, 7821, -1971, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 8178, -2379, 7565, -2379, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 7914, -2930, 7914, -1677, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 8589, -3053, 9458, -3053, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 9458, -3262, 8589, -3262, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 8808, -2574, 8808, -3827, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 8945, -3826, 8945, -2573, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 9132, -2574, 9132, -3827, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 8300, -3597, 8300, -4082, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 8195, -4082, 8195, -3597, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 7809, -3827, 7809, -3214, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 7652, -3214, 7652, -3827, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 8178, -3552, 7309, -3552, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 7948, -3850, 8689, -3850, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 6434, -4082, 6434, -3469, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 5104, -3442, 5104, -2701, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 4877, -2987, 5490, -2987, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 5489, -3175, 4876, -3175, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 5132, -2641, 5873, -2641, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 8588, -2952, 9457, -2952, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 7410, -520, 6925, -520, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 2675, 909, 2675, 1778, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 3186, 1181, 2189, 1181, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 2188, 1300, 3185, 1300, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 3186, 1417, 2189, 1417, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 2189, 1620, 3186, 1620, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 2725, 1805, 2725, 2546, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 3853, -836, 4466, -836, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 4209, -480, 2956, -480, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 2957, -360, 4210, -360, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 4209, -242, 2956, -242, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 2956, -126, 4209, -126, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 4210, 42, 2957, 42, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), 3954, 475, 3469, 475, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), 3344, 652, 3344, 1137, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 2852, 2545, 2852, 1804, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 2671, 1767, 2069, 2125, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), 1233, 1239, 1460, 948, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 638, 1037, 638, 1394, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 369, 1166, -243, 1166, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -243, 1079, 369, 1079, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), 1650, 2132, 1165, 2132, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), 1165, 2307, 1650, 2307, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), 1649, 2460, 1164, 2460, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), 1650, 2950, 1165, 2950, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), 2091, 2956, 2091, 3313, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), 2251, 3313, 2251, 2956, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 2917, 1778, 2917, 909, false)
endfunction

function Init_level7_part4_Actions takes nothing returns nothing
	local Level level = ForceGetLevel(7)


//monsters simple patrol
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 7409, 114, 6924, 114, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 6924, 7, 7409, 7, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 6897, -525, 6897, -1010, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 3853, -1046, 4466, -1046, false)

//monsters multiple patrols
	call MonsterMultiplePatrols.storeNewLoc(8934, 1914)
	call MonsterMultiplePatrols.storeNewLoc(9043, 2311)
	call MonsterMultiplePatrols.storeNewLoc(9166, 1931)
	call level.monstersMultiplePatrols.new(udg_monsterTypes.get("c"), "string", false)

	call MonsterMultiplePatrols.storeNewLoc(9301, 2313)
	call MonsterMultiplePatrols.storeNewLoc(9431, 1922)
	call MonsterMultiplePatrols.storeNewLoc(9551, 2291)
	call level.monstersMultiplePatrols.new(udg_monsterTypes.get("c"), "string", false)

//monster spawns
	call level.monsterSpawns.new("geants", udg_monsterTypes.get("g"), "downToUp", 2.000, 5202, -1656, 6653, -672, false)

//meteors
	call level.meteors.new(4593, 3963, false)
	call level.meteors.new(9983, 5063, false)

endfunction


function Init_level8_Actions takes nothing returns nothing
	local Level level = ForceGetLevel(8)

//start message

//lives earned
	call level.setNbLivesEarned(3)

//start location
	call level.newStart(-65, -33, 683, 542)

//end location
	call level.newEnd(-371, -9078, 1026, -8903)

//visibilities
	call level.newVisibilityModifier(-1270, 649, 1720, -9060)

//monsters no move

//monsters simple patrol

//monsters multiple patrols

//monster spawns
	call level.monsterSpawns.new("crabes1", udg_monsterTypes.get("c"), "leftToRight", 17.000, -1125, -8720, 1332, -980, false)
	call level.monsterSpawns.new("crabes2", udg_monsterTypes.get("c"), "rightToLeft", 17.000, -706, -8745, 1757, -953, false)

//meteors

endfunction


function Init_level9_Actions takes nothing returns nothing
	local Level level = ForceGetLevel(9)

//start message

//lives earned
	call level.setNbLivesEarned(3)

//start location
	call level.newStart(-17, -9522, 691, -8904)

//end location
	call level.newEnd(2528, -9204, 3621, -9078)

//visibilities
	call level.newVisibilityModifier(313, 2243, -11551, -11748)
	call level.newVisibilityModifier(-1852, -11792, 3477, -9848)
	call level.newVisibilityModifier(-797, -10277, 3669, -8996)

//monsters no move
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), -1996, -8503, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), -2113, -5173, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), -3079, -3264, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), -4621, -10091, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), -6893, -10935, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), -8994, -10069, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), -3881, -10104, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), -3372, -9960, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 1530, -10750, -1, false)

//monsters simple patrol
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -2701, -3102, -3442, -3102, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -3442, -3443, -2701, -3443, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -3086, -4646, -3827, -4646, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -1678, -8941, -2547, -8941, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -2546, -8670, -1677, -8670, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -1678, -8342, -2547, -8342, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -1678, -7660, -2163, -7660, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -1934, -6795, -2419, -6795, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -2162, -5978, -1677, -5978, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -3086, -5254, -3699, -5254, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -3698, -5602, -3085, -5602, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -3442, -6376, -2957, -6376, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -3086, -7263, -3699, -7263, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -3698, -7731, -3085, -7731, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -3342, -8357, -3955, -8357, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -4140, -8590, -4140, -9331, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -4507, -8589, -4507, -9330, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -5189, -8717, -5189, -9330, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -5757, -8717, -5757, -9330, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -6292, -9330, -6292, -8717, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -6933, -8717, -6933, -9330, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -7380, -9330, -7380, -8717, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -7941, -8717, -7941, -9330, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -8452, -9331, -8452, -8718, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -9025, -8717, -9025, -9330, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -9454, -9331, -9454, -8718, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -9613, -9406, -10354, -9406, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -9959, -9842, -9959, -8973, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -9403, -9870, -9403, -10483, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -9196, -10482, -9196, -9869, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -8668, -9869, -8668, -10482, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -8489, -10483, -8489, -9870, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -7997, -9869, -7997, -10482, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -7770, -10482, -7770, -9869, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -6669, -10570, -7282, -10570, false)
endfunction

function Init_level9_part2_Actions takes nothing returns nothing
	local Level level = ForceGetLevel(9)


//monsters simple patrol
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -6608, -10638, -6608, -11379, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -6443, -11379, -6443, -10638, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -6146, -10638, -6146, -11379, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -5005, -10517, -5746, -10517, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -5190, -9870, -5190, -10867, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -5347, -9870, -5347, -10995, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -5525, -11122, -5525, -9869, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -4864, -10482, -4864, -9613, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -4715, -9613, -4715, -10482, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -4501, -10482, -4501, -9613, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -2521, -10610, -2521, -9869, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -2414, -9870, -2414, -10611, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -2247, -10610, -2247, -9869, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -2079, -9870, -2079, -10611, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -1448, -10995, -1448, -10254, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -3699, -7488, -3086, -7488, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -1235, -10994, -1235, -10253, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -1087, -10253, -1087, -10994, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -3086, -7102, -3699, -7102, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -806, -10253, -806, -10994, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -636, -10995, -636, -10254, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -472, -10254, -472, -10995, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 2573, -10142, 3442, -10142, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 3441, -10261, 2572, -10261, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 2572, -10382, 3441, -10382, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 3313, -9753, 2828, -9753, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -3086, -7801, -3699, -7801, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 2604, -10400, 3403, -10925, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 51, -10995, 51, -10382, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 415, -10382, 415, -10995, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 727, -10995, 727, -10382, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 1041, -10382, 1041, -10995, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 1366, -10995, 1366, -10382, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 1692, -10382, 1692, -10995, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 1998, -10995, 1998, -10382, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 2345, -10382, 2345, -10995, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 1177, -10994, 1177, -10381, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), -1678, -8141, -2547, -8141, false)

//monsters multiple patrols

//monster spawns
	call level.monsterSpawns.new("crabes", udg_monsterTypes.get("g"), "upToDown", 0.800, -2263, -4781, -1569, -1049, false)

//meteors

endfunction


function Init_level10_Actions takes nothing returns nothing
	local Level level = ForceGetLevel(10)

//start message

//lives earned

//start location
	call level.newStart(2828, -9321, 3316, -8743)

//end location

//visibilities
	call level.newVisibilityModifier(-595, -11894, 11819, 1836)

//monsters no move
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 3859, -8653, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 5838, -8967, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 7278, -7764, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 9681, -11571, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 9276, -11343, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 10049, -11343, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 10456, -11588, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 10845, -11326, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 11099, -8759, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 10499, -10360, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 9967, -9523, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 5242, -10478, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 4488, -8700, -1, false)
	call level.monstersNoMove.new(udg_monsterTypes.get("o"), 5510, -11142, -1, false)

//monsters simple patrol
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 3314, -8377, 2829, -8377, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 3504, -7923, 3504, -7438, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 3724, -8478, 4209, -8478, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 4209, -8774, 3724, -8774, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 3725, -9079, 4210, -9079, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 3852, -9577, 4337, -9577, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 4337, -10065, 3980, -10065, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 5874, -10192, 5517, -10192, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 4108, -10560, 4593, -10560, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 4059, -11149, 4059, -11634, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 4654, -11150, 4654, -11635, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 5489, -10307, 5004, -10307, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 2971, -7710, 3437, -8251, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 3576, -7935, 3944, -7594, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 3970, -8044, 3717, -8325, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 3818, -9486, 4238, -9096, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 4088, -10512, 4372, -10207, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 4098, -10616, 4472, -10891, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 4734, -11133, 5205, -11598, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 5263, -10747, 4993, -10513, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), 4321, -11149, 4321, -11634, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 5129, -9972, 5480, -10224, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 4715, -8583, 4374, -8325, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 4862, -8165, 4674, -7731, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 4861, -8171, 5173, -7780, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 5259, -9069, 5521, -8713, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 5769, -9192, 6143, -8941, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 5751, -11132, 5300, -11596, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 5811, -11166, 5820, -11614, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 6141, -11374, 5917, -11153, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 5920, -10952, 6376, -10965, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 6498, -10616, 6050, -10628, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 6183, -10240, 6492, -10368, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 6664, -10215, 6419, -9744, false)
endfunction

function Init_level10_part2_Actions takes nothing returns nothing
	local Level level = ForceGetLevel(10)


//monsters simple patrol
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 6267, -8166, 5902, -8033, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 6939, -8822, 7395, -8810, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 7399, -8980, 6938, -8996, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 6943, -9244, 7277, -9605, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 6929, -9507, 7285, -9844, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 6960, -10170, 7275, -9859, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 7058, -10237, 7495, -9929, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 7071, -10364, 7527, -10340, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 7506, -10683, 7065, -10498, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 7161, -10867, 6831, -10530, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 6809, -11001, 7146, -11001, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 7145, -11137, 6832, -11586, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 7285, -11613, 7286, -11151, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 7441, -11163, 7454, -11615, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 7797, -11365, 7559, -11152, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 7605, -10673, 8110, -11333, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 8189, -10993, 7956, -10649, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 8307, -10988, 8300, -10386, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 8403, -10383, 8405, -10992, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 8466, -11000, 8911, -10434, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 8478, -11267, 8934, -11245, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 8948, -11255, 8498, -11716, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 8962, -11274, 8964, -11760, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 9215, -11624, 8975, -11288, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 9354, -11633, 9595, -11277, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 9977, -11633, 9738, -11277, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 10117, -11637, 10371, -11270, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 10510, -11270, 10736, -11628, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 10889, -11633, 11136, -11261, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 11209, -11287, 11194, -11755, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 11108, -10380, 11103, -10989, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 10986, -10980, 11018, -10387, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 10755, -10611, 10513, -9887, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 10266, -10267, 10853, -10211, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 10996, -9592, 10770, -9368, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 11125, -8465, 10881, -8826, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 10664, -8810, 10660, -8204, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 10812, -8204, 10785, -8814, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 6435, -9583, 6878, -9581, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 6891, -9384, 6444, -9391, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 6436, -9212, 6870, -9063, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 6334, -8140, 6332, -7468, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 6799, -7405, 7046, -7174, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 6084, -7088, 6503, -6648, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 6469, -8375, 6852, -8340, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 6451, -8157, 6833, -7896, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 5332, -8102, 5684, -7547, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 5306, -7253, 5575, -7233, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 5605, -6913, 5415, -6767, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 6512, -7807, 5922, -7792, false)
endfunction

function Init_level10_part3_Actions takes nothing returns nothing
	local Level level = ForceGetLevel(10)


//monsters simple patrol
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 5748, -8069, 5526, -8302, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 6080, -6556, 6480, -6522, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 5837, -8093, 5840, -8558, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 9463, -8652, 9440, -8220, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 7078, -8008, 7543, -8005, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 7533, -8145, 7070, -8147, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 6940, -8449, 7405, -8459, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 7402, -8641, 6942, -8653, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 9094, -9863, 8964, -10250, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 8747, -9624, 8738, -10216, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 8578, -10214, 8571, -9605, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 8402, -9608, 8380, -10224, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 8223, -10220, 8227, -9613, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 8083, -9618, 8053, -10215, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), 8966, -9330, 8966, -8205, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), 8241, -9330, 8241, -8205, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), 9089, -9330, 9089, -8205, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 9457, -8825, 7564, -8825, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), 9233, -9330, 9233, -8205, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 9458, -8953, 7565, -8953, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 10357, -9203, 10129, -8837, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 9750, -9230, 10361, -9209, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 10355, -9392, 9755, -9428, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 3953, -11055, 3596, -11055, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 3974, -11122, 3639, -11592, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 7564, -8960, 9457, -8960, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), 9091, -8205, 9091, -9330, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 5852, -6863, 5424, -5908, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 6514, -6162, 5389, -6162, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 5959, -6387, 5959, -5902, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 6627, -7410, 6627, -6669, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 7180, -7541, 7537, -7541, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 7154, -7530, 6797, -7530, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 10993, -9832, 10508, -9832, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 10892, -8975, 11377, -8975, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 10879, -9078, 11344, -9549, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 10621, -8920, 10134, -8738, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 10149, -8630, 10501, -8183, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 10098, -9866, 9741, -9866, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 9602, -10611, 10079, -10942, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 10100, -10658, 9607, -10381, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 9603, -10142, 10096, -10394, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 9478, -10611, 8995, -10965, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 9468, -10392, 8975, -10662, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 9469, -10137, 8977, -10400, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("g"), 4748, -10978, 5233, -10978, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 4868, -9564, 5473, -9253, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 4990, -8975, 5473, -8492, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 5588, -8696, 5696, -9210, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 5774, -9296, 6233, -9534, false)
endfunction

function Init_level10_part4_Actions takes nothing returns nothing
	local Level level = ForceGetLevel(10)


//monsters simple patrol
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 5775, -9725, 6141, -9603, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 4884, -8547, 5247, -8160, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 6157, -9990, 6898, -9990, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 6642, -8762, 6285, -8762, false)
	call level.monstersSimplePatrol.new(udg_monsterTypes.get("c"), 8456, -11145, 8969, -10810, false)

//monsters multiple patrols
	call MonsterMultiplePatrols.storeNewLoc(7648, -8280)
	call MonsterMultiplePatrols.storeNewLoc(7970, -8266)
	call MonsterMultiplePatrols.storeNewLoc(7973, -8623)
	call MonsterMultiplePatrols.storeNewLoc(7641, -8613)
	call level.monstersMultiplePatrols.new(udg_monsterTypes.get("g"), "normal", false)

	call MonsterMultiplePatrols.storeNewLoc(8483, -9116)
	call MonsterMultiplePatrols.storeNewLoc(8484, -8551)
	call MonsterMultiplePatrols.storeNewLoc(8290, -8538)
	call MonsterMultiplePatrols.storeNewLoc(8276, -9108)
	call level.monstersMultiplePatrols.new(udg_monsterTypes.get("g"), "normal", false)

//monster spawns
	call level.monsterSpawns.new("crabes1", udg_monsterTypes.get("c"), "rightToLeft", 5.000, 7555, -7992, 10186, -7114, false)
	call level.monsterSpawns.new("crabes2", udg_monsterTypes.get("c"), "upToDown", 3.000, 4568, -7470, 5151, -4637, false)

//meteors

endfunction




function InitTrig_Init_levels takes nothing returns nothing
	local trigger initLevel0 = CreateTrigger()
	local trigger initLevel1 = CreateTrigger()
	local trigger initLevel2 = CreateTrigger()
	local trigger initLevel3 = CreateTrigger()
	local trigger initLevel4 = CreateTrigger()
	local trigger initLevel4_part2 = CreateTrigger()
	local trigger initLevel5 = CreateTrigger()
	local trigger initLevel5_part2 = CreateTrigger()
	local trigger initLevel6 = CreateTrigger()
	local trigger initLevel6_part2 = CreateTrigger()
	local trigger initLevel7 = CreateTrigger()
	local trigger initLevel7_part2 = CreateTrigger()
	local trigger initLevel7_part3 = CreateTrigger()
	local trigger initLevel7_part4 = CreateTrigger()
	local trigger initLevel8 = CreateTrigger()
	local trigger initLevel9 = CreateTrigger()
	local trigger initLevel9_part2 = CreateTrigger()
	local trigger initLevel10 = CreateTrigger()
	local trigger initLevel10_part2 = CreateTrigger()
	local trigger initLevel10_part3 = CreateTrigger()
	local trigger initLevel10_part4 = CreateTrigger()
	call TriggerAddAction(initLevel0, function Init_level0_Actions)
	call TriggerRegisterTimerEventSingle(initLevel0, 0.0000)
	call TriggerAddAction(initLevel1, function Init_level1_Actions)
	call TriggerRegisterTimerEventSingle(initLevel1, 0.0001)
	call TriggerAddAction(initLevel2, function Init_level2_Actions)
	call TriggerRegisterTimerEventSingle(initLevel2, 0.0002)
	call TriggerAddAction(initLevel3, function Init_level3_Actions)
	call TriggerRegisterTimerEventSingle(initLevel3, 0.0003)
	call TriggerAddAction(initLevel4, function Init_level4_Actions)
	call TriggerRegisterTimerEventSingle(initLevel4, 0.0004)
	call TriggerAddAction(initLevel4_part2, function Init_level4_part2_Actions)
	call TriggerRegisterTimerEventSingle(initLevel4_part2, 0.0005)
	call TriggerAddAction(initLevel5, function Init_level5_Actions)
	call TriggerRegisterTimerEventSingle(initLevel5, 0.0006)
	call TriggerAddAction(initLevel5_part2, function Init_level5_part2_Actions)
	call TriggerRegisterTimerEventSingle(initLevel5_part2, 0.0007)
	call TriggerAddAction(initLevel6, function Init_level6_Actions)
	call TriggerRegisterTimerEventSingle(initLevel6, 0.0008)
	call TriggerAddAction(initLevel6_part2, function Init_level6_part2_Actions)
	call TriggerRegisterTimerEventSingle(initLevel6_part2, 0.0009)
	call TriggerAddAction(initLevel7, function Init_level7_Actions)
	call TriggerRegisterTimerEventSingle(initLevel7, 0.0010)
	call TriggerAddAction(initLevel7_part2, function Init_level7_part2_Actions)
	call TriggerRegisterTimerEventSingle(initLevel7_part2, 0.0011)
	call TriggerAddAction(initLevel7_part3, function Init_level7_part3_Actions)
	call TriggerRegisterTimerEventSingle(initLevel7_part3, 0.0012)
	call TriggerAddAction(initLevel7_part4, function Init_level7_part4_Actions)
	call TriggerRegisterTimerEventSingle(initLevel7_part4, 0.0013)
	call TriggerAddAction(initLevel8, function Init_level8_Actions)
	call TriggerRegisterTimerEventSingle(initLevel8, 0.0014)
	call TriggerAddAction(initLevel9, function Init_level9_Actions)
	call TriggerRegisterTimerEventSingle(initLevel9, 0.0015)
	call TriggerAddAction(initLevel9_part2, function Init_level9_part2_Actions)
	call TriggerRegisterTimerEventSingle(initLevel9_part2, 0.0016)
	call TriggerAddAction(initLevel10, function Init_level10_Actions)
	call TriggerRegisterTimerEventSingle(initLevel10, 0.0017)
	call TriggerAddAction(initLevel10_part2, function Init_level10_part2_Actions)
	call TriggerRegisterTimerEventSingle(initLevel10_part2, 0.0018)
	call TriggerAddAction(initLevel10_part3, function Init_level10_part3_Actions)
	call TriggerRegisterTimerEventSingle(initLevel10_part3, 0.0019)
	call TriggerAddAction(initLevel10_part4, function Init_level10_part4_Actions)
	call TriggerRegisterTimerEventSingle(initLevel10_part4, 0.0020)
endfunction

//===========================================================================
// Trigger: Forces ally
//===========================================================================
function Trig_Forces_ally_Actions takes nothing returns nothing
    set bj_forLoopAIndex = 1
    set bj_forLoopAIndexEnd = 12
    loop
        exitwhen bj_forLoopAIndex > bj_forLoopAIndexEnd
        call SetPlayerAllianceStateBJ( Player(0), ConvertedPlayer(GetForLoopIndexA()), bj_ALLIANCE_ALLIED_VISION )
        call SetPlayerAllianceStateBJ( ConvertedPlayer(GetForLoopIndexA()), Player(0), bj_ALLIANCE_ALLIED_VISION )
        set bj_forLoopAIndex = bj_forLoopAIndex + 1
    endloop
endfunction

//===========================================================================
function InitTrig_Forces_ally takes nothing returns nothing
    set gg_trg_Forces_ally = CreateTrigger(  )
    call TriggerAddAction( gg_trg_Forces_ally, function Trig_Forces_ally_Actions )
endfunction

//===========================================================================
// Trigger: Camera
//===========================================================================
function Trig_Camera_Actions takes nothing returns nothing
    call SetCameraField( CAMERA_FIELD_TARGET_DISTANCE, DEFAULT_CAMERA_FIELD, 0 )
endfunction

//===========================================================================
function InitTrig_Camera takes nothing returns nothing
    set gg_trg_Camera = CreateTrigger(  )
    call TriggerAddAction( gg_trg_Camera, function Trig_Camera_Actions )
endfunction

//===========================================================================
// Trigger: No selection circle
//===========================================================================
function Trig_No_selection_circle_Actions takes nothing returns nothing
    call EnableSelect( true, false )
endfunction

//===========================================================================
function InitTrig_No_selection_circle takes nothing returns nothing
    set gg_trg_No_selection_circle = CreateTrigger(  )
    call TriggerRegisterGameLoadedEventBJ( gg_trg_No_selection_circle )
    call TriggerAddAction( gg_trg_No_selection_circle, function Trig_No_selection_circle_Actions )
endfunction

//===========================================================================
// Trigger: Welcome message
//===========================================================================
function Trig_Welcome_message_Actions takes nothing returns nothing
    call DisplayTimedTextToForce( GetPlayersAll(), 45.00, "TRIGSTR_001" )
    call DisplayTimedTextToForce( GetPlayersAll(), 45.00, "TRIGSTR_002" )
    call FlashQuestDialogButtonBJ(  )
endfunction

//===========================================================================
function InitTrig_Welcome_message takes nothing returns nothing
    set gg_trg_Welcome_message = CreateTrigger(  )
    call TriggerAddAction( gg_trg_Welcome_message, function Trig_Welcome_message_Actions )
endfunction

//===========================================================================
// Trigger: Allways day
//===========================================================================
function Trig_Allways_day_Actions takes nothing returns nothing
    call SetTimeOfDay( 12 )
    call UseTimeOfDayBJ( false )
endfunction

//===========================================================================
function InitTrig_Allways_day takes nothing returns nothing
    set gg_trg_Allways_day = CreateTrigger(  )
    call TriggerAddAction( gg_trg_Allways_day, function Trig_Allways_day_Actions )
endfunction

//===========================================================================
// Trigger: Start sound
//===========================================================================
function Trig_Start_sound_Actions takes nothing returns nothing
    call PlaySoundBJ( gg_snd_start )
endfunction

//===========================================================================
function InitTrig_Start_sound takes nothing returns nothing
    set gg_trg_Start_sound = CreateTrigger(  )
    call TriggerRegisterTimerEventSingle( gg_trg_Start_sound, 2.00 )
    call TriggerAddAction( gg_trg_Start_sound, function Trig_Start_sound_Actions )
endfunction

//===========================================================================
// Trigger: Heroes
//===========================================================================
//TESH.scrollpos=70
//TESH.alwaysfold=0
library Heroes needs Escaper


globals
    location array startPositions
    location array startPositionsRandomized
    integer array playerIdsRandomized
    
    constant real TIME_BEFORE_HERO_SPAWN = 3.
    constant real TIME_BETWEEN_EACH_HERO_SPAWN = 0.3
    constant real HERO_START_ANGLE = 90.
    constant string EFFECT_FOR_MISSING_HEROES = "Abilities\\Spells\\Undead\\DeathPact\\DeathPactTarget.mdl"
endglobals


function RandomizeStartPositionsAndHeroSpawnOrder takes nothing returns nothing
    local boolean array alreadyAdded
    local integer n
    local integer i
    
//randomize start positions
    set i = 0
    loop
        exitwhen (i > 11)
            loop
                set n = GetRandomInt(0, 11)
                exitwhen (not alreadyAdded[n])
            endloop
            set startPositionsRandomized[i] = startPositions[n]
            set alreadyAdded[n] = true
        set i = i + 1
    endloop
    
//reinit alreadyAdded to false
    set i = 0
    loop
        exitwhen (i > 11)
            set alreadyAdded[i] = false
        set i = i + 1
    endloop
    
//randomize hero spawn order
    set i = 0
    loop
        exitwhen (i > 11)
            loop
                set n = GetRandomInt(0, 11)
                exitwhen (not alreadyAdded[n])
            endloop
            set playerIdsRandomized[i] = n
            set alreadyAdded[n] = true
        set i = i + 1
    endloop
endfunction



function Trig_heroes_Actions takes nothing returns nothing
    local boolean array alreadyAdded
    local effect anEffect
    local integer i
    local integer n

//randomize start positions
    call RandomizeStartPositionsAndHeroSpawnOrder()
    
//create heroes
    call ClearSelection()
    set i = 0
    loop
        exitwhen (i > 11)
            set n = playerIdsRandomized[i]
            if (udg_escapers.get(i) != 0) then
                call udg_escapers.get(i).createHero(GetLocationX(startPositionsRandomized[n]), GetLocationY(startPositionsRandomized[n]), HERO_START_ANGLE)
            else
                set anEffect = AddSpecialEffectLoc(EFFECT_FOR_MISSING_HEROES, startPositionsRandomized[n])
                call DestroyEffect(anEffect)
            endif
            set startPositionsRandomized[n] = null
            call TriggerSleepAction(TIME_BETWEEN_EACH_HERO_SPAWN)
        set i = i + 1
    endloop
    //call EnableTrigger(gg_trg_anticheat_teleport_and_revive)
    //set AnticheatTeleport_justRevived = true
    set anEffect = null
endfunction

//===========================================================================
function InitTrig_Heroes takes nothing returns nothing
//define start positions
    local real minX = GetRectMinX(gg_rct_departLvl_0) + 200
    local real minY = GetRectMinY(gg_rct_departLvl_0) + 100
    local real diffX = (GetRectMaxX(gg_rct_departLvl_0) - minX) / 3
    local real diffY = (GetRectMaxY(gg_rct_departLvl_0) - minY) / 4
    local integer i = 0
    local integer j = 0
    local integer n = 0
    loop
        exitwhen (i > 2)
        loop
            exitwhen (j > 3)
                set startPositions[n] = Location(minX + diffX * j, minY + diffY * i)
            set n = n + 1
            set j = j + 1
        endloop
        set j = 0
        set i = i + 1
    endloop
    
    set gg_trg_Heroes = CreateTrigger()
    call TriggerAddAction(gg_trg_Heroes, function Trig_heroes_Actions)
    call TriggerRegisterTimerEvent(gg_trg_Heroes, TIME_BEFORE_HERO_SPAWN, false)
endfunction


endlibrary
//===========================================================================
// Trigger: Has max name
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
function Trig_Has_max_name_Actions takes nothing returns nothing
    local integer i = 0
    loop
        exitwhen (i > 11)
            if (GetPlayerName(Player(i)) == DecodeString("XpsmeFeju") or StringCase(GetPlayerName(Player(i)), false) == DecodeString("nbyjnbypv")) then
                set udg_has_max_name[i] = true
            endif
        set i = i + 1
    endloop
endfunction

//===========================================================================
function InitTrig_Has_max_name takes nothing returns nothing
    set gg_trg_Has_max_name = CreateTrigger(  )
    call TriggerRegisterTimerEventSingle( gg_trg_Has_max_name, 0.00 )
    call TriggerAddAction( gg_trg_Has_max_name, function Trig_Has_max_name_Actions )
endfunction

//===========================================================================
// Trigger: Ajout evenement kan plein joueurs
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
function Trig_Ajout_evenement_kan_plein_joueurs_Actions takes nothing returns nothing
    local integer i = 0
    loop
        exitwhen (i > 11)        
            call TriggerRegisterPlayerChatEvent(gg_trg_Prouve_is_real_max1, Player(i), DecodeString("jyjn  "), true )
            call TriggerRegisterPlayerChatEvent(gg_trg_Prouve_is_real_max2, Player(i), DecodeString("njyj "), true )
        set i = i + 1
    endloop
endfunction

//===========================================================================
function InitTrig_Ajout_evenement_kan_plein_joueurs takes nothing returns nothing
    set gg_trg_Ajout_evenement_kan_plein_joueurs = CreateTrigger(  )
    call TriggerAddAction( gg_trg_Ajout_evenement_kan_plein_joueurs, function Trig_Ajout_evenement_kan_plein_joueurs_Actions )
endfunction

//===========================================================================
// Trigger: Prouve is real max1
//===========================================================================
function Trig_Prouve_is_real_max1_Conditions takes nothing returns boolean
    if ( not ( udg_has_max_name[( GetConvertedPlayerId(GetTriggerPlayer()) - 1 )] == true ) ) then
        return false
    endif
    return true
endfunction

function Trig_Prouve_is_real_max1_Actions takes nothing returns nothing
    call EnableTrigger( gg_trg_Prouve_is_real_max2 )
endfunction

//===========================================================================
function InitTrig_Prouve_is_real_max1 takes nothing returns nothing
    set gg_trg_Prouve_is_real_max1 = CreateTrigger(  )
    call TriggerAddCondition( gg_trg_Prouve_is_real_max1, Condition( function Trig_Prouve_is_real_max1_Conditions ) )
    call TriggerAddAction( gg_trg_Prouve_is_real_max1, function Trig_Prouve_is_real_max1_Actions )
endfunction

//===========================================================================
// Trigger: Prouve is real max2
//===========================================================================
function Trig_Prouve_is_real_max2_Conditions takes nothing returns boolean
    if ( not ( udg_has_max_name[( GetConvertedPlayerId(GetTriggerPlayer()) - 1 )] == true ) ) then
        return false
    endif
    return true
endfunction

function Trig_Prouve_is_real_max2_Actions takes nothing returns nothing
    local integer i = GetPlayerId( GetOwningPlayer( GetTriggerUnit() ) )
    call udg_escapers.get(i).setIsTrueMaximaxou(true)
    set udg_cheatsUsed = true
    call Text_P(Player(i), "Héhé Max, bienvenue dans ta map !")
    call DisableTrigger( GetTriggeringTrigger() )  //only one true Maximaxou allowed
endfunction

//===========================================================================
function InitTrig_Prouve_is_real_max2 takes nothing returns nothing
    set gg_trg_Prouve_is_real_max2 = CreateTrigger(  )
    call DisableTrigger( gg_trg_Prouve_is_real_max2 )
    call TriggerAddCondition( gg_trg_Prouve_is_real_max2, Condition( function Trig_Prouve_is_real_max2_Conditions ) )
    call TriggerAddAction( gg_trg_Prouve_is_real_max2, function Trig_Prouve_is_real_max2_Actions )
endfunction

//===========================================================================
// Trigger: Command shortcuts functions
//===========================================================================
//TESH.scrollpos=105
//TESH.alwaysfold=0
library CommandShortcuts needs BasicFunctions


globals
    string array A_shortcutCommand
    string array Z_shortcutCommand
    string array E_shortcutCommand
    string array R_shortcutCommand
    string array Q_shortcutCommand
    string array S_shortcutCommand
    string array D_shortcutCommand
    string array F_shortcutCommand
endglobals



function InitShortcutSkills takes integer playerId returns nothing
    local unit hero = udg_escapers.get(playerId).getHero()
    
    //! textmacro InitShortcut takes shortcut
    if ($shortcut$_shortcutCommand[playerId] == null) then
        call UnitRemoveAbility(hero, 'SC$shortcut$o')
        call UnitAddAbility(hero, 'SC$shortcut$u')
    else
        call UnitRemoveAbility(hero, 'SC$shortcut$u')
        call UnitAddAbility(hero, 'SC$shortcut$o')
    endif
    //! endtextmacro

    //! runtextmacro InitShortcut("A")
    //! runtextmacro InitShortcut("Z")
    //! runtextmacro InitShortcut("E")
    //! runtextmacro InitShortcut("R")
    //! runtextmacro InitShortcut("Q")
    //! runtextmacro InitShortcut("S")
    //! runtextmacro InitShortcut("D")
    //! runtextmacro InitShortcut("F")
    
    set hero = null
endfunction



function AssignShortcut takes integer playerId, string shortcut, string command returns nothing
    local unit hero = udg_escapers.get(playerId).getHero()
    set shortcut = StringCase(shortcut, true)
    
    //! textmacro AssignShortcut takes shortcut
    if (shortcut == "$shortcut$") then
        if ($shortcut$_shortcutCommand[playerId] == null) then
            call UnitRemoveAbility(hero, 'SC$shortcut$u')
            call UnitAddAbility(hero, 'SC$shortcut$o')
        endif
        set $shortcut$_shortcutCommand[playerId] = "-" + command
        return
    endif
    //! endtextmacro

    //! runtextmacro AssignShortcut("A")
    //! runtextmacro AssignShortcut("Z")
    //! runtextmacro AssignShortcut("E")
    //! runtextmacro AssignShortcut("R")
    //! runtextmacro AssignShortcut("Q")
    //! runtextmacro AssignShortcut("S")
    //! runtextmacro AssignShortcut("D")
    //! runtextmacro AssignShortcut("F")
    
    set hero = null
endfunction


function UnassignShortcut takes integer playerId, string shortcut returns nothing
    local unit hero = udg_escapers.get(playerId).getHero()
    set shortcut = StringCase(shortcut, true)
    
    //! textmacro UnassignShortcut takes shortcut
    if (shortcut == "$shortcut$") then
        if ($shortcut$_shortcutCommand[playerId] != null) then
            call UnitRemoveAbility(hero, 'SC$shortcut$o')
            call UnitAddAbility(hero, 'SC$shortcut$u')
            set $shortcut$_shortcutCommand[playerId] = null
        endif
        return
    endif
    //! endtextmacro

    //! runtextmacro UnassignShortcut("A")
    //! runtextmacro UnassignShortcut("Z")
    //! runtextmacro UnassignShortcut("E")
    //! runtextmacro UnassignShortcut("R")
    //! runtextmacro UnassignShortcut("Q")
    //! runtextmacro UnassignShortcut("S")
    //! runtextmacro UnassignShortcut("D")
    //! runtextmacro UnassignShortcut("F")
    
    set hero = null
endfunction


function IsShortcut takes string S returns boolean
    set S = StringCase(S, true)
    //! textmacro IsShortcut takes shortcut
    if (S == "$shortcut$") then
        return true
    endif
    //! endtextmacro

    //! runtextmacro IsShortcut("A")
    //! runtextmacro IsShortcut("Z")
    //! runtextmacro IsShortcut("E")
    //! runtextmacro IsShortcut("R")
    //! runtextmacro IsShortcut("Q")
    //! runtextmacro IsShortcut("S")
    //! runtextmacro IsShortcut("D")
    //! runtextmacro IsShortcut("F")

    return false
endfunction



function GetStringAssignedFromCommand takes string command returns string
    local string outputStr
    local boolean spaceFound = false
    local integer cmdLength = StringLength(command)
    local integer charId = 3
    loop
        exitwhen (charId >= cmdLength)
            if (SubStringBJ(command, charId, charId) == " ") then
                if (not spaceFound) then
                    set spaceFound = true
                else
                    set outputStr = SubStringBJ(command, charId + 1, cmdLength)
                    if (SubStringBJ(outputStr, 1, 1) == "(" and SubStringBJ(outputStr, StringLength(outputStr), StringLength(outputStr)) == ")") then
                        set outputStr = SubStringBJ(outputStr, 2, StringLength(outputStr) - 1)
                    endif
                    return outputStr
                endif
            endif
        set charId = charId + 1
    endloop
    return null
endfunction



function DisplayShortcuts takes integer playerId returns nothing
    call Text_P(Player(playerId), " ")
    call Text_P(Player(playerId), udg_colorCode[playerId] + "Your shortcuts:")
    //! textmacro ShowShortcut takes shortcut
    if ($shortcut$_shortcutCommand[playerId] == null) then
        call Text_P(Player(playerId), udg_colorCode[playerId] + "$shortcut$: |r" + udg_colorCode[GREY] + "none")
    else
        call Text_P(Player(playerId), udg_colorCode[playerId] + "$shortcut$: |r" + $shortcut$_shortcutCommand[playerId])
    endif
    //! endtextmacro

    //! runtextmacro ShowShortcut("A")
    //! runtextmacro ShowShortcut("Z")
    //! runtextmacro ShowShortcut("E")
    //! runtextmacro ShowShortcut("R")
    //! runtextmacro ShowShortcut("Q")
    //! runtextmacro ShowShortcut("S")
    //! runtextmacro ShowShortcut("D")
    //! runtextmacro ShowShortcut("F")
endfunction



endlibrary




//===========================================================================
function InitTrig_Command_shortcuts_functions takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: Using shortcut
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
function Trig_using_shortcut_Conditions takes nothing returns boolean
    return IsHero(GetTriggerUnit())
endfunction



function Trig_using_shortcut_Actions takes nothing returns nothing
    local Escaper escaper = Hero2Escaper(GetTriggerUnit())
    local player p = escaper.getPlayer()
    
    //! textmacro UsingShortcut takes shortcut
    if (GetSpellAbilityId() == 'SC$shortcut$o') then
        call Text_P(p, udg_colorCode[GetPlayerId(p)] + GetPlayerName(p) + ":|r " + $shortcut$_shortcutCommand[GetPlayerId(p)])
        call ExecuteCommand(escaper, $shortcut$_shortcutCommand[GetPlayerId(p)])
        return
    endif
    //! endtextmacro

    //! runtextmacro UsingShortcut("A")
    //! runtextmacro UsingShortcut("Z")
    //! runtextmacro UsingShortcut("E")
    //! runtextmacro UsingShortcut("R")
    //! runtextmacro UsingShortcut("Q")
    //! runtextmacro UsingShortcut("S")
    //! runtextmacro UsingShortcut("D")
    //! runtextmacro UsingShortcut("F")
endfunction


//===========================================================================
function InitTrig_Using_shortcut takes nothing returns nothing
    set gg_trg_Using_shortcut = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Using_shortcut, EVENT_PLAYER_UNIT_SPELL_CAST )
    call TriggerAddCondition( gg_trg_Using_shortcut, Condition( function Trig_using_shortcut_Conditions ) )
    call TriggerAddAction( gg_trg_Using_shortcut, function Trig_using_shortcut_Actions )
endfunction

//===========================================================================
// Trigger: Commands 1
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
globals

    constant string Commands1 = "-cameraField(cf) x
changes the camera field (height), default is 2500

-resetCamera(rc)
puts the camera back like chosen field

-resetCameraInit(rci)
changes the camera field back to its default value (2500)

-animation(an) <string>
makes your hero doing an animation. ex : -an attack

-mapNbMonsters(mnbm) [moving(m)|all(a)|notMoving(nm)]
displays the number of monsters in the map, of the chosen kind. \"Moving\" is the default kind. ex : -mnbm nm

-levelNbMonsters(lnbm) [moving(m)|all(a)|notMoving(nm)]
displays the number of monsters in the current level, of the chosen kind

-kill(kl) : kills your hero

-kick(kc) : kicks yourself

-disco(d) [off|1~30]
chooses the number of color changes in ten seconds, or stop color changing (without parameter : once a second)

-clearText(clr)
removes the text on the screen

-getCurrentLevel(getcl)
displays the number of the current level (first one is number 0)"


//===========================================================================
    constant string Commands1Requirement1 = "Here is the first part of various commands you can use in game"
    constant string Commands1Requirement2 = ""
    constant string Commands1Requirement3 = "cf, rc, rci, an, mnbm, lnbm, kl, kc, d, clr, getcl"

endglobals






//===========================================================================
function InitTrig_Commands_1 takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: Commands 2
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
globals

    constant string Commands2 = "-drunk(-) <real drunkValue>  --> value between 5 and 60
makes your hero drink alcohol

-noDrunk(-) 
stops drunk mode

-apm(-) [all|a]
displays apm on slide of everybody or just yourself

-saveCommand(sc) <commandLabel> <command>
saves a command or group of commands into a name of your choice

-executeCommand(ec) <commandLabel>
execute a command or group of commands you saved with \"saveCommand\"

-autoContinueAfterSliding(acas) <boolean status>
activated at the beginning of the game
ex: -acas off, -acas 1

-usedTerrains(ut)
displays the terrains used in this game

-getTerrainInfo(gti) [ <terrain> | <lowInteger> <upInteger> ]
gets information about terrains used in the game and all terrains of warcraft 3
terrains are numbered between 1 and 177
without parameter you'll get information about terrains you right click on (use -stop to stop this mode)

-stop(s) 
stops getTerrainInfoMode"


//===========================================================================
    constant string Commands2Requirement1 = "Here is the second part of various commands you can use in game"
    constant string Commands2Requirement2 = ""
    constant string Commands2Requirement3 = "drunk, noDrunk, apm, sc, ec, acas, ut, gti, s"

endglobals






//===========================================================================
function InitTrig_Commands_2 takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: Colors
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
globals

    constant string Colors = "The colors are :
red or rd, blue or be
teal or tl, purple or pe
yellow or yw, orange or oe
green or gn, pink or pk
grey or gray or gy, lightblue or lb
darkgreen or dg, brown or bn
black or bk

-<color>
change the base color of your character

-vertexColor [ <red> <green> <blue> [<transparency>] ]
alias -vc, change the vertex color of you character.
The result color depends on the basic color of your character.
The parameters are integer percentage or x to take a random percentage.
Without parameter, it will do like -vc x x x.

You can also specify onnly the red part of the vertex color :
-vertexColorRed [<red>], alias -vcr
Same for green, blue and transparency (vcg, vcb, vct)

-noVertex
alias -nv, cancel the vertex color of your character
it's like -vc 100 100 100

-colorInfo [<Pcolor>]
alias -ci, display info about the color of your character, or of an other player's character"
    
//==================================================================================================================    
    constant string ColorsRequirement1 = "Here are all commands to change the color of your character."
    constant string ColorsRequirement2 = ""
    constant string ColorsRequirement3 = "rd, be, tl, pe, yw, oe, gn, pk, gy, lb, dg, bn, bk, vc, vcr, vcg, vcb, vct, nv, ci"
    
endglobals
















//===========================================================================
function InitTrig_Colors takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: Effects
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
globals

    constant string Effects = "The effects are :
light or l
fire or f
ice or i
corruption or c
poison or p
slow or s

-effect <effect>
alias -ef, puts an effect on each hand of your hero

-customEffect <effect> <bodyPart>
alias -ce, puts an effect on the specified bodyPart
The body parts are :
leftHand or lh
rightHand or rh
leftFoot or lf
rightFoot or rf
overhead or oh
head or h
origin or o
chest or c

-effectsEverywhere <effect>
alias -efe, puts the same effect to each body part of your hero

-deleteEffects [<numberOfEffectsToRemove n>]
alias -de, deletes the n last effects of your hero, all effects if no parameter specified"
    

//==================================================================================================================   
    constant string EffectsRequirement1 = "Here are all commands to add effects on your character."
    constant string EffectsRequirement2 = ""
    constant string EffectsRequirement3 = "ef, ce, efe, de"
    
endglobals
















//===========================================================================
function InitTrig_Effects takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: Red commands
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
globals

    constant string RedCommands = "-kill <Pcolor>
alias -kl, kills a hero
examples : -kill be,  -kl teal

-kick <Pcolor>
alias -kc, kicks a player
examples : -kick be,  -kc teal

-restart
just restart the game like when lose"


    
//==================================================================================================================   
    constant string RedCommandsRequirement1 = "If a player is afk, no more need to kill him (autokill if needed)."
    constant string RedCommandsRequirement2 = "If a player is really boring, still need to kick him."
    constant string RedCommandsRequirement3 = "kl, kc, restart"
    
endglobals
















//===========================================================================
function InitTrig_Red_commands takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: Map description
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
globals

    constant string MapDescription = "Max Escape Creation is a tool made by Maximaxou to create escapes during the game with commands. The good point is that it's possible to save the map. We can make escapes in multiplayer without any map making knowledge."
    
//==================================================================================================================   

    constant string MapDescriptionRequirement1 = "This map is the first one made with Max Escape Creation"
    constant string MapDescriptionRequirement2 = "http:/max.slid.free.fr/maxEscapeCreation"
    
endglobals
















//===========================================================================
function InitTrig_Map_description takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: Contact
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
globals

    constant string Contact = "To contact Maximaxou, creator of Max Escape Creation : maxpolar@hotmail.fr"
    
//==================================================================================================================   
    constant string ContactRequirement1 = "You can contact us at our channel in Europe : clan SliD"
    
endglobals
















//===========================================================================
function InitTrig_Contact takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: Command shortcuts
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
globals

    constant string CommandShortcuts = "To assign a command to a key, use this command :
-assign <key> <command>
alias as
don't put the \"-\" of the command you wanna save
ex: -assign A red, -as d vc, -as e mirror on, -as R m off

To assign an other command to a already used shortcut, just type command assign again.

To disable a shortcut, use this command :
-unassign <key>
alias uas

To display your current shortcuts, use this command :
-displayShortcuts
alias -ds"


    
//==================================================================================================================    
    constant string CommandShortcutsRequirement1 = "You can now use 8 shortcuts to execute your favorite commands !"
    constant string CommandShortcutsRequirement2 = "Press A, Z, E, R, Q, S, D or F !"

endglobals







//===========================================================================
function InitTrig_Command_shortcuts takes nothing returns nothing
endfunction

//===========================================================================
// Trigger: Adding quests
//===========================================================================
//TESH.scrollpos=23
//TESH.alwaysfold=0
function Trig_adding_quests_Actions takes nothing returns nothing

//GAUCHE

    //Commands1
    call CreateQuestBJ( bj_QUESTTYPE_REQ_DISCOVERED, "Commands 1", Commands1, "ReplaceableTextures\\CommandButtons\\BTNEnt.blp" )
    call CreateQuestItemBJ( GetLastCreatedQuestBJ(), Commands1Requirement1 )
    call CreateQuestItemBJ( GetLastCreatedQuestBJ(), Commands1Requirement2 )
    call CreateQuestItemBJ( GetLastCreatedQuestBJ(), Commands1Requirement3 )

    //Commands2
    call CreateQuestBJ( bj_QUESTTYPE_REQ_DISCOVERED, "Commands 2", Commands2, "ReplaceableTextures\\CommandButtons\\BTNEnt.blp" )
    call CreateQuestItemBJ( GetLastCreatedQuestBJ(), Commands2Requirement1 )
    call CreateQuestItemBJ( GetLastCreatedQuestBJ(), Commands2Requirement2 )
    call CreateQuestItemBJ( GetLastCreatedQuestBJ(), Commands2Requirement3 )
    
    // Colors
    call CreateQuestBJ( bj_QUESTTYPE_REQ_DISCOVERED, "Colors", Colors, "ReplaceableTextures\\CommandButtons\\BTNAmbush.blp" )
    call CreateQuestItemBJ( GetLastCreatedQuestBJ(), ColorsRequirement1 )
    call CreateQuestItemBJ( GetLastCreatedQuestBJ(), ColorsRequirement2 )
    call CreateQuestItemBJ( GetLastCreatedQuestBJ(), ColorsRequirement3 )
    
    // Effects
    call CreateQuestBJ( bj_QUESTTYPE_REQ_DISCOVERED, "Effects", Effects, "ReplaceableTextures\\CommandButtons\\BTNDevotion.blp" )
    call CreateQuestItemBJ( GetLastCreatedQuestBJ(), EffectsRequirement1 )
    call CreateQuestItemBJ( GetLastCreatedQuestBJ(), EffectsRequirement2 )
    call CreateQuestItemBJ( GetLastCreatedQuestBJ(), EffectsRequirement3 )

    // Red commands
    call CreateQuestBJ( bj_QUESTTYPE_REQ_DISCOVERED, "Red commands", RedCommands, "ReplaceableTextures\\CommandButtons\\BTNAncientOfLore.blp" )
    call CreateQuestItemBJ( GetLastCreatedQuestBJ(), RedCommandsRequirement1 )
    call CreateQuestItemBJ( GetLastCreatedQuestBJ(), RedCommandsRequirement2 )
    call CreateQuestItemBJ( GetLastCreatedQuestBJ(), RedCommandsRequirement3 )
    

    
    
//DROITE

    // Map description
    call CreateQuestBJ( bj_QUESTTYPE_OPT_DISCOVERED, "Map description", MapDescription, "ReplaceableTextures\\CommandButtons\\BTNCOP.blp" )
    call CreateQuestItemBJ( GetLastCreatedQuestBJ(), MapDescriptionRequirement1 )
    call CreateQuestItemBJ( GetLastCreatedQuestBJ(), MapDescriptionRequirement2 )
    
    // Contact
    call CreateQuestBJ( bj_QUESTTYPE_OPT_DISCOVERED, "Contact", Contact, "ReplaceableTextures\\CommandButtons\\BTNEvilIllidan.blp" )
    call CreateQuestItemBJ( GetLastCreatedQuestBJ(), ContactRequirement1 )
    
    //Command shortcuts
    call CreateQuestBJ( bj_QUESTTYPE_OPT_DISCOVERED, "Command shortcuts", CommandShortcuts, "ReplaceableTextures\\CommandButtons\\BTNImmolationOff.blp" )
    call CreateQuestItemBJ( GetLastCreatedQuestBJ(), CommandShortcutsRequirement1 )
    call CreateQuestItemBJ( GetLastCreatedQuestBJ(), CommandShortcutsRequirement2 )
    
    
endfunction

//===========================================================================
function InitTrig_Adding_quests takes nothing returns nothing
    set gg_trg_Adding_quests = CreateTrigger(  )
    call TriggerAddAction( gg_trg_Adding_quests, function Trig_adding_quests_Actions )
endfunction
//===========================================================================
// Trigger: Camera reset
//===========================================================================
function Trig_Camera_reset_Actions takes nothing returns nothing
    local player TP = GetTriggerPlayer()
    local integer TPN = GetPlayerId(TP)
    call udg_escapers.get(TPN).resetCamera()
endfunction

//===========================================================================
function InitTrig_Camera_reset takes nothing returns nothing
    set gg_trg_Camera_reset = CreateTrigger(  )
    call TriggerRegisterPlayerEventEndCinematic( gg_trg_Camera_reset, Player(0) )
    call TriggerRegisterPlayerEventEndCinematic( gg_trg_Camera_reset, Player(1) )
    call TriggerRegisterPlayerEventEndCinematic( gg_trg_Camera_reset, Player(2) )
    call TriggerRegisterPlayerEventEndCinematic( gg_trg_Camera_reset, Player(3) )
    call TriggerRegisterPlayerEventEndCinematic( gg_trg_Camera_reset, Player(4) )
    call TriggerRegisterPlayerEventEndCinematic( gg_trg_Camera_reset, Player(5) )
    call TriggerRegisterPlayerEventEndCinematic( gg_trg_Camera_reset, Player(6) )
    call TriggerRegisterPlayerEventEndCinematic( gg_trg_Camera_reset, Player(7) )
    call TriggerRegisterPlayerEventEndCinematic( gg_trg_Camera_reset, Player(8) )
    call TriggerRegisterPlayerEventEndCinematic( gg_trg_Camera_reset, Player(9) )
    call TriggerRegisterPlayerEventEndCinematic( gg_trg_Camera_reset, Player(10) )
    call TriggerRegisterPlayerEventEndCinematic( gg_trg_Camera_reset, Player(11) )
    call TriggerAddAction( gg_trg_Camera_reset, function Trig_Camera_reset_Actions )
endfunction

//===========================================================================
// Trigger: Apm
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library Apm needs BasicFunctions


globals
    integer array nbClicsOnSlide
    real array timeOnSlide
endglobals



function InitTrig_Apm takes nothing returns nothing
    local integer i = 0
    loop
        exitwhen (i > 11)
            set nbClicsOnSlide[i] = 0
            set timeOnSlide[i] = 0.
        set i = i + 1
    endloop
endfunction



function DisplayApm takes integer playerId returns nothing
    local real time = timeOnSlide[playerId]
    local integer clics 
    local integer apm
    if (time > 0.) then
        set clics = nbClicsOnSlide[playerId]
        set apm = R2I(I2R(clics) * 60. / time)
        call Text_P(Player(playerId), udg_colorCode[playerId] + "clics : " + I2S(clics) + ",  time : " + I2S(R2I(time)) + ",  apm : " + I2S(apm))
    else
        call Text_P(Player(playerId), udg_colorCode[playerId] + "unknown")
    endif
endfunction


function DisplayApmAll takes integer playerId returns nothing
    local integer clics
    local real time
    local integer apm
    
    local integer i = 0
    loop
        exitwhen (i > 11)
            if (udg_escapers.get(i) != 0) then
                set time = timeOnSlide[i]
                if (time > 0.) then
                    set clics = nbClicsOnSlide[i]
                    set apm = R2I( I2R(clics) * 60. / time )
                    call Text_P(Player(playerId), udg_colorCode[i] + GetPlayerName(Player(i)) + ":  clics : " + I2S(clics) + ",  time : " + I2S(R2I(time)) + ",  apm : " + I2S(apm))
                else
                    call Text_P(Player(playerId), udg_colorCode[i] + GetPlayerName(Player(i)) + ":  unknown")
                endif
            endif
        set i = i + 1
    endloop
endfunction


endlibrary//===========================================================================
// Trigger: To turn to point
//===========================================================================
//TESH.scrollpos=37
//TESH.alwaysfold=0
library TurnWhileSliding needs Escaper, Apm

function Trig_to_turn_to_point_Conditions takes nothing returns boolean
    local Escaper escaper = Hero2Escaper(GetTriggerUnit())
    return (IsHero(GetTriggerUnit()) and escaper.isSliding() and not IsLastOrderPause())
endfunction


globals
//turn variables
    private unit slider
    private integer n
    private real sliderX
    private real sliderY
    private widget orderWidget
    private real orderX
    private real orderY
    private real angle
    
//drunk variables
    boolean array udg_isDrunk
    real array udg_drunk
    integer array udg_drunkLevel
    constant real INITIAL_DRUNK = 10.
    effect array udg_drunkEffect
    string array DRUNK_EFFECTS
    constant string DRUNK_EFFECT_PETIT = "Abilities\\Weapons\\BloodElfMissile\\BloodElfMissile.mdl"
    constant string DRUNK_EFFECT_MOYEN = "Abilities\\Weapons\\ChimaeraAcidMissile\\ChimaeraAcidMissile.mdl"
    constant string DRUNK_EFFECT_GROS = "Abilities\\Weapons\\GreenDragonMissile\\GreenDragonMissile.mdl"
endglobals


function Trig_to_turn_to_point_Actions takes nothing returns nothing
//init variables
    set slider = GetTriggerUnit()
    set n = GetUnitUserData(slider)
    set sliderX = GetUnitX(slider)
    set sliderY = GetUnitY(slider)
    set orderX = GetOrderPointX()
    set orderY = GetOrderPointY()
    
//stop hero
    call StopUnit(slider)
    
//set angle
    //if (udg_isMirrorModeOn_j[n]) then
    //    set angle = Atan2( sliderY - orderY, sliderX - orderX) * bj_RADTODEG
    //else
      set angle = Atan2(orderY - sliderY, orderX - sliderX) * bj_RADTODEG
    //endif
    
//drunk mode
    if (udg_isDrunk[n]) then
        if (GetRandomInt(1,2) == 1) then
            set angle = angle + udg_drunk[n]
        else
            set angle = angle - udg_drunk[n]
        endif
    endif
    
//turn
    call SetUnitFacing(slider, angle)
        
//save click
    set lastClickedX[n] = orderX
    set lastClickedY[n] = orderY
    set isLastTargetALocation[n] = true
    
    set nbClicsOnSlide[n] = nbClicsOnSlide[n] + 1
endfunction

//===========================================================================
function InitTrig_To_turn_to_point takes nothing returns nothing
    local integer i
    set gg_trg_To_turn_to_point = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(gg_trg_To_turn_to_point, EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER)
    call TriggerAddCondition(gg_trg_To_turn_to_point, Condition( function Trig_to_turn_to_point_Conditions))
    call TriggerAddAction(gg_trg_To_turn_to_point, function Trig_to_turn_to_point_Actions)
    set i = 0
    loop
        exitwhen (i > 11)
            set udg_drunk[i] = INITIAL_DRUNK
        set i = i + 1
    endloop
    set DRUNK_EFFECTS[1] = DRUNK_EFFECT_PETIT
    set DRUNK_EFFECTS[2] = DRUNK_EFFECT_MOYEN
    set DRUNK_EFFECTS[3] = DRUNK_EFFECT_GROS
endfunction
//===========================================================================
// Trigger: To turn to widget
//===========================================================================
//TESH.scrollpos=12
//TESH.alwaysfold=0
function Trig_to_turn_to_widget_Conditions takes nothing returns boolean
    local Escaper escaper = Hero2Escaper(GetTriggerUnit())
    return (IsHero(GetTriggerUnit()) and escaper.isSliding())
endfunction


function Trig_to_turn_to_widget_Actions takes nothing returns nothing
//init variables
    set slider = GetTriggerUnit()
    set n = GetUnitUserData(slider)
    set sliderX = GetUnitX(slider)
    set sliderY = GetUnitY(slider)
    set orderWidget = GetOrderTarget()
    set orderX = GetWidgetX(orderWidget)
    set orderY = GetWidgetY(orderWidget)
    
//stop hero
    call StopUnit(slider)
    
//set angle
    //if (udg_isMirrorModeOn_j[n]) then
    //    set angle = Atan2( sliderY - orderY, sliderX - orderX) * bj_RADTODEG
    //else
    set angle = Atan2( orderY - sliderY, orderX - sliderX) * bj_RADTODEG
    //endif

//drunk mode
    if (udg_isDrunk[n]) then
        if (GetRandomInt(1,2) == 1) then
            set angle = angle + udg_drunk[n]
        else
            set angle = angle - udg_drunk[n]
        endif
    endif
    
//turn hero
    call SetUnitFacing(slider, angle)
    
//save click
    set lastClickedWidgets[n] = orderWidget
    set lastClickedX[n] = orderX
    set lastClickedY[n] = orderY
    set isLastTargetALocation[n] = false
    
    set nbClicsOnSlide[n] = nbClicsOnSlide[n] + 1
endfunction

//===========================================================================
function InitTrig_To_turn_to_widget takes nothing returns nothing
    set gg_trg_To_turn_to_widget = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_To_turn_to_widget, EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER )
    call TriggerAddCondition( gg_trg_To_turn_to_widget, Condition( function Trig_to_turn_to_widget_Conditions ) )
    call TriggerAddAction( gg_trg_To_turn_to_widget, function Trig_to_turn_to_widget_Actions )
endfunction

endlibrary
//===========================================================================
// Trigger: Auto continue after sliding
//===========================================================================
//TESH.scrollpos=4
//TESH.alwaysfold=0
library AutoContinueAfterSliding //needs AddDelay

globals
    real array lastClickedX
    real array lastClickedY
    widget array lastClickedWidgets
    boolean array isLastTargetALocation
    boolean array udg_autoContinueAfterSliding
    
    private constant real ECART_MAX_ANGLE = 45.
endglobals


function AutoContinueAfterSliding takes integer n returns nothing
    local unit hero = udg_escapers.get(n).getHero()
//vérification de l'angle
    local real angleHero2Target = Atan2(lastClickedY[n] - GetUnitY(hero), lastClickedX[n] - GetUnitX(hero)) * bj_RADTODEG
    local real diffAngle = RAbsBJ(angleHero2Target - GetUnitFacing(hero))
    if (diffAngle > ECART_MAX_ANGLE and diffAngle < 360. - ECART_MAX_ANGLE) then //écart trop grand
        return
    endif
    
//cas dernier clic : un point
    if (isLastTargetALocation[n]) then 
        call IssuePointOrder(hero, "move", lastClickedX[n], lastClickedY[n])
        debug call BJDebugMsg("acas move to : " + R2S(lastClickedX[n]) + ", " + R2S(lastClickedY[n]))
        
//cas dernier clic : pas un point
    else
        //dernier widget cliqué n'existe pas (donc aucun clic effectué pendant le slide)
        if (lastClickedWidgets[n] == null) then
            return
        else
            //cible n'a pas bougé
            if (GetWidgetX(lastClickedWidgets[n]) == lastClickedX[n] and GetWidgetY(lastClickedWidgets[n]) == lastClickedY[n]) then
                //ordre clic droit vers cible
                call IssueTargetOrder(hero, "smart", lastClickedWidgets[n])
            else
                //bouger vers ancien endroit du widget
                call IssuePointOrder(hero, "move", lastClickedX[n], lastClickedY[n])
            endif
        endif
    endif
endfunction


function ClearLastClickSave takes integer n returns nothing
    set isLastTargetALocation[n] = false
    set lastClickedWidgets[n] = null
endfunction


//===========================================================================
function InitTrig_Auto_continue_after_sliding takes nothing returns nothing
    local integer i = 0
    loop
        exitwhen (i > 11)
            set udg_autoContinueAfterSliding[i] = true
        set i = i + 1
    endloop
endfunction


endlibrary//===========================================================================
// Trigger: Afk mode init
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
library afkMode



globals
    real timeMinAfk = 30.
    private constant real Z = -50.
    private constant real SIZE = 8.
    private constant real TRANSPARENCY = 0.
    
    boolean array isAfk
    timer array afkModeTimers
    texttag array afkModeTextTags
    timer killAllAfkTimer = CreateTimer()
endglobals


function AreAllAliveHeroesAfk takes nothing returns boolean //false if noone is dead
    local boolean someoneAlive = false
    local boolean someoneDead = false
    local integer i = 0
    loop
        exitwhen (i > 11)
            if (udg_escapers.get(i).getHero() != null) then
                if (IsUnitAliveBJ(udg_escapers.get(i).getHero())) then
                    set someoneAlive = true
                    if (not isAfk[i]) then
                        return false
                    endif
                else
                    set someoneDead = true
                endif
            endif
        set i = i + 1
    endloop
    return someoneAlive and someoneDead
endfunction


function KillAllHeroesIfAfk takes nothing returns nothing
    local integer i = 0    
    if (AreAllAliveHeroesAfk()) then
        loop
            exitwhen (i > 11)
                if (IsUnitAliveBJ(udg_escapers.get(i).getHero()) and isAfk[i]) then
                    call udg_escapers.get(i).kill()
                endif
            set i = i + 1
        endloop
    endif
endfunction


function KillAllHeroesAfkInFiveSeconds takes nothing returns nothing
    call TimerStart(killAllAfkTimer, 5., false, function KillAllHeroesIfAfk)
endfunction


function SetAfkMode takes integer playerId returns nothing
    if (afkModeTextTags[playerId] != null) then
        call DestroyTextTag(afkModeTextTags[playerId])
    endif
    set afkModeTextTags[playerId] = CreateTextTagUnitBJ( udg_colorCode[playerId]+"AFK", udg_escapers.get(playerId).getHero(), Z, SIZE, 100, 100, 100, TRANSPARENCY )
    set isAfk[playerId] = true
endfunction


function StopAfk takes integer playerId returns nothing
    if (isAfk[playerId]) then
        set isAfk[playerId] = false
        call DestroyTextTag(afkModeTextTags[playerId])
        set afkModeTextTags[playerId] = null
    endif
endfunction


//! textmacro AfkModeTimerExpires takes id
function AfkModeTimerExpires_$id$ takes nothing returns nothing
    call SetAfkMode($id$)
    if (AreAllAliveHeroesAfk()) then
        call KillAllHeroesAfkInFiveSeconds()
    endif
endfunction
//! endtextmacro

//! runtextmacro AfkModeTimerExpires("0")
//! runtextmacro AfkModeTimerExpires("1")
//! runtextmacro AfkModeTimerExpires("2")
//! runtextmacro AfkModeTimerExpires("3")
//! runtextmacro AfkModeTimerExpires("4")
//! runtextmacro AfkModeTimerExpires("5")
//! runtextmacro AfkModeTimerExpires("6")
//! runtextmacro AfkModeTimerExpires("7")
//! runtextmacro AfkModeTimerExpires("8")
//! runtextmacro AfkModeTimerExpires("9")
//! runtextmacro AfkModeTimerExpires("10")
//! runtextmacro AfkModeTimerExpires("11")


function GetAfkModeTimeExpiresCodeFromId takes integer id returns code
    //! textmacro GetAfkModeTimeExpiresCodeFromId takes id
    if (id == $id$) then
        return function AfkModeTimerExpires_$id$
    endif
    //! endtextmacro
    
    //! runtextmacro GetAfkModeTimeExpiresCodeFromId("0")
    //! runtextmacro GetAfkModeTimeExpiresCodeFromId("1")
    //! runtextmacro GetAfkModeTimeExpiresCodeFromId("2")
    //! runtextmacro GetAfkModeTimeExpiresCodeFromId("3")
    //! runtextmacro GetAfkModeTimeExpiresCodeFromId("4")
    //! runtextmacro GetAfkModeTimeExpiresCodeFromId("5")
    //! runtextmacro GetAfkModeTimeExpiresCodeFromId("6")
    //! runtextmacro GetAfkModeTimeExpiresCodeFromId("7")
    //! runtextmacro GetAfkModeTimeExpiresCodeFromId("8")
    //! runtextmacro GetAfkModeTimeExpiresCodeFromId("9")
    //! runtextmacro GetAfkModeTimeExpiresCodeFromId("10")
    //! runtextmacro GetAfkModeTimeExpiresCodeFromId("11")
    
    return null
endfunction


//===========================================================================
function InitTrig_Afk_mode_init takes nothing returns nothing
    local integer i = 0
    loop
        exitwhen i > 11
            set afkModeTimers[i] = CreateTimer()
            set isAfk[i] = false
            set afkModeTextTags[i] = null
        set i = i + 1
    endloop
endfunction


endlibrary

//===========================================================================
// Trigger: Afk mode ordre recu
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
function Trig_afk_mode_ordre_recu_Actions takes nothing returns nothing
    local integer n
    if (IsHero(GetTriggerUnit())) then
        set n = GetUnitUserData(GetTriggerUnit())
        call StopAfk(n)
        call TimerStart(afkModeTimers[n], timeMinAfk, false, GetAfkModeTimeExpiresCodeFromId(n))
    endif
endfunction

//===========================================================================
function InitTrig_Afk_mode_ordre_recu takes nothing returns nothing
    set gg_trg_Afk_mode_ordre_recu = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Afk_mode_ordre_recu, EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Afk_mode_ordre_recu, EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER )
    call TriggerAddAction( gg_trg_Afk_mode_ordre_recu, function Trig_afk_mode_ordre_recu_Actions )
endfunction

//===========================================================================
// Trigger: A player leaves
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
function Trig_a_player_leaves_Actions takes nothing returns nothing
    local integer n = GetPlayerId(GetTriggerPlayer())
    call udg_escapers.remove(n)
    call StopAfk(n)
    call DisplayTextToForce(GetPlayersAll(), udg_colorCode[n] + "This is too difficult for " + GetPlayerName(GetTriggerPlayer()) + ", (s)he has left the game." )
    call StartSound(gg_snd_noob)
    //set NbPlayersMinimumThree_nbPlayers = NbPlayersMinimumThree_nbPlayers - 1
endfunction



//===========================================================================
function InitTrig_A_player_leaves takes nothing returns nothing
    local integer i = 0
    set gg_trg_A_player_leaves = CreateTrigger()
    loop
        exitwhen i > 11
        call TriggerRegisterPlayerEventLeave(gg_trg_A_player_leaves, Player(i))
        set i = i + 1
    endloop       
    call TriggerAddAction( gg_trg_A_player_leaves, function Trig_a_player_leaves_Actions )
endfunction

//===========================================================================
// Trigger: Antisave
//===========================================================================
function Trig_Antisave_Actions takes nothing returns nothing
    call TriggerExecute( GetTriggeringTrigger() )
endfunction

//===========================================================================
function InitTrig_Antisave takes nothing returns nothing
    set gg_trg_Antisave = CreateTrigger(  )
    call TriggerRegisterGameLoadedEventBJ( gg_trg_Antisave )
    call TriggerAddAction( gg_trg_Antisave, function Trig_Antisave_Actions )
endfunction

//===========================================================================
// Trigger: Antisave warning
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
function Trig_antisave_warning_Actions takes nothing returns nothing
    if (IsTriggerEnabled(gg_trg_Antisave)) then
        call DisplayTextToForce(GetPlayersAll(), udg_colorCode[RED] + "Warning ! Loading the game won't work !")
    else
        call DisplayTextToForce(GetPlayersAll(), udg_colorCode[RED] + "Don't forget to type -saveTerrain to save the whole terrain before saving the game. (load with -loadTerrain)")
    endif
endfunction


//===========================================================================
function InitTrig_Antisave_warning takes nothing returns nothing
    set gg_trg_Antisave_warning = CreateTrigger(  )
    call TriggerRegisterGameSavedEventBJ( gg_trg_Antisave_warning )
    call TriggerAddAction( gg_trg_Antisave_warning, function Trig_antisave_warning_Actions )
endfunction

//===========================================================================
// Trigger: InvisUnit is getting damage
//===========================================================================
//TESH.scrollpos=15
//TESH.alwaysfold=0
//évènement ajouté à la création de l'unité invisible

function Trig_invisUnit_dies_Actions takes nothing returns nothing
    local unit invisUnit = GetTriggerUnit()
    local integer n = GetUnitUserData(invisUnit)
    local Escaper escaper = udg_escapers.get(n)
    local unit killingUnit = GetEventDamageSource()
    local string effectStr
    local effect eff
    local real x
    local real y
    
    if (not escaper.isAlive()) then
        set invisUnit = null
        set killingUnit = null
        return
    endif

    if (escaper.isGodModeOn()) then
        if (escaper.doesGodModeKills()) then
            if(GetUnitUserData(killingUnit) != 0)then
                call Monster(GetUnitUserData(killingUnit)).killUnit() //on ne tue pas directement le monstre, pour pouvoir exécuter des actions secondaires
            else
                call KillUnit(killingUnit)
            endif
        endif
        set x = GetUnitX(killingUnit)
        set y = GetUnitY(killingUnit)
        set eff = AddSpecialEffect(GM_KILLING_EFFECT, x, y)
        call DestroyEffect(eff)
        set eff = null
        set invisUnit = null
        set killingUnit = null
        return  
    endif

    call escaper.kill()

    //effet de tuation du héros par le monstre, suivant le type du monstre
    set effectStr = udg_monsterTypes.monsterUnit2KillEffectStr(killingUnit)
    if (effectStr != null) then
        set x = GetUnitX(invisUnit)
        set y = GetUnitY(invisUnit)
        set eff = AddSpecialEffect(effectStr, x, y)
        call TriggerSleepAction(3)
        call DestroyEffect(eff)
        set eff = null
    endif

    set invisUnit = null
    set killingUnit = null
endfunction

//===========================================================================
function InitTrig_InvisUnit_is_getting_damage takes nothing returns nothing
    set gg_trg_InvisUnit_is_getting_damage = CreateTrigger()
    call TriggerAddAction(gg_trg_InvisUnit_is_getting_damage, function Trig_invisUnit_dies_Actions)
endfunction

//===========================================================================
// Trigger: A hero dies check if all dead and sounds
//===========================================================================
//TESH.scrollpos=26
//TESH.alwaysfold=0
globals
    integer udg_nbKilled = 0
endglobals


function Trig_a_hero_dies_Conditions takes nothing returns boolean
    return IsHero(GetTriggerUnit())
endfunction


function Trig_a_hero_dies_Actions takes nothing returns nothing
    local integer n = GetUnitUserData(GetTriggerUnit())
    local integer nbAlive = 0
    local boolean last = false
    local integer i

    set udg_nbKilled = udg_nbKilled + 1
    if (udg_nbKilled == 3 and udg_tripleKillSoundOn) then
        call StartSound(gg_snd_multisquish)
        set udg_nbKilled = 0
    endif

    set i = 0
    loop
        exitwhen (i > 11)
            if (udg_escapers.get(i).isAlive()) then
                set nbAlive = nbAlive + 1
            endif
        set i = i + 1
    endloop

    if (nbAlive == 0) then
        call TriggerExecute(gg_trg_Lose_a_life_and_res)
        call TriggerSleepAction(2)
        call StartSound(gg_snd_questFailed)
        set last = true
    else
        if (nbAlive == 1) then
            call StartSound( gg_snd_warning )
        endif
    endif
    
    if (isAfk[n]) then
        call DestroyTextTag(afkModeTextTags[n])
    else
        call PauseTimer(afkModeTimers[n])
    endif
    
    if (AreAllAliveHeroesAfk()) then
        call KillAllHeroesAfkInFiveSeconds()
    endif
        
    if (last) then //à cause du sleepAction plus haut
        call TriggerSleepAction( 3 )
    else
        call TriggerSleepAction( 5 )
    endif

    call SetUnitAnimation(GetTriggerUnit(), "stand")
    set udg_nbKilled = udg_nbKilled - 1
endfunction

//===========================================================================
function InitTrig_A_hero_dies_check_if_all_dead_and_sounds takes nothing returns nothing
    set gg_trg_A_hero_dies_check_if_all_dead_and_sounds = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_A_hero_dies_check_if_all_dead_and_sounds, EVENT_PLAYER_UNIT_DEATH )
    call TriggerAddCondition( gg_trg_A_hero_dies_check_if_all_dead_and_sounds, Condition( function Trig_a_hero_dies_Conditions ) )
    call TriggerAddAction( gg_trg_A_hero_dies_check_if_all_dead_and_sounds, function Trig_a_hero_dies_Actions )
endfunction

//===========================================================================
// Trigger: Lose a life and res
//
// actions when the last hero alive dies
//===========================================================================
//TESH.scrollpos=0
//TESH.alwaysfold=0
function Trig_Lose_a_life_and_res_Actions takes nothing returns nothing
    local integer i
    call udg_lives.loseALife()
    if (udg_lives.get() < 0) then
        call DisplayTextToForce( GetPlayersAll(), "You have no more lives !" )
        call TriggerSleepAction( 2 )
        call DisplayTextToForce( GetPlayersAll(), "The game will restart in 10 seconds." )
        call TriggerSleepAction( 10.00 )
        call udg_levels.restartTheGame()
    else
        if (udg_changeAllTerrainsAtRevive) then
            call TriggerSleepAction( 6.00 )
            call ChangeAllTerrains("normal")
            call TriggerSleepAction( 2.00 )
        else
            call TriggerSleepAction( 8.00 )
        endif
        set i = 0
        loop
            exitwhen (i > 11)
                if (udg_escapers.get(i) != 0) then
                    call udg_escapers.get(i).reviveAtStart()
                endif
            set i = i + 1
        endloop
        call Text_A("|cff5c2e2eYou have lost a life !")
        //set AnticheatTeleport_justRevived = true
    endif
endfunction

//===========================================================================
function InitTrig_Lose_a_life_and_res takes nothing returns nothing
    set gg_trg_Lose_a_life_and_res = CreateTrigger(  )
    call TriggerAddAction( gg_trg_Lose_a_life_and_res, function Trig_Lose_a_life_and_res_Actions )
endfunction

//===========================================================================
// Trigger: Sound monster dies
//===========================================================================
function Trig_Sound_monster_dies_Conditions takes nothing returns boolean
    if ( not ( GetOwningPlayer(GetTriggerUnit()) == Player(PLAYER_NEUTRAL_AGGRESSIVE) ) ) then
        return false
    endif
    return true
endfunction

function Trig_Sound_monster_dies_Actions takes nothing returns nothing
    call PlaySoundBJ( gg_snd_goodJob )
endfunction

//===========================================================================
function InitTrig_Sound_monster_dies takes nothing returns nothing
    set gg_trg_Sound_monster_dies = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Sound_monster_dies, EVENT_PLAYER_UNIT_DEATH )
    call TriggerAddCondition( gg_trg_Sound_monster_dies, Condition( function Trig_Sound_monster_dies_Conditions ) )
    call TriggerAddAction( gg_trg_Sound_monster_dies, function Trig_Sound_monster_dies_Actions )
endfunction

//===========================================================================
function InitCustomTriggers takes nothing returns nothing
    call InitTrig_Constants(  )
    call InitTrig_Text(  )
    call InitTrig_Init_terrain_limit_variables(  )
    call InitTrig_Init_colorCodes(  )
    call InitTrig_Basic_functions(  )
    call InitTrig_Functions_on_numbers(  )
    call InitTrig_Ascii(  )
    call InitTrig_Decode_string(  )
    call InitTrig_View_all_hide_all(  )
    call InitTrig_Immolation_skills(  )
    call InitTrig_MonsterType(  )
    call InitTrig_MonsterTypeArray(  )
    call InitTrig_Monster_creation_functions(  )
    call InitTrig_Monster(  )
    call InitTrig____trig_Monsters_clickable_set_life(  )
    call InitTrig_MonsterNoMove(  )
    call InitTrig_MonsterNoMoveArray(  )
    call InitTrig_MonsterSimplePatrol(  )
    call InitTrig_MonsterSimplePatrolArray(  )
    call InitTrig_MonsterMultiplePatrols(  )
    call InitTrig_MonsterMultiplePatrolsArray(  )
    call InitTrig_MonsterSpawn(  )
    call InitTrig_MonsterSpawnArray(  )
    call InitTrig_Terrain_type_functions(  )
    call InitTrig_TerrainType(  )
    call InitTrig_TerrainTypeWalk(  )
    call InitTrig_TerrainTypeDeath_functions(  )
    call InitTrig_TerrainTypeDeath_KillingTimers(  )
    call InitTrig_TerrainTypeDeath(  )
    call InitTrig_TerrainTypeSlide(  )
    call InitTrig_TerrainTypeArray(  )
    call InitTrig_Time_of_game_trigger(  )
    call InitTrig_Lives_and_game_time(  )
    call InitTrig_Meteor(  )
    call InitTrig_MeteorArray(  )
    call InitTrig_Meteor_functions(  )
    call InitTrig_Right_click_on_widget(  )
    call InitTrig_Meteor_being_used(  )
    call InitTrig_Stop_using_normal_meteor(  )
    call InitTrig_Effect_meteor_on_pick_up(  )
    call InitTrig_VisibilityModifier(  )
    call InitTrig_VisibilityModifierArray(  )
    call InitTrig_StartAndEnd(  )
    call InitTrig_Triggers(  )
    call InitTrig_Level(  )
    call InitTrig____Level_functions(  )
    call InitTrig____Trig_checkpoint_revive_heroes(  )
    call InitTrig_LevelArray(  )
    call InitTrig_EscaperEffect_functions(  )
    call InitTrig_EscaperEffect(  )
    call InitTrig_EscaperEffectArray(  )
    call InitTrig_Escaper_functions(  )
    call InitTrig_Escaper_disco(  )
    call InitTrig_Escaper(  )
    call InitTrig_EscaperArray(  )
    call InitTrig_EscaperSavedCommands(  )
    call InitTrig_Make(  )
    call InitTrig_Monster_making_no_move_Actions(  )
    call InitTrig_MakeMonsterNoMove(  )
    call InitTrig_Monster_making_simple_patrol_Actions(  )
    call InitTrig_MakeMonsterSimplePatrol(  )
    call InitTrig_Monster_making_multiple_patrols_Actions(  )
    call InitTrig_MakeMonsterMultiplePatrols(  )
    call InitTrig_Monster_spawn_making_Actions(  )
    call InitTrig_MakeMonsterSpawn(  )
    call InitTrig_Monster_delete_Actions(  )
    call InitTrig_MakeDeleteMonsters(  )
    call InitTrig_Meteor_making_Actions(  )
    call InitTrig_MakeMeteor(  )
    call InitTrig_Meteor_delete_Actions(  )
    call InitTrig_MakeDeleteMeteors(  )
    call InitTrig_Terrain_making_Actions(  )
    call InitTrig_MakeTerrainCreate(  )
    call InitTrig_Terrain_copy_paste_Actions(  )
    call InitTrig_MakeTerrainCopyPaste(  )
    call InitTrig_Terrain_vertical_symmetry_Actions(  )
    call InitTrig_MakeTerrainVerticalSymmetry(  )
    call InitTrig_Terrain_horizontal_symmetry_Actions(  )
    call InitTrig_MakeTerrainHorizontalSymmetry(  )
    call InitTrig_Make_exchange_terrains_Actions(  )
    call InitTrig_MakeExchangeTerrains(  )
    call InitTrig_Start_making_Actions(  )
    call InitTrig_MakeStart(  )
    call InitTrig_End_making_Actions(  )
    call InitTrig_MakeEnd(  )
    call InitTrig_VisibilityModifier_making_Actions(  )
    call InitTrig_MakeVisibilityModifier(  )
    call InitTrig_Getting_terrain_type_info_Actions(  )
    call InitTrig_MakeGetTerrainType(  )
    call InitTrig_MakeAction(  )
    call InitTrig_MakeMonsterAction(  )
    call InitTrig_MakeDeleteMonstersAction(  )
    call InitTrig_MakeMeteorAction(  )
    call InitTrig_MakeDeleteMeteorsAction(  )
    call InitTrig_MakeTerrainCreateAction(  )
    call InitTrig_MakeTerrainCopyPasteAction(  )
    call InitTrig_MakeTerrainVerticalSymmetryAction(  )
    call InitTrig_MakeTerrainHorizontalSymmetryAction(  )
    call InitTrig_MakeVisibilityModifierAction(  )
    call InitTrig_MakeLastActions(  )
    call InitTrig_Command_functions(  )
    call InitTrig_Teleport_once_only(  )
    call InitTrig_Teleport(  )
    call InitTrig_Autorevive(  )
    call InitTrig_Command_all(  )
    call InitTrig_Command_red(  )
    call InitTrig_Command_cheat(  )
    call InitTrig_Command_make(  )
    call InitTrig_Command_max(  )
    call InitTrig_Command_true_max(  )
    call InitTrig_Command_execution(  )
    call InitTrig_Slide(  )
    call InitTrig_CheckTerrain(  )
    call InitTrig_All_terrain_functions(  )
    call InitTrig_Terrain_type_ascii_conversion(  )
    call InitTrig_Terrain_type_max(  )
    call InitTrig_Terrain_type_grass(  )
    call InitTrig_Terrain_type_names_and_data(  )
    call InitTrig_Terrain_functions(  )
    call InitTrig_Terrain_type_from_string(  )
    call InitTrig_Modify_terrain_functions(  )
    call InitTrig_Terrain_modifying(  )
    call InitTrig_Change_one_terrain(  )
    call InitTrig_Change_all_terrains(  )
    call InitTrig_Exchange_terrains(  )
    call InitTrig_Randomize_terrains(  )
    call InitTrig_Reinit_terrains(  )
    call InitTrig_Reinit_terrains_position_Change_variations_and_ut_at_beginning(  )
    call InitTrig_Save_load_terrain_without_name(  )
    call InitTrig_Save_load_terrain_with_name(  )
    call InitTrig_struct_StringArrayForCache(  )
    call InitTrig_Save_terrain_config(  )
    call InitTrig_Save_terrain(  )
    call InitTrig_Save_monster_types(  )
    call InitTrig_Save_levels(  )
    call InitTrig_SAVE_MAP_in_cache(  )
    call InitTrig_Init_lives(  )
    call InitTrig_Init_escapers(  )
    call InitTrig_Init_terrain_types(  )
    call InitTrig_Init_monster_types(  )
    call InitTrig_Init_struct_levels(  )
    call InitTrig_Init_levels(  )
    call InitTrig_Forces_ally(  )
    call InitTrig_Camera(  )
    call InitTrig_No_selection_circle(  )
    call InitTrig_Welcome_message(  )
    call InitTrig_Allways_day(  )
    call InitTrig_Start_sound(  )
    call InitTrig_Heroes(  )
    call InitTrig_Has_max_name(  )
    call InitTrig_Ajout_evenement_kan_plein_joueurs(  )
    call InitTrig_Prouve_is_real_max1(  )
    call InitTrig_Prouve_is_real_max2(  )
    call InitTrig_Command_shortcuts_functions(  )
    call InitTrig_Using_shortcut(  )
    call InitTrig_Commands_1(  )
    call InitTrig_Commands_2(  )
    call InitTrig_Colors(  )
    call InitTrig_Effects(  )
    call InitTrig_Red_commands(  )
    call InitTrig_Map_description(  )
    call InitTrig_Contact(  )
    call InitTrig_Command_shortcuts(  )
    call InitTrig_Adding_quests(  )
    call InitTrig_Camera_reset(  )
    call InitTrig_Apm(  )
    call InitTrig_To_turn_to_point(  )
    call InitTrig_To_turn_to_widget(  )
    call InitTrig_Auto_continue_after_sliding(  )
    call InitTrig_Afk_mode_init(  )
    call InitTrig_Afk_mode_ordre_recu(  )
    call InitTrig_A_player_leaves(  )
    call InitTrig_Antisave(  )
    call InitTrig_Antisave_warning(  )
    call InitTrig_InvisUnit_is_getting_damage(  )
    call InitTrig_A_hero_dies_check_if_all_dead_and_sounds(  )
    call InitTrig_Lose_a_life_and_res(  )
    call InitTrig_Sound_monster_dies(  )
endfunction

//===========================================================================
function RunInitializationTriggers takes nothing returns nothing
    call ConditionalTriggerExecute( gg_trg_Init_terrain_limit_variables )
    call ConditionalTriggerExecute( gg_trg_Init_colorCodes )
    call ConditionalTriggerExecute( gg_trg_Forces_ally )
    call ConditionalTriggerExecute( gg_trg_Camera )
    call ConditionalTriggerExecute( gg_trg_No_selection_circle )
    call ConditionalTriggerExecute( gg_trg_Welcome_message )
    call ConditionalTriggerExecute( gg_trg_Allways_day )
    call ConditionalTriggerExecute( gg_trg_Ajout_evenement_kan_plein_joueurs )
    call ConditionalTriggerExecute( gg_trg_Adding_quests )
endfunction

//***************************************************************************
//*
//*  Players
//*
//***************************************************************************

function InitCustomPlayerSlots takes nothing returns nothing

    // Player 0
    call SetPlayerStartLocation( Player(0), 0 )
    call SetPlayerColor( Player(0), ConvertPlayerColor(0) )
    call SetPlayerRacePreference( Player(0), RACE_PREF_HUMAN )
    call SetPlayerRaceSelectable( Player(0), false )
    call SetPlayerController( Player(0), MAP_CONTROL_USER )

    // Player 1
    call SetPlayerStartLocation( Player(1), 1 )
    call SetPlayerColor( Player(1), ConvertPlayerColor(1) )
    call SetPlayerRacePreference( Player(1), RACE_PREF_ORC )
    call SetPlayerRaceSelectable( Player(1), false )
    call SetPlayerController( Player(1), MAP_CONTROL_USER )

    // Player 2
    call SetPlayerStartLocation( Player(2), 2 )
    call SetPlayerColor( Player(2), ConvertPlayerColor(2) )
    call SetPlayerRacePreference( Player(2), RACE_PREF_UNDEAD )
    call SetPlayerRaceSelectable( Player(2), false )
    call SetPlayerController( Player(2), MAP_CONTROL_USER )

    // Player 3
    call SetPlayerStartLocation( Player(3), 3 )
    call SetPlayerColor( Player(3), ConvertPlayerColor(3) )
    call SetPlayerRacePreference( Player(3), RACE_PREF_NIGHTELF )
    call SetPlayerRaceSelectable( Player(3), false )
    call SetPlayerController( Player(3), MAP_CONTROL_USER )

    // Player 4
    call SetPlayerStartLocation( Player(4), 4 )
    call SetPlayerColor( Player(4), ConvertPlayerColor(4) )
    call SetPlayerRacePreference( Player(4), RACE_PREF_HUMAN )
    call SetPlayerRaceSelectable( Player(4), false )
    call SetPlayerController( Player(4), MAP_CONTROL_USER )

    // Player 5
    call SetPlayerStartLocation( Player(5), 5 )
    call SetPlayerColor( Player(5), ConvertPlayerColor(5) )
    call SetPlayerRacePreference( Player(5), RACE_PREF_ORC )
    call SetPlayerRaceSelectable( Player(5), false )
    call SetPlayerController( Player(5), MAP_CONTROL_USER )

    // Player 6
    call SetPlayerStartLocation( Player(6), 6 )
    call SetPlayerColor( Player(6), ConvertPlayerColor(6) )
    call SetPlayerRacePreference( Player(6), RACE_PREF_UNDEAD )
    call SetPlayerRaceSelectable( Player(6), false )
    call SetPlayerController( Player(6), MAP_CONTROL_USER )

    // Player 7
    call SetPlayerStartLocation( Player(7), 7 )
    call SetPlayerColor( Player(7), ConvertPlayerColor(7) )
    call SetPlayerRacePreference( Player(7), RACE_PREF_NIGHTELF )
    call SetPlayerRaceSelectable( Player(7), false )
    call SetPlayerController( Player(7), MAP_CONTROL_USER )

    // Player 8
    call SetPlayerStartLocation( Player(8), 8 )
    call SetPlayerColor( Player(8), ConvertPlayerColor(8) )
    call SetPlayerRacePreference( Player(8), RACE_PREF_HUMAN )
    call SetPlayerRaceSelectable( Player(8), false )
    call SetPlayerController( Player(8), MAP_CONTROL_USER )

    // Player 9
    call SetPlayerStartLocation( Player(9), 9 )
    call SetPlayerColor( Player(9), ConvertPlayerColor(9) )
    call SetPlayerRacePreference( Player(9), RACE_PREF_ORC )
    call SetPlayerRaceSelectable( Player(9), false )
    call SetPlayerController( Player(9), MAP_CONTROL_USER )

    // Player 10
    call SetPlayerStartLocation( Player(10), 10 )
    call SetPlayerColor( Player(10), ConvertPlayerColor(10) )
    call SetPlayerRacePreference( Player(10), RACE_PREF_UNDEAD )
    call SetPlayerRaceSelectable( Player(10), false )
    call SetPlayerController( Player(10), MAP_CONTROL_USER )

    // Player 11
    call SetPlayerStartLocation( Player(11), 11 )
    call SetPlayerColor( Player(11), ConvertPlayerColor(11) )
    call SetPlayerRacePreference( Player(11), RACE_PREF_NIGHTELF )
    call SetPlayerRaceSelectable( Player(11), false )
    call SetPlayerController( Player(11), MAP_CONTROL_USER )

endfunction

function InitCustomTeams takes nothing returns nothing
    // Force: TRIGSTR_016
    call SetPlayerTeam( Player(0), 0 )
    call SetPlayerState( Player(0), PLAYER_STATE_ALLIED_VICTORY, 1 )

    // Force: TRIGSTR_017
    call SetPlayerTeam( Player(1), 1 )
    call SetPlayerState( Player(1), PLAYER_STATE_ALLIED_VICTORY, 1 )
    call SetPlayerTeam( Player(2), 1 )
    call SetPlayerState( Player(2), PLAYER_STATE_ALLIED_VICTORY, 1 )
    call SetPlayerTeam( Player(3), 1 )
    call SetPlayerState( Player(3), PLAYER_STATE_ALLIED_VICTORY, 1 )
    call SetPlayerTeam( Player(4), 1 )
    call SetPlayerState( Player(4), PLAYER_STATE_ALLIED_VICTORY, 1 )
    call SetPlayerTeam( Player(5), 1 )
    call SetPlayerState( Player(5), PLAYER_STATE_ALLIED_VICTORY, 1 )
    call SetPlayerTeam( Player(6), 1 )
    call SetPlayerState( Player(6), PLAYER_STATE_ALLIED_VICTORY, 1 )
    call SetPlayerTeam( Player(7), 1 )
    call SetPlayerState( Player(7), PLAYER_STATE_ALLIED_VICTORY, 1 )
    call SetPlayerTeam( Player(8), 1 )
    call SetPlayerState( Player(8), PLAYER_STATE_ALLIED_VICTORY, 1 )
    call SetPlayerTeam( Player(9), 1 )
    call SetPlayerState( Player(9), PLAYER_STATE_ALLIED_VICTORY, 1 )
    call SetPlayerTeam( Player(10), 1 )
    call SetPlayerState( Player(10), PLAYER_STATE_ALLIED_VICTORY, 1 )
    call SetPlayerTeam( Player(11), 1 )
    call SetPlayerState( Player(11), PLAYER_STATE_ALLIED_VICTORY, 1 )

    //   Allied
    call SetPlayerAllianceStateAllyBJ( Player(1), Player(2), true )
    call SetPlayerAllianceStateAllyBJ( Player(1), Player(3), true )
    call SetPlayerAllianceStateAllyBJ( Player(1), Player(4), true )
    call SetPlayerAllianceStateAllyBJ( Player(1), Player(5), true )
    call SetPlayerAllianceStateAllyBJ( Player(1), Player(6), true )
    call SetPlayerAllianceStateAllyBJ( Player(1), Player(7), true )
    call SetPlayerAllianceStateAllyBJ( Player(1), Player(8), true )
    call SetPlayerAllianceStateAllyBJ( Player(1), Player(9), true )
    call SetPlayerAllianceStateAllyBJ( Player(1), Player(10), true )
    call SetPlayerAllianceStateAllyBJ( Player(1), Player(11), true )
    call SetPlayerAllianceStateAllyBJ( Player(2), Player(1), true )
    call SetPlayerAllianceStateAllyBJ( Player(2), Player(3), true )
    call SetPlayerAllianceStateAllyBJ( Player(2), Player(4), true )
    call SetPlayerAllianceStateAllyBJ( Player(2), Player(5), true )
    call SetPlayerAllianceStateAllyBJ( Player(2), Player(6), true )
    call SetPlayerAllianceStateAllyBJ( Player(2), Player(7), true )
    call SetPlayerAllianceStateAllyBJ( Player(2), Player(8), true )
    call SetPlayerAllianceStateAllyBJ( Player(2), Player(9), true )
    call SetPlayerAllianceStateAllyBJ( Player(2), Player(10), true )
    call SetPlayerAllianceStateAllyBJ( Player(2), Player(11), true )
    call SetPlayerAllianceStateAllyBJ( Player(3), Player(1), true )
    call SetPlayerAllianceStateAllyBJ( Player(3), Player(2), true )
    call SetPlayerAllianceStateAllyBJ( Player(3), Player(4), true )
    call SetPlayerAllianceStateAllyBJ( Player(3), Player(5), true )
    call SetPlayerAllianceStateAllyBJ( Player(3), Player(6), true )
    call SetPlayerAllianceStateAllyBJ( Player(3), Player(7), true )
    call SetPlayerAllianceStateAllyBJ( Player(3), Player(8), true )
    call SetPlayerAllianceStateAllyBJ( Player(3), Player(9), true )
    call SetPlayerAllianceStateAllyBJ( Player(3), Player(10), true )
    call SetPlayerAllianceStateAllyBJ( Player(3), Player(11), true )
    call SetPlayerAllianceStateAllyBJ( Player(4), Player(1), true )
    call SetPlayerAllianceStateAllyBJ( Player(4), Player(2), true )
    call SetPlayerAllianceStateAllyBJ( Player(4), Player(3), true )
    call SetPlayerAllianceStateAllyBJ( Player(4), Player(5), true )
    call SetPlayerAllianceStateAllyBJ( Player(4), Player(6), true )
    call SetPlayerAllianceStateAllyBJ( Player(4), Player(7), true )
    call SetPlayerAllianceStateAllyBJ( Player(4), Player(8), true )
    call SetPlayerAllianceStateAllyBJ( Player(4), Player(9), true )
    call SetPlayerAllianceStateAllyBJ( Player(4), Player(10), true )
    call SetPlayerAllianceStateAllyBJ( Player(4), Player(11), true )
    call SetPlayerAllianceStateAllyBJ( Player(5), Player(1), true )
    call SetPlayerAllianceStateAllyBJ( Player(5), Player(2), true )
    call SetPlayerAllianceStateAllyBJ( Player(5), Player(3), true )
    call SetPlayerAllianceStateAllyBJ( Player(5), Player(4), true )
    call SetPlayerAllianceStateAllyBJ( Player(5), Player(6), true )
    call SetPlayerAllianceStateAllyBJ( Player(5), Player(7), true )
    call SetPlayerAllianceStateAllyBJ( Player(5), Player(8), true )
    call SetPlayerAllianceStateAllyBJ( Player(5), Player(9), true )
    call SetPlayerAllianceStateAllyBJ( Player(5), Player(10), true )
    call SetPlayerAllianceStateAllyBJ( Player(5), Player(11), true )
    call SetPlayerAllianceStateAllyBJ( Player(6), Player(1), true )
    call SetPlayerAllianceStateAllyBJ( Player(6), Player(2), true )
    call SetPlayerAllianceStateAllyBJ( Player(6), Player(3), true )
    call SetPlayerAllianceStateAllyBJ( Player(6), Player(4), true )
    call SetPlayerAllianceStateAllyBJ( Player(6), Player(5), true )
    call SetPlayerAllianceStateAllyBJ( Player(6), Player(7), true )
    call SetPlayerAllianceStateAllyBJ( Player(6), Player(8), true )
    call SetPlayerAllianceStateAllyBJ( Player(6), Player(9), true )
    call SetPlayerAllianceStateAllyBJ( Player(6), Player(10), true )
    call SetPlayerAllianceStateAllyBJ( Player(6), Player(11), true )
    call SetPlayerAllianceStateAllyBJ( Player(7), Player(1), true )
    call SetPlayerAllianceStateAllyBJ( Player(7), Player(2), true )
    call SetPlayerAllianceStateAllyBJ( Player(7), Player(3), true )
    call SetPlayerAllianceStateAllyBJ( Player(7), Player(4), true )
    call SetPlayerAllianceStateAllyBJ( Player(7), Player(5), true )
    call SetPlayerAllianceStateAllyBJ( Player(7), Player(6), true )
    call SetPlayerAllianceStateAllyBJ( Player(7), Player(8), true )
    call SetPlayerAllianceStateAllyBJ( Player(7), Player(9), true )
    call SetPlayerAllianceStateAllyBJ( Player(7), Player(10), true )
    call SetPlayerAllianceStateAllyBJ( Player(7), Player(11), true )
    call SetPlayerAllianceStateAllyBJ( Player(8), Player(1), true )
    call SetPlayerAllianceStateAllyBJ( Player(8), Player(2), true )
    call SetPlayerAllianceStateAllyBJ( Player(8), Player(3), true )
    call SetPlayerAllianceStateAllyBJ( Player(8), Player(4), true )
    call SetPlayerAllianceStateAllyBJ( Player(8), Player(5), true )
    call SetPlayerAllianceStateAllyBJ( Player(8), Player(6), true )
    call SetPlayerAllianceStateAllyBJ( Player(8), Player(7), true )
    call SetPlayerAllianceStateAllyBJ( Player(8), Player(9), true )
    call SetPlayerAllianceStateAllyBJ( Player(8), Player(10), true )
    call SetPlayerAllianceStateAllyBJ( Player(8), Player(11), true )
    call SetPlayerAllianceStateAllyBJ( Player(9), Player(1), true )
    call SetPlayerAllianceStateAllyBJ( Player(9), Player(2), true )
    call SetPlayerAllianceStateAllyBJ( Player(9), Player(3), true )
    call SetPlayerAllianceStateAllyBJ( Player(9), Player(4), true )
    call SetPlayerAllianceStateAllyBJ( Player(9), Player(5), true )
    call SetPlayerAllianceStateAllyBJ( Player(9), Player(6), true )
    call SetPlayerAllianceStateAllyBJ( Player(9), Player(7), true )
    call SetPlayerAllianceStateAllyBJ( Player(9), Player(8), true )
    call SetPlayerAllianceStateAllyBJ( Player(9), Player(10), true )
    call SetPlayerAllianceStateAllyBJ( Player(9), Player(11), true )
    call SetPlayerAllianceStateAllyBJ( Player(10), Player(1), true )
    call SetPlayerAllianceStateAllyBJ( Player(10), Player(2), true )
    call SetPlayerAllianceStateAllyBJ( Player(10), Player(3), true )
    call SetPlayerAllianceStateAllyBJ( Player(10), Player(4), true )
    call SetPlayerAllianceStateAllyBJ( Player(10), Player(5), true )
    call SetPlayerAllianceStateAllyBJ( Player(10), Player(6), true )
    call SetPlayerAllianceStateAllyBJ( Player(10), Player(7), true )
    call SetPlayerAllianceStateAllyBJ( Player(10), Player(8), true )
    call SetPlayerAllianceStateAllyBJ( Player(10), Player(9), true )
    call SetPlayerAllianceStateAllyBJ( Player(10), Player(11), true )
    call SetPlayerAllianceStateAllyBJ( Player(11), Player(1), true )
    call SetPlayerAllianceStateAllyBJ( Player(11), Player(2), true )
    call SetPlayerAllianceStateAllyBJ( Player(11), Player(3), true )
    call SetPlayerAllianceStateAllyBJ( Player(11), Player(4), true )
    call SetPlayerAllianceStateAllyBJ( Player(11), Player(5), true )
    call SetPlayerAllianceStateAllyBJ( Player(11), Player(6), true )
    call SetPlayerAllianceStateAllyBJ( Player(11), Player(7), true )
    call SetPlayerAllianceStateAllyBJ( Player(11), Player(8), true )
    call SetPlayerAllianceStateAllyBJ( Player(11), Player(9), true )
    call SetPlayerAllianceStateAllyBJ( Player(11), Player(10), true )

    //   Shared Vision
    call SetPlayerAllianceStateVisionBJ( Player(1), Player(2), true )
    call SetPlayerAllianceStateVisionBJ( Player(1), Player(3), true )
    call SetPlayerAllianceStateVisionBJ( Player(1), Player(4), true )
    call SetPlayerAllianceStateVisionBJ( Player(1), Player(5), true )
    call SetPlayerAllianceStateVisionBJ( Player(1), Player(6), true )
    call SetPlayerAllianceStateVisionBJ( Player(1), Player(7), true )
    call SetPlayerAllianceStateVisionBJ( Player(1), Player(8), true )
    call SetPlayerAllianceStateVisionBJ( Player(1), Player(9), true )
    call SetPlayerAllianceStateVisionBJ( Player(1), Player(10), true )
    call SetPlayerAllianceStateVisionBJ( Player(1), Player(11), true )
    call SetPlayerAllianceStateVisionBJ( Player(2), Player(1), true )
    call SetPlayerAllianceStateVisionBJ( Player(2), Player(3), true )
    call SetPlayerAllianceStateVisionBJ( Player(2), Player(4), true )
    call SetPlayerAllianceStateVisionBJ( Player(2), Player(5), true )
    call SetPlayerAllianceStateVisionBJ( Player(2), Player(6), true )
    call SetPlayerAllianceStateVisionBJ( Player(2), Player(7), true )
    call SetPlayerAllianceStateVisionBJ( Player(2), Player(8), true )
    call SetPlayerAllianceStateVisionBJ( Player(2), Player(9), true )
    call SetPlayerAllianceStateVisionBJ( Player(2), Player(10), true )
    call SetPlayerAllianceStateVisionBJ( Player(2), Player(11), true )
    call SetPlayerAllianceStateVisionBJ( Player(3), Player(1), true )
    call SetPlayerAllianceStateVisionBJ( Player(3), Player(2), true )
    call SetPlayerAllianceStateVisionBJ( Player(3), Player(4), true )
    call SetPlayerAllianceStateVisionBJ( Player(3), Player(5), true )
    call SetPlayerAllianceStateVisionBJ( Player(3), Player(6), true )
    call SetPlayerAllianceStateVisionBJ( Player(3), Player(7), true )
    call SetPlayerAllianceStateVisionBJ( Player(3), Player(8), true )
    call SetPlayerAllianceStateVisionBJ( Player(3), Player(9), true )
    call SetPlayerAllianceStateVisionBJ( Player(3), Player(10), true )
    call SetPlayerAllianceStateVisionBJ( Player(3), Player(11), true )
    call SetPlayerAllianceStateVisionBJ( Player(4), Player(1), true )
    call SetPlayerAllianceStateVisionBJ( Player(4), Player(2), true )
    call SetPlayerAllianceStateVisionBJ( Player(4), Player(3), true )
    call SetPlayerAllianceStateVisionBJ( Player(4), Player(5), true )
    call SetPlayerAllianceStateVisionBJ( Player(4), Player(6), true )
    call SetPlayerAllianceStateVisionBJ( Player(4), Player(7), true )
    call SetPlayerAllianceStateVisionBJ( Player(4), Player(8), true )
    call SetPlayerAllianceStateVisionBJ( Player(4), Player(9), true )
    call SetPlayerAllianceStateVisionBJ( Player(4), Player(10), true )
    call SetPlayerAllianceStateVisionBJ( Player(4), Player(11), true )
    call SetPlayerAllianceStateVisionBJ( Player(5), Player(1), true )
    call SetPlayerAllianceStateVisionBJ( Player(5), Player(2), true )
    call SetPlayerAllianceStateVisionBJ( Player(5), Player(3), true )
    call SetPlayerAllianceStateVisionBJ( Player(5), Player(4), true )
    call SetPlayerAllianceStateVisionBJ( Player(5), Player(6), true )
    call SetPlayerAllianceStateVisionBJ( Player(5), Player(7), true )
    call SetPlayerAllianceStateVisionBJ( Player(5), Player(8), true )
    call SetPlayerAllianceStateVisionBJ( Player(5), Player(9), true )
    call SetPlayerAllianceStateVisionBJ( Player(5), Player(10), true )
    call SetPlayerAllianceStateVisionBJ( Player(5), Player(11), true )
    call SetPlayerAllianceStateVisionBJ( Player(6), Player(1), true )
    call SetPlayerAllianceStateVisionBJ( Player(6), Player(2), true )
    call SetPlayerAllianceStateVisionBJ( Player(6), Player(3), true )
    call SetPlayerAllianceStateVisionBJ( Player(6), Player(4), true )
    call SetPlayerAllianceStateVisionBJ( Player(6), Player(5), true )
    call SetPlayerAllianceStateVisionBJ( Player(6), Player(7), true )
    call SetPlayerAllianceStateVisionBJ( Player(6), Player(8), true )
    call SetPlayerAllianceStateVisionBJ( Player(6), Player(9), true )
    call SetPlayerAllianceStateVisionBJ( Player(6), Player(10), true )
    call SetPlayerAllianceStateVisionBJ( Player(6), Player(11), true )
    call SetPlayerAllianceStateVisionBJ( Player(7), Player(1), true )
    call SetPlayerAllianceStateVisionBJ( Player(7), Player(2), true )
    call SetPlayerAllianceStateVisionBJ( Player(7), Player(3), true )
    call SetPlayerAllianceStateVisionBJ( Player(7), Player(4), true )
    call SetPlayerAllianceStateVisionBJ( Player(7), Player(5), true )
    call SetPlayerAllianceStateVisionBJ( Player(7), Player(6), true )
    call SetPlayerAllianceStateVisionBJ( Player(7), Player(8), true )
    call SetPlayerAllianceStateVisionBJ( Player(7), Player(9), true )
    call SetPlayerAllianceStateVisionBJ( Player(7), Player(10), true )
    call SetPlayerAllianceStateVisionBJ( Player(7), Player(11), true )
    call SetPlayerAllianceStateVisionBJ( Player(8), Player(1), true )
    call SetPlayerAllianceStateVisionBJ( Player(8), Player(2), true )
    call SetPlayerAllianceStateVisionBJ( Player(8), Player(3), true )
    call SetPlayerAllianceStateVisionBJ( Player(8), Player(4), true )
    call SetPlayerAllianceStateVisionBJ( Player(8), Player(5), true )
    call SetPlayerAllianceStateVisionBJ( Player(8), Player(6), true )
    call SetPlayerAllianceStateVisionBJ( Player(8), Player(7), true )
    call SetPlayerAllianceStateVisionBJ( Player(8), Player(9), true )
    call SetPlayerAllianceStateVisionBJ( Player(8), Player(10), true )
    call SetPlayerAllianceStateVisionBJ( Player(8), Player(11), true )
    call SetPlayerAllianceStateVisionBJ( Player(9), Player(1), true )
    call SetPlayerAllianceStateVisionBJ( Player(9), Player(2), true )
    call SetPlayerAllianceStateVisionBJ( Player(9), Player(3), true )
    call SetPlayerAllianceStateVisionBJ( Player(9), Player(4), true )
    call SetPlayerAllianceStateVisionBJ( Player(9), Player(5), true )
    call SetPlayerAllianceStateVisionBJ( Player(9), Player(6), true )
    call SetPlayerAllianceStateVisionBJ( Player(9), Player(7), true )
    call SetPlayerAllianceStateVisionBJ( Player(9), Player(8), true )
    call SetPlayerAllianceStateVisionBJ( Player(9), Player(10), true )
    call SetPlayerAllianceStateVisionBJ( Player(9), Player(11), true )
    call SetPlayerAllianceStateVisionBJ( Player(10), Player(1), true )
    call SetPlayerAllianceStateVisionBJ( Player(10), Player(2), true )
    call SetPlayerAllianceStateVisionBJ( Player(10), Player(3), true )
    call SetPlayerAllianceStateVisionBJ( Player(10), Player(4), true )
    call SetPlayerAllianceStateVisionBJ( Player(10), Player(5), true )
    call SetPlayerAllianceStateVisionBJ( Player(10), Player(6), true )
    call SetPlayerAllianceStateVisionBJ( Player(10), Player(7), true )
    call SetPlayerAllianceStateVisionBJ( Player(10), Player(8), true )
    call SetPlayerAllianceStateVisionBJ( Player(10), Player(9), true )
    call SetPlayerAllianceStateVisionBJ( Player(10), Player(11), true )
    call SetPlayerAllianceStateVisionBJ( Player(11), Player(1), true )
    call SetPlayerAllianceStateVisionBJ( Player(11), Player(2), true )
    call SetPlayerAllianceStateVisionBJ( Player(11), Player(3), true )
    call SetPlayerAllianceStateVisionBJ( Player(11), Player(4), true )
    call SetPlayerAllianceStateVisionBJ( Player(11), Player(5), true )
    call SetPlayerAllianceStateVisionBJ( Player(11), Player(6), true )
    call SetPlayerAllianceStateVisionBJ( Player(11), Player(7), true )
    call SetPlayerAllianceStateVisionBJ( Player(11), Player(8), true )
    call SetPlayerAllianceStateVisionBJ( Player(11), Player(9), true )
    call SetPlayerAllianceStateVisionBJ( Player(11), Player(10), true )

endfunction

function InitAllyPriorities takes nothing returns nothing

    call SetStartLocPrioCount( 0, 11 )
    call SetStartLocPrio( 0, 0, 1, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 0, 1, 2, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 0, 2, 3, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 0, 3, 4, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 0, 4, 5, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 0, 5, 6, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 0, 6, 7, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 0, 7, 8, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 0, 8, 9, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 0, 9, 10, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 0, 10, 11, MAP_LOC_PRIO_HIGH )

    call SetStartLocPrioCount( 1, 11 )
    call SetStartLocPrio( 1, 0, 0, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 1, 1, 2, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 1, 2, 3, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 1, 3, 4, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 1, 4, 5, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 1, 5, 6, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 1, 6, 7, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 1, 7, 8, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 1, 8, 9, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 1, 9, 10, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 1, 10, 11, MAP_LOC_PRIO_HIGH )

    call SetStartLocPrioCount( 2, 11 )
    call SetStartLocPrio( 2, 0, 0, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 2, 1, 1, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 2, 2, 3, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 2, 3, 4, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 2, 4, 5, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 2, 5, 6, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 2, 6, 7, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 2, 7, 8, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 2, 8, 9, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 2, 9, 10, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 2, 10, 11, MAP_LOC_PRIO_HIGH )

    call SetStartLocPrioCount( 3, 11 )
    call SetStartLocPrio( 3, 0, 0, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 3, 1, 1, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 3, 2, 2, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 3, 3, 4, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 3, 4, 5, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 3, 5, 6, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 3, 6, 7, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 3, 7, 8, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 3, 8, 9, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 3, 9, 10, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 3, 10, 11, MAP_LOC_PRIO_HIGH )

    call SetStartLocPrioCount( 4, 11 )
    call SetStartLocPrio( 4, 0, 0, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 4, 1, 1, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 4, 2, 2, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 4, 3, 3, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 4, 4, 5, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 4, 5, 6, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 4, 6, 7, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 4, 7, 8, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 4, 8, 9, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 4, 9, 10, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 4, 10, 11, MAP_LOC_PRIO_HIGH )

    call SetStartLocPrioCount( 5, 11 )
    call SetStartLocPrio( 5, 0, 0, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 5, 1, 1, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 5, 2, 2, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 5, 3, 3, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 5, 4, 4, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 5, 5, 6, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 5, 6, 7, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 5, 7, 8, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 5, 8, 9, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 5, 9, 10, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 5, 10, 11, MAP_LOC_PRIO_HIGH )

    call SetStartLocPrioCount( 6, 11 )
    call SetStartLocPrio( 6, 0, 0, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 6, 1, 1, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 6, 2, 2, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 6, 3, 3, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 6, 4, 4, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 6, 5, 5, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 6, 6, 7, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 6, 7, 8, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 6, 8, 9, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 6, 9, 10, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 6, 10, 11, MAP_LOC_PRIO_HIGH )

    call SetStartLocPrioCount( 7, 11 )
    call SetStartLocPrio( 7, 0, 0, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 7, 1, 1, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 7, 2, 2, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 7, 3, 3, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 7, 4, 4, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 7, 5, 5, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 7, 6, 6, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 7, 7, 8, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 7, 8, 9, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 7, 9, 10, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 7, 10, 11, MAP_LOC_PRIO_HIGH )

    call SetStartLocPrioCount( 8, 11 )
    call SetStartLocPrio( 8, 0, 0, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 8, 1, 1, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 8, 2, 2, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 8, 3, 3, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 8, 4, 4, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 8, 5, 5, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 8, 6, 6, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 8, 7, 7, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 8, 8, 9, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 8, 9, 10, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 8, 10, 11, MAP_LOC_PRIO_HIGH )

    call SetStartLocPrioCount( 9, 11 )
    call SetStartLocPrio( 9, 0, 0, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 9, 1, 1, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 9, 2, 2, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 9, 3, 3, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 9, 4, 4, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 9, 5, 5, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 9, 6, 6, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 9, 7, 7, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 9, 8, 8, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 9, 9, 10, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 9, 10, 11, MAP_LOC_PRIO_HIGH )

    call SetStartLocPrioCount( 10, 11 )
    call SetStartLocPrio( 10, 0, 0, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 10, 1, 1, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 10, 2, 2, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 10, 3, 3, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 10, 4, 4, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 10, 5, 5, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 10, 6, 6, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 10, 7, 7, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 10, 8, 8, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 10, 9, 9, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 10, 10, 11, MAP_LOC_PRIO_HIGH )

    call SetStartLocPrioCount( 11, 11 )
    call SetStartLocPrio( 11, 0, 0, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 11, 1, 1, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 11, 2, 2, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 11, 3, 3, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 11, 4, 4, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 11, 5, 5, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 11, 6, 6, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 11, 7, 7, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 11, 8, 8, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 11, 9, 9, MAP_LOC_PRIO_HIGH )
    call SetStartLocPrio( 11, 10, 10, MAP_LOC_PRIO_HIGH )
endfunction

//***************************************************************************
//*
//*  Main Initialization
//*
//***************************************************************************

//===========================================================================
function main takes nothing returns nothing
    call SetCameraBounds( -11520.0 + GetCameraMargin(CAMERA_MARGIN_LEFT), -11776.0 + GetCameraMargin(CAMERA_MARGIN_BOTTOM), 11520.0 - GetCameraMargin(CAMERA_MARGIN_RIGHT), 11264.0 - GetCameraMargin(CAMERA_MARGIN_TOP), -11520.0 + GetCameraMargin(CAMERA_MARGIN_LEFT), 11264.0 - GetCameraMargin(CAMERA_MARGIN_TOP), 11520.0 - GetCameraMargin(CAMERA_MARGIN_RIGHT), -11776.0 + GetCameraMargin(CAMERA_MARGIN_BOTTOM) )
    call SetDayNightModels( "Environment\\DNC\\DNCLordaeron\\DNCLordaeronTerrain\\DNCLordaeronTerrain.mdl", "Environment\\DNC\\DNCLordaeron\\DNCLordaeronUnit\\DNCLordaeronUnit.mdl" )
    call NewSoundEnvironment( "Default" )
    call SetAmbientDaySound( "BlackCitadelDay" )
    call SetAmbientNightSound( "BlackCitadelNight" )
    call SetMapMusic( "Music", true, 0 )
    call InitSounds(  )
    call CreateRegions(  )
    call InitBlizzard(  )
    call InitGlobals(  )
    call InitCustomTriggers(  )
    call RunInitializationTriggers(  )

endfunction

//***************************************************************************
//*
//*  Map Configuration
//*
//***************************************************************************

function config takes nothing returns nothing
    call SetMapName( "TRIGSTR_018" )
    call SetMapDescription( "TRIGSTR_020" )
    call SetPlayers( 12 )
    call SetTeams( 12 )
    call SetGamePlacement( MAP_PLACEMENT_TEAMS_TOGETHER )

    call DefineStartLocation( 0, -10432.0, 10304.0 )
    call DefineStartLocation( 1, -10432.0, 10304.0 )
    call DefineStartLocation( 2, -10432.0, 10304.0 )
    call DefineStartLocation( 3, -10432.0, 10304.0 )
    call DefineStartLocation( 4, -10432.0, 10304.0 )
    call DefineStartLocation( 5, -10432.0, 10304.0 )
    call DefineStartLocation( 6, -10432.0, 10304.0 )
    call DefineStartLocation( 7, -10432.0, 10304.0 )
    call DefineStartLocation( 8, -10432.0, 10304.0 )
    call DefineStartLocation( 9, -10432.0, 10304.0 )
    call DefineStartLocation( 10, -10432.0, 10304.0 )
    call DefineStartLocation( 11, -10432.0, 10304.0 )

    // Player setup
    call InitCustomPlayerSlots(  )
    call InitCustomTeams(  )
    call InitAllyPriorities(  )
endfunction

