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

Trigger Viewer

GoldenLands v3.0AI.w3x
Variables
Initialization
GameConstants
Initialization
Player
Team
Pathing
test
Animation
Order Tracker
Map System
Game Commands
Test Commandss
Player Leave
Map Info
----Terminado----
Last Man Standing
Obelisk Defend
Game Mode Selection
Vote System
Pick Hero System
Preload
Advanced Book
On Index
Unit Index
----Mejorar----
AoE Meter
Ability Description
Ability Library
Hero Library
Multiboard
Game Multiboard
End Multiboard
Illusion
Lightning
Attack Range
---------------------------
Point
Heroic Traits
Trait Buffs
Gate Tower
Perks
Standard Buffs
Chain System
Respawn
BountyExpKill
Neutral Hostile
InCombat
Game Loop
Fear System
Status
Status Buffs
Status Immunity
Buff Manager
Message
Upgrade Skills
Effect
Load Functions
PlayerTarget and FriendlyFire
Unit Data
KPJ System
Tree Respawn
Enum
Miscelaneous
Hero Regen
Special Stats Formulas
Hero Attributes
Bonus
Commands
DamageMod
Teleport
Aura System
Dummy Caster Recycler
OnAttackEffects
----Incompletos/Errores/Rehacer----
DummySFX
Texttag
Damage TextTag
Game Play
War Hall
Wave Abilities
Defender Squad
Pet
Ancient Obelisk
Base
Base Abilitys
Troops
Waves
Guard Path
Control Base
GoldMine
WarChief
---------------------------
Commander Buffs
Commander Abilities
Advanced
LSE vJASS
Orders Repo
Filed Of View
Rapid Sound
Unit Moving
MissileRecycler
Unit Recycler
Missile
Event
SpellEffectEvent
RegisterPlayerUnitEvent
Table
Timer Utils Ex
CTL32
Alloc
Misc Libraries
LoadingBar
Bar
Queue
ARGB
Linked List
ErrorMessage
NewGroup
TerrainPathability
Revive Unit
Dummy Caster
Movespeed
World Bounds
Damage Engine Config
Damage Engine
----------ITEMS--------------
Items
---------------------------
Magic Data
Magic Buffs
Trinket Data
Trinket Buffs
Armor Data
Armor Buffs
Weapon Data
Weapon Buffs
Consumable Data
Consumable Buffs
Misc Data
Item Events
Item Missiles
---------------------------
Item Enchant
Enchant Buffs
Runes
Runes Effects
Item
Item Upgrade
Item Cleanup
Stash Abilities
----------HEROES-----------
Human
Disruption Magus
Disruption Magus Data
Strobe Lights
Magic Walls
Magic Canalization
Disruptive Nebula
Scarlet Guard
Scarlet Guard Data
Scarlet Strike
Defensive Assault
War Emblem
Ascalon Sword Art
Sacred Defender
Sacred Defender Data
Justice Hammer
Bastion of Light
Sacred Prism
Winged Blessing
Earthbinder
Earthbinder
Earthen Steel
Tremors
Summon Golems
Iron Consistency
Gryphon Rider
Gryphon Rider Data
Stellar Strike
Iron Will
Storm Hammers
Sky Dive
Dwarf Runner
Dwarf Runner Data
Front Guns
Overheat
Engineering Upgrade
Overdrive
Orc
Fel Rider
Fel Rider Data
Fel Blade
Devourer Bite
Outworld Fire
Fel Onslaught
Bone Crusher
Bone Crusher Data
Deadly Spin
Uncontrolled Anger
Crushing Blows
Inner Wrath
Voodoo Priest
Voodoo Priest Data
Shadow Wave
Spirit Room
Voodoo Mask
Dancing Ether
Zealot
Zealot Data
Tearing Slash
Berserk Shadow
Killer Instinct
Ravager
Headhunter
Headhunter Data
Piercing Spear
Frenzy
Stack Heads
Envenomed Spears
Ogre Sorcerer
Ogre Sorcerer Data
Crushing Rock
Spell Book
Fire Gale
Disruptive Shout
Unleash Strength
Battle Tendency
Bloodlust
Undead
Soul Harvester
Soul Harvester Data
Soul Absorption
Shadow Embrace
Haunt
Void Shift
Frozenshell
Frozenshell Data
Cold Swirl
Frostbitten Bulwark
Ice Walls
Arctic Fang
Doomed Queen
Damn Queen Data
Vampiric Horde
Banshee Cry
Chains Of Fatality
Terror Shout
Warlock
Warlock Data
Nether Curse
Chaos Meteor
Life Drain
Inner Demon
Plague Bringer
Plague Bringer Data
Underground Lash
Shake Entrails
Rotten Monstrosity
Rotten Cloud
Flesh Behemoth
Flesh Behemoth Data
Nightmare Chains
Putrid Breath
Sinister Harvest
Corrosive Scraps
Night Elf
Elder Sage
Elder Sage Data
Nature Wave
Life Bloom
Natures Touch
Elder Mystic
Tempest Druid
Tempest Druid Data
Living Tornado
Wild Flight
Wind Flutter
Winds of Change
Shadow Slayer
Shadow Slayer Data
Silent Edge
Vile Tricks
Hateful Glaive
Blade Dance
Lizard Archer
Lizard Archer Data
Chameleon Shot
Summon Lylia
Nibble
Wild Charge
Guardian Cobra
Crocodile Fangs
Royal Shout
Moon Mistress
Moon Mistress
Lunar Ring
Starfall
Moon Fire
Moonlight
Dream Eater
Dream Eater
Fairy Dust
Sleep
Phase Shift
Emerald Trance
Neutral
Bandit Champion
---------------------------
Bandit Champion Data
Stealth
Throw Dagger
Silent Rush
Premeditation
Blink Strike
Demon Guard
Demon Guard Data
Doom Blade
Flaming Cuirass
Demonic Hand
Inferno Eruption
Death Sting
Death Sting Data
Poisonous Glands
Corrosive Venom
Scorpid Attack
Tunnels
Scorpid Hatchlings
Gnoll Warden
Gnoll Warden Data
Expel Intruder
Scare Fangs
Overcharge
Thunder Awaken
Goblin Grenadier
Goblin Grenadier Data
Fragmented Bullet
Rocket Jump
Shock Grenade
Cobra K300
The Hermit
The Hermit Data
Incendiary Gunpowder
Diamond Armor
Burrow
Earth Tremble
----------AI----------
Heroes AI
AI Bandit Champion
AI Elder Sage
AI Demon Guard
AI Death Sting
AI DisruptionMagus
AI Scarlet Guard
AI Fel Rider
AI Soul Harvester
AI Sacred Defender
AI Shadow Slayer
AI Tempest Druid
AI Bone Crusher
AI Gnoll Warden
AI Doomed Queen
AI Lizard Archer
AI Frozenshell
AI Goblin Grenadier
AI Voodoo Priest
AI Earthbinder
AI Warlock
AI Zealot
AI Moon Mistress
AI Headhunter
AI Plague Bringer
AI Gryphon Rider
AI Flesh Behemoth
AI Dream Eater
AI Dwarf Runner
AI The Hermit
AI Ogre Sorcerer
AI
AI System
AI Region
AI ItemBuild
AI Threat
AI AbilityBuild
AI UpgradeBuild
Enter map-specific custom script code below. This text will be included in the map script after variables are declared and before any trigger code.
//Autor: -Manuel-
//Email: manuelescmar123@gmail.com
Name Type Is Array Initial Value
AfterDamageEvent real No
AOEDamageEvent real No
ArenaWalls destructable Yes
ArenaWalls2 destructable Yes
CenterPoint location No
ClearDamageEvent trigger No
DAMAGE_FACTOR_BRACERS real No
DAMAGE_FACTOR_ELUNES real No
DAMAGE_FACTOR_ETHEREAL real No
DamageBlockingAbility abilcode No
DamageEvent real No
DamageEventAmount real No
DamageEventAOE integer No
DamageEventAOEGroup group No
DamageEventCode integer No
DamageEventLevel integer No
DamageEventOverride boolean No
DamageEventPrevAmt real No
DamageEventSource unit No
DamageEventsWasted integer No
DamageEventTarget unit No
DamageEventTrigger trigger No
DamageEventType integer No
DamageModifierEvent real No
DamageTypeAttack integer No
DamageTypeBlocked integer No
DamageTypeCriticalStrike integer No
DamageTypeExplosive integer No
DamageTypeHeal integer No
DamageTypeHealOverTime integer No
DamageTypeMagic integer No
DamageTypeMagicAoe integer No
DamageTypeMagicOverTime integer No
DamageTypePhysical integer No
DamageTypePhysicalAoe integer No
DamageTypePhysicalOverTime integer No
DamageTypePure integer No
DamageTypeReduced integer No
DmgEvBracers itemcode No
DmgEvRecursionN integer No
DmgEvRunning boolean No
DmgEvStarted boolean No
DmgEvTimer timer No
DmgEvTrig trigger No
EnhancedDamageTarget unit No
HideDamageFrom boolean Yes
IsDamageSpell boolean No
IsUnitBeingKnockedBack boolean Yes
K2DAmphibious boolean Yes
K2DAngle real Yes
K2DBounce boolean Yes
K2DCollision real Yes
K2DCos real Yes
K2DCosD1 real Yes
K2DCosD2 real Yes
K2DCosH real Yes
K2DDebrisKiller unit No
K2DDestRadius real Yes
K2DDistanceLeft real Yes
K2DFreeze boolean Yes
K2DFriction real Yes
K2DFXModel string Yes
K2DFXRate real Yes
K2DFXTimeLeft real Yes
K2DHeight real Yes
K2DHeightThreshold real Yes
K2DImpact trigger Yes
K2DItem item No
K2DItemOffset boolean No
K2DItemsFound boolean No
K2DKillTrees boolean Yes
K2DLastX real Yes
K2DLastY real Yes
K2DMaxDestRadius real No
K2DMaxX real No
K2DMaxY real No
K2DMinX real No
K2DMinY real No
K2DNext integer Yes
K2DOverride boolean Yes
K2DPause boolean Yes
K2DPrev integer Yes
K2DRadius integer Yes
K2DRegion rect No
K2DSimple boolean Yes
K2DSin real Yes
K2DSinD1 real Yes
K2DSinD2 real Yes
K2DSinH real Yes
K2DSource unit Yes
K2DTimeLeft real Yes
K2DTimeout real No
K2DTimer timer No
K2DUnbiasedCollision boolean Yes
K2DVelocity real Yes
K2DX real No
K2DY real No
Knockback2DAmphibious boolean No
Knockback2DAngle real No
Knockback2DBounces boolean No
Knockback2DCollision real No
Knockback2DDefaultBounce boolean No
Knockback2DDefaultDestRadius real No
Knockback2DDefaultFriction real No
Knockback2DDefaultFX string No
Knockback2DDefaultFXRate real No
Knockback2DDefaultGravity real No
Knockback2DDefaultKillTrees boolean No
Knockback2DDefaultPause boolean No
Knockback2DDestRadius real No
Knockback2DDistance real No
Knockback2DFriction real No
Knockback2DFXRate real No
Knockback2DGravity real No
Knockback2DHeight real No
Knockback2DKillTrees boolean No
Knockback2DLoopFX string No
Knockback2DOnImpact trigger No
Knockback2DOverride boolean No
Knockback2DPause boolean No
Knockback2DRobustPathing integer No
Knockback2DSimple boolean No
Knockback2DSource unit No
Knockback2DTime real No
Knockback2DTreeOrDebris string No
Knockback2DUnbiasedCollision boolean No
Knockback2DUnit unit No
LastDamageHP real No
LastDmgCode integer Yes
LastDmgPrevAmount real Yes
LastDmgPrevType integer Yes
LastDmgSource unit Yes
LastDmgTarget unit Yes
LastDmgValue real Yes
LastDmgWasSpell boolean Yes
LocalPlayer player No
LoopInt integer No
NextDamageCode integer No
NextDamageOverride boolean No
NextDamageType integer No
onPreDamageCustom real No
Radians_QuarterPi real No
Radians_QuarterTurn real No
Radians_Turn real No
SpellDamageAbility abilcode No
temp string No
TempX real No
TempY real No
UnitDamageRegistered boolean Yes
library GameConstants uses MiscLibrary
    globals
        constant integer GAME_MODE_NORMAL = 1
        constant integer GAME_MODE_LMS    = 2
        constant integer GAME_MODE_OD     = 3
    endglobals
    struct Game extends array
        public static constant real     CAMERA_SMOTH_FACTOR                 = 17
        public static constant player   PLAYER_NEUTRAL_HOSTILE              = Player(PLAYER_NEUTRAL_AGGRESSIVE)
        public static constant player   PLAYER_NEUTRAL_EXTRA                = Player(PLAYER_NEUTRAL_PASSIVE)
        public static constant player   PLAYER_WARCHIEF_HORDE               = Player(0)
        public static constant player   PLAYER_WARCHIEF_ALLIANCE            = Player(1)
        public static constant integer  PLAYER_MAX                          = 11
        public static constant real     PLAYER_NEUTRAL_HANDICAP             = 1.0
        public static constant integer  PLAYER_INITIAL_GOLD                 = 800
        public static constant real     TIME_TO_INIT_GAME                   = 120
        public static constant real     TIME_OF_DAY                         = 6.00
        public static constant real     HIDE_X                              = 6528
        public static constant real     HIDE_Y                              = -6907
       
        public static constant integer  FACTION_NEUTRAL                     = 0
        public static constant integer  FACTION_HUMAN                       = 1
        public static constant integer  FACTION_ORC                         = 2
        public static constant integer  FACTION_NIGHTELF                    = 3
        public static constant integer  FACTION_UNDEAD                      = 4
       
        public static constant integer  FLAG_NO_COMBAT                      = 'A00F'
        public static constant integer  FLAG_WARD                           = 'A04R'
        public static constant integer  FLAG_NO_AGGRO                       = 'A06E'
        public static constant integer  FLAG_HERO_CREEP                     = 'A089'
       
        public static constant integer  DUMMY_CASTER                        = 'u001'
        public static constant integer  DEFAULT_CAMERA                      = 1650
   
        static player                   FirstPlayer                          = null
        static player                   LocalPlayer                         = null
        static real                     TIME_PRELOADING                     = 12.00
        static boolean                  GameStarted                         = false
        static boolean                  CreepsSpawned
        static boolean                  IsSinglePlayer                      = false
        static boolean                  IsReplay                            = false
        static boolean                  IsOnline                            = false
        static boolean                  GameOver                            = false
        static boolean                  TestMode                            = false
        static Team                      Winner                              = 0
        static integer                  ResourcesToWin                      = 3000
        //LMS
        static integer                  Rounds                              = 15
        static integer                  Round                               = 0
        static boolean                  RoundStarted                        = false
       
        static string                   FireworksSfx                        = "Abilities\\Spells\\Human\\Flare\\FlareTarget.mdl"
       
        static integer                  Mode  
       
        public static method DefineVariables takes nothing returns nothing
            set LocalPlayer = GetLocalPlayer()
            set IsSinglePlayer = true
            set CreepsSpawned = false
            set Mode = 0
        endmethod
       
        private static method LoopSfx takes nothing returns nothing
            local real x
            local real y  
            local integer i
            local effect sfx
            if Winner == 1 then
                set i = 2
                loop
                    if Players[i].isPlaying then
                        if GetRandomInt(1,100) <= 35 then
                            call QueueUnitAnimation(Players[i].hero.hero,Players[i].hero.WinAni)
                        endif
                        if GetRandomInt(1,100) <= 15 then
                            set x = GetUnitX(Players[i].hero.hero) + GetRandomReal(-100,100)
                            set y = GetUnitY(Players[i].hero.hero) + GetRandomReal(-100,100)
                            set sfx = AddSpecialEffect(FireworksSfx,x,y)
                            call BlzSetSpecialEffectScale(sfx,GetRandomReal(0.4,0.7))
                            call DestroyEffect(sfx)
                        endif
                    endif
                    set i = i + 1
                    exitwhen i > 6
                endloop
            else
                set i = 7
                loop
                    if Players[i].isPlaying then
                        if GetRandomInt(1,100) <= 35 then
                            call QueueUnitAnimation(Players[i].hero.hero,Players[i].hero.WinAni)
                        endif
                        if GetRandomInt(1,100) <= 15 then
                            set x = GetUnitX(Players[i].hero.hero) + GetRandomReal(-100,100)
                            set y = GetUnitY(Players[i].hero.hero) + GetRandomReal(-100,100)
                            set sfx = AddSpecialEffect(FireworksSfx,x,y)
                            call BlzSetSpecialEffectScale(sfx,GetRandomReal(0.4,0.7))
                            call DestroyEffect(sfx)
                        endif
                    endif
                    set i = i + 1
                    exitwhen i > 11
                endloop
            endif
            set sfx = null
        endmethod
       
        private static method GameOverVictory takes nothing returns nothing
            local integer i = 2
            local timer t = CreateTimer()
            local Hero h
            local PickHeroSystem phs
            call TimerStart(t,1.0,true,function thistype.LoopSfx)
            set t = null
            if Winner == 1 then
                call DisplayTimedTextToPlayer(Game.LocalPlayer,0,0,99999,"|cFF0063C6Victory: |r"+HORDE_COLOR+Winner.name+"!!|r")
            else
                call DisplayTimedTextToPlayer(Game.LocalPlayer,0,0,99999,"|cFF0063C6Victory: |r"+ALLIANCE_COLOR+Winner.name+"!!|r")
            endif
            call DisplayTimedTextToPlayer(Game.LocalPlayer,0,0,99999,"Thanks for Playing!!")
            call EndMultiboard_Setup.execute()
            call SetMapFlag(MAP_FOG_ALWAYS_VISIBLE,true)
            call ShowUnit(phs.VisionDummy1,true)
            call ShowUnit(phs.VisionDummy2,true)
            call ShowUnit(phs.lockcamera,true)
            call StartSound(gg_snd_HeroicVictory)
            call CinematicFadeBJ( bj_CINEFADETYPE_FADEIN, 3.0, "ReplaceableTextures\\CameraMasks\\Black_mask.blp", 0, 0, 0, 0 )
            loop
                if Players[i].isPlaying then
                    set phs = PickHeroSystem[i]
                    set h = Players[i].hero
                    call ShowUnit(phs.circleDummy,true)
                    call UnitAddAbility(phs.circleDummy,'Aloc')
                    call SetUnitPathing(h.hero,false)
                    call UnitRemoveAllBuffs(h.hero)
                    if not UnitAlive(h.hero) then
                        call ReviveHero(h.hero,GetUnitX(phs.circleDummy),GetUnitY(phs.circleDummy),false)
                    endif
                    call SetUnitX(h.hero,GetUnitX(phs.circleDummy))
                    call SetUnitY(h.hero,GetUnitY(phs.circleDummy))
                    call PauseUnit(h.hero,false)
                    //call BlzPauseUnitEx(h.hero,true)
                    if i <= 6 then
                        call SetUnitFacing(h.hero,45.00)
                    else
                        call SetUnitFacing(h.hero,225.00)
                    endif
                    call SetUnitState(h.hero,UNIT_STATE_LIFE,999999)
                    call UnitAddAbility(h.hero,'Ane2')
                    call BlzUnitDisableAbility(h.hero,'Amov',true,false)
                    call BlzUnitDisableAbility(h.hero,'Aatk',true,false)
                    call SetCameraTargetControllerNoZForPlayer(Player(i),PickHeroSystem.lockcamera, 0, 0, false )
                    call SelectUnitForPlayer(h.hero,Player(i),true)
                endif
                set i = i + 1
                exitwhen i > PLAYER_MAX
            endloop
            call DestroyTimer(GetExpiredTimer())
        endmethod
       
        public static method RunGameOver takes Team t returns nothing
            local timer tr = CreateTimer()
            call PauseAllUnitsBJ(true)
            call CinematicFadeBJ( bj_CINEFADETYPE_FADEOUT, 3.0, "ReplaceableTextures\\CameraMasks\\Black_mask.blp", 0, 0, 0, 0 )
            call TimerStart(tr,4.0,false,function thistype.GameOverVictory)
            call PlayerLib_BuildMax.execute()
            set GameOver = true
            set Winner = t
            set tr = null
        endmethod
    endstruct
endlibrary

 
scope Initialization initializer init
    globals
        private constant string PRELOAD_MSG = "PRELOADING OBJECTS, PLEASE WAIT"
        string HIGHLIGHT = "|cff99b4d1"
        timerdialog GameModeDialog
        timer        GameModeTimer
    endglobals
   
    private function InitEnviromentFix takes nothing returns nothing
        //Doodads Tower
        call SetDoodadAnimationRect(bj_mapInitialPlayableArea, 'D001', "stand ready attack",false)
        //Mine
        call SetBuildingFacing(gg_unit_n00N_0058,160)
        call SetBuildingFacing(gg_unit_n00N_0033,340)
        call SetBuildingFacing(gg_unit_n00N_0118,335)
        call SetBuildingFacing(gg_unit_n00N_0117,170)
        //SideShop
        call SetBuildingFacing(gg_unit_n017_0001,0)
        call SetBuildingFacing(gg_unit_n017_0053,180)
        //Spell Enhancement
        call SetBuildingFacing(gg_unit_n007_0063,70)
        call SetUnitAnimation(gg_unit_n007_0063,"stand work")
        //call SetBuildingFacing(gg_unit_n004_0176,20)
        call SetUnitAnimation(gg_unit_n004_0176,"stand work")
        //Shops Facing
        //Horde
        call SetBuildingFacing(gg_unit_n00O_0246,90)  //Armor 1
        call SetBuildingFacing(gg_unit_n00P_0044,90)  //Armor 2
        call SetBuildingFacing(gg_unit_n00T_0250,90) //Weapon 1
        call SetBuildingFacing(gg_unit_n012_0108,90) //Weapon 2
        call SetBuildingFacing(gg_unit_n00E_0258,90) //Magic Accs 1
        call SetBuildingFacing(gg_unit_n00Z_0106,90) //Magic Accs 2
        call SetBuildingFacing(gg_unit_n00U_0256,45) //trinkets 1
        call SetBuildingFacing(gg_unit_n01A_0062,45) //trinket 2
        call SetBuildingFacing(gg_unit_n00B_0048,45) //Consumables
        call SetBuildingFacing(gg_unit_n000_0254,305) //market
        //Alliance
        call SetBuildingFacing(gg_unit_n00A_0045,270)  //Armor 1
        call SetBuildingFacing(gg_unit_n003_0245,270)  //Armor 2
        call SetBuildingFacing(gg_unit_ma00_0249,270)  //Weapon 1
        call SetBuildingFacing(gg_unit_n011_0032,270)  //Weapon 2
        call SetBuildingFacing(gg_unit_n001_0257,270)  //Magic Accs 1
        call SetBuildingFacing(gg_unit_n010_0096,270)  //Magic Accs 2
        call SetBuildingFacing(gg_unit_n00D_0012,225)  //Trinket
        call SetBuildingFacing(gg_unit_n00B_0248,225)  //Consumables
        call SetBuildingFacing(gg_unit_n000_0253,270)  //Market
        call SetBuildingFacing(gg_unit_n01B_0061,225)  //Trinket
    endfunction
   
    private function InitGame takes nothing returns boolean
        call DestroyTimer(GameModeTimer)
        call DestroyTimerDialog(GameModeDialog)
        call StartSound(gg_snd_GameStart)
        call ModifyGateBJ( bj_GATEOPERATION_DESTROY, gg_dest_Dofv_3954 )
        call ModifyGateBJ( bj_GATEOPERATION_DESTROY, gg_dest_Dofv_3955 )
        call WarchiefLib_CreateWarchief()
        if PickHeroSystem.PicksCount == Players.PlayersActive then
            call LoadFunction.Destroy()
        endif
        set GameLoop.Minutes = 0
        set GameLoop.Seconds = 0
        set GameModeTimer = null
        set GameModeDialog = null
        set Game.GameStarted = true
        return false
    endfunction
   
    private function GameModeEnd takes nothing returns nothing
        call DestroyTimer(GameModeTimer)
        call DestroyTimerDialog(GameModeDialog)
        call GameMode.verifyWinner()
        call Players.RemoveVotingUnits()
        if GameMode.winner.name == "Normal" or GameMode.winner == 0 then
            set Game.Mode = GAME_MODE_NORMAL
            if GameMode.winner == 0 then
                call Message.Show("The "+HIGHLIGHT+"Normal Game|r"+" mode has been selected by default",MESSAGE_STYLE_INFO)
            else
                call Message.Show("The "+HIGHLIGHT+"Normal Game|r"+" mode has been selected by voting",MESSAGE_STYLE_INFO)
            endif
            call Message.Show("Choose your Hero, battle starts in 2 Min",MESSAGE_STYLE_INFO)
            call RemoveWalls.execute(1)
            call Hostile_Setup()
            call BaseLib_Setup()
            call GoldMine_GSetup()
            call GuardPath_Setup()
            call AncientObelisk_Setup()
            call DefenderSquad_Setup.evaluate()
            call WarHall_Setup.evaluate()
            //call Pet_Setup.execute()
            set GameModeTimer = CreateTimer()
            set GameModeDialog = CreateTimerDialog(GameModeTimer)
            call TimerDialogDisplay(GameModeDialog,true)
            call TimerStart(GameModeTimer,Game.TIME_TO_INIT_GAME,false,function InitGame)
        endif
        if GameMode.winner.name == "Last Man Standing" then
            set Game.Mode = GAME_MODE_LMS
            call Message.Show("The "+HIGHLIGHT+"Last Man Standing|r"+" mode has been selected by voting",MESSAGE_STYLE_INFO)
            call Message.Show("Choose your Hero, the first round will begin in 2 min",MESSAGE_STYLE_LMS)
            call RemoveWalls.execute(2)
            call RemoveUnit(gg_unit_n00C_0039)
            call RemoveUnit(gg_unit_n016_0041)
            call RemoveUnit(gg_unit_ngme_0040)
            call LastManStanding_Setup.evaluate()
            call LastManStanding_Start.evaluate()
            set Game.GameStarted = true
        endif
        if GameMode.winner.name == "Obelisk Defend" then
            set Game.Mode = GAME_MODE_OD
            call Message.Show("The "+HIGHLIGHT+"Obelisk Defend|r"+" mode has been selected by voting",MESSAGE_STYLE_INFO)
            call Message.Show("Choose your Hero, the first round will begin in 2 min",MESSAGE_STYLE_LMS)
            call RemoveWalls.execute(2)
            call AncientObelisk_Setup()
            call UnitRemoveAbility(AncientObelisk.obelisk,'Avul')
            call ObeliskDefend_Setup.evaluate()
            call ObeliskDefend_Start.evaluate()    
            set Game.GameStarted = true
        endif
        call Runes_Setup()
        call Runes_CreateRandomRune()
        call GameMultiboard_Setup()
        call PickHeroSystem_Setup()
        call GameLoop.Start()
    endfunction
   
    private function PresentationMessage takes nothing returns nothing
        call DisplayTimedTextToPlayer(Game.LocalPlayer,0.8,0.7,300.0,"|c00ffcc00THE GOLDEN LANDS v3.0|r  ")
        call DisplayTimedTextToPlayer(Game.LocalPlayer,0.8,0.7,300.0,"  |c00808080Preloading, Please wait.|r")
    endfunction
   
    private function InitCamera takes nothing returns nothing
        call FogMaskEnable(false)
        call ShowInterface(false, 0.00 )
        call CinematicFadeBJ( bj_CINEFADETYPE_FADEOUT, 0, "ReplaceableTextures\\CameraMasks\\Black_mask.blp", 0, 0, 0, 0 )
    endfunction
   
    private function SetupGame takes nothing returns boolean
        call Game.DefineVariables()
        call PresentationMessage()
        set ON_INDEX = Event.create()
        set ON_DEINDEX = Event.create()
        call IndexEvent_Setup()
        call DamageEngineInit.evaluate()
        call UnitIndex_Setup()
        call IsUnitMoving_Setup()
        set ENABLE_INDEXER = false
        call PreloadGen.Start()
        //Misc Stuff
        call SetMapFlag(MAP_LOCK_RESOURCE_TRADING, true)
        call CameraSetSmoothingFactor(Game.CAMERA_SMOTH_FACTOR)
        call ShowUnit( gg_unit_n018_0054,false)
        call ShowUnit( gg_unit_n018_0056,false)
        call FogEnable(false)
        call FogEnable(true)
        //Misc Stuff
        call TriggerSleepAction(Game.TIME_PRELOADING)
        set ENABLE_INDEXER = true
        call SetFloatGameState(GAME_STATE_TIME_OF_DAY,Game.TIME_OF_DAY)
        //Not Related GamePlay initializations
        call InitEnviromentFix()
        call MapInfo_Setup()
        call TreeRespawn_Setup()
        //Not Related GamePlay initializations
        //Core
        call Message_init()
        call TeamLib_Setup()
        call PlayerLib_Setup()
        call InCombat_Setup()
        call BountyExp_Setup()
        //Core
        //Items
        call Enchant_Setup()
        call WeaponData_Setup.execute()
        call ArmorData_Setup.execute()
        call TrinketData_Setup.execute()
        call MagicData_Setup.execute()
        call ConsumableData_Setup.execute()
        call MiscData_Setup.execute()
        //Items
        //AI
        call ItemBuild_Setup()
        call AIRegion.Init()
        //AI
        call DamageTextTag_Setup()
        call Perks_Setup()
        call AbilityLibrary_Setup()
        call Teleport_Setup.execute()
        call GateTower_Setup.execute()
        call ShowInterface(true, 3 )
        call CinematicFadeBJ( bj_CINEFADETYPE_FADEIN, 3, "ReplaceableTextures\\CameraMasks\\Black_mask.blp", 0, 0, 0, 0 )
        call ClearTextMessages()
        call PickHeroSystem_LockCameraVision()
        call GameModes_Setup()
        set GameModeTimer = CreateTimer()
        set GameModeDialog = CreateTimerDialog(GameModeTimer)
        call TimerDialogDisplay(GameModeDialog,true)
        call TimerStart(GameModeTimer,20.00,false,function GameModeEnd)
        call Message.Show("The Players have 20 seconds to select the game mode",MESSAGE_STYLE_INFO)
        call DestroyTrigger(GetTriggeringTrigger())
        return false
    endfunction
   
    private function init takes nothing returns nothing
        local trigger t = CreateTrigger()
        call TriggerRegisterTimerEvent(t,0.1,false)
        call InitCamera()
        call TriggerAddAction(t,function SetupGame)
        set t = null
    endfunction
endscope
library PlayerLib uses MiscLibrary
   
    globals
        integer MAX_SP_D = 0
        integer MAX_AT_D = 0
        integer MAX_H_D = 0
        integer MAX_CRIT_D = 0
        integer MAX_DMG_D = 0
        integer MAX_SP_T = 0
        integer MAX_AT_T = 0
        integer MAX_H_T = 0
        integer MAX_CRIT_T = 0
        integer MAX_DMG_T = 0
        integer MAX_KILLS = 0
        integer MAX_DEATHS = 0
        integer MAX_GOLD = 0
        integer MAX_HONOR = 0
        integer MAX_GOLD_L = 0
        integer MAX_BASES_T = 0
        integer MAX_MINES_T = 0
        integer MAX_OBELISK_T = 0
    endglobals
   
    public function BuildMax takes nothing returns nothing
        local integer i = 2
        local Players p
        loop
            set p = Players[i]
            if p.spellDmgD > MAX_SP_D then
                set MAX_SP_D = p.spellDmgD
            endif
            if p.attDmgD > MAX_AT_D then
                set MAX_AT_D = p.attDmgD
            endif
            if p.healD > MAX_H_D then
                set MAX_H_D = p.healD
            endif
            if p.maxCritD > MAX_CRIT_D then
                set MAX_CRIT_D = p.maxCritD
            endif
            if p.totalDmgD > MAX_DMG_D then
                set MAX_DMG_D = p.totalDmgD
            endif
            if p.spellDmgT > MAX_SP_T then
                set MAX_SP_T = p.spellDmgT
            endif
            if p.attDmgT > MAX_AT_T then
                set MAX_AT_T = p.attDmgT
            endif
            if p.maxCritT > MAX_CRIT_T then
                set MAX_CRIT_T = p.maxCritT
            endif
            if p.totalDmgT > MAX_DMG_T then
                set MAX_DMG_T = p.totalDmgT
            endif
            if p.totalGold > MAX_GOLD then
                set MAX_GOLD = p.totalGold
            endif
            if p.totalHonor > MAX_HONOR then
                set MAX_HONOR = p.totalHonor
            endif
            if p.goldLost > MAX_GOLD_L then
                set MAX_GOLD_L = p.goldLost
            endif
            if p.basesT > MAX_BASES_T then
                set MAX_BASES_T = p.basesT
            endif
            if p.minesT > MAX_MINES_T then
                set MAX_MINES_T = p.minesT
            endif
            if p.obeliskT > MAX_OBELISK_T then
                set MAX_OBELISK_T = p.obeliskT
            endif
            if p.kills > MAX_KILLS then
                set MAX_KILLS = p.kills
            endif
            if p.deaths > MAX_DEATHS then
                set MAX_DEATHS = p.deaths
            endif
            set i = i + 1
            exitwhen i > Game.PLAYER_MAX
        endloop
    endfunction
   
    struct Players extends array
        string  name
        Hero    hero
        unit    dummy  
        unit    baul
        unit    traitUnit
        unit    voteUnit
        integer kills
        integer deaths
        integer suicides
        integer gold
        integer honor
        real    goldFactor
        boolean left
        boolean isPlaying
        boolean camSmooth
        boolean fog
        integer heroesKilledTemp
        boolean inArena
       
        integer cameraDistance
       
        string ai
       
        //for multiboard
        integer     spellDmgD
        integer     attDmgD
        integer     healD
        integer     maxCritD
        integer     spellDmgT
        integer     attDmgT
        integer     healT
        integer     maxCritT
        integer     totalDmgD
        integer     totalDmgT
        integer     totalGold
        integer     totalHonor
        integer     goldLost
        integer     basesD
        integer     basesT
        integer     minesT
        integer     obeliskT
        integer     creepsE
        integer     creepsN
       
        integer maxCritDTarget
        integer maxCritDType
        integer maxCritTSource
        integer maxCritTType
       
        boolean aoeShow
       
        Table tb
       
        public static integer PlayersActive = 0
        public static integer PlayersTotal = 0
        public static integer TraitCount = 0
       
        public static method create takes player wichPlayer, string n returns thistype
            local thistype this = GetPlayerId(wichPlayer)
            if this <= 6 and wichPlayer != Game.PLAYER_WARCHIEF_ALLIANCE then
                set dummy = CreateUnit(wichPlayer,'ddot',Team[1].startX,Team[1].startY,0)
            elseif this <= 11 and wichPlayer != Game.PLAYER_WARCHIEF_HORDE then
                set dummy = CreateUnit(wichPlayer,'ddot',Team[2].startX,Team[2].startY,0)
            else
                set dummy = CreateUnit(wichPlayer,'ddot',Game.HIDE_X,Game.HIDE_Y,0)
            endif
            if wichPlayer != Game.PLAYER_NEUTRAL_HOSTILE then
                set traitUnit = CreateUnit(wichPlayer,HeroicTraits_TRAIT_UNIT_ID,Game.HIDE_X,Game.HIDE_Y,0)
            endif
            if this >= 2 and this <= 11 and GetPlayerController(wichPlayer) != MAP_CONTROL_COMPUTER then
                set voteUnit = CreateUnit(wichPlayer,'h00F',GetRectCenterX(gg_rct_PickRegion),GetRectCenterY(gg_rct_PickRegion),0)
                if Game.LocalPlayer != wichPlayer then
                    call SetUnitScale(voteUnit,0,0,0)
                endif
                call SelectUnitForPlayer(voteUnit,wichPlayer,true)
            endif
            set cameraDistance = Game.DEFAULT_CAMERA
            set name = n
            set kills = 0
            set deaths = 0
            set suicides = 0
            set gold = 0
            set honor = 0
            set left = false
            set isPlaying = true
            set camSmooth = true
            set fog = true
            set tb = Table.create()
            set inArena = false
            //alala
            set spellDmgD = 0
            set attDmgD = 0
            set healD = 0
            set attDmgT = 0
            set maxCritD = 0
            set spellDmgT = 0
            set healT = 0
            set maxCritT = 0
            set totalDmgD = 0
            set totalDmgT = 0
            set totalGold = 0
            set totalHonor = 0
            set goldLost = 0
            set basesD = 0
            set basesT = 0
            set minesT = 0
            set obeliskT = 0
            set creepsE = 0
            set creepsN = 0
            set maxCritDTarget = 0
            set maxCritDType = 0
            set maxCritTSource = 0
            set maxCritTType = 0
            set heroesKilledTemp = 0
            set aoeShow = true
            return this
        endmethod
       
        public static method RemoveVotingUnits takes nothing returns nothing
            local integer  i = 2
            loop
                if thistype[i].voteUnit != null then
                    call RemoveUnit(thistype[i].voteUnit)
                endif
                set i = i + 1
                exitwhen i > Game.PLAYER_MAX
            endloop
        endmethod
       
        public static method CheckPositionPenalty takes nothing returns nothing
            local integer i = 2
            local DamageOptions op
            local real x
            local real y
            local real hx
            local real hy
            if Game.Mode == GAME_MODE_NORMAL then
                if not Game.GameStarted then
                    loop
                        if thistype[i].isPlaying and thistype[i].hero != 0 then
                            if i < 7 then
                                set x = Team[1].startX
                                set y = Team[1].startX
                            else
                                set x = Team[2].startX
                                set y = Team[2].startX
                            endif
                            if Distance(x,y,GetUnitX(thistype[i].hero.hero),GetUnitY(thistype[i].hero.hero)) > 3000 then
                                call SetUnitX(thistype[i].hero.hero,x)
                                call SetUnitY(thistype[i].hero.hero,y)
                            endif
                        endif
                        set i = i + 1
                        exitwhen i > Game.PLAYER_MAX
                    endloop
                endif
            else
                if Game.Mode == GAME_MODE_LMS or Game.Mode == GAME_MODE_OD then
                    if Game.RoundStarted then
                        set x = GetRectCenterX(gg_rct_FightRegion)
                        set y = GetRectCenterY(gg_rct_FightRegion)
                        loop
                            if thistype[i].isPlaying and thistype[i].hero != 0 then
                                if thistype[i].inArena then
                                    if not RectContainsCoords(gg_rct_FightRegion,GetUnitX(thistype[i].hero.hero),GetUnitY(thistype[i].hero.hero)) then
                                        set op = DamageOptions.create()
                                        set op.fixedDamage = true
                                        call CodeDamage.Damage(thistype[i].hero.hero,thistype[i].hero.hero,100,udg_DamageTypePure,"",0,op)
                                    endif
                                else
                                    if Distance(GetPlayerStartLocationX(Player(i)),GetPlayerStartLocationY(Player(i)),GetUnitX(thistype[i].hero.hero),GetUnitY(thistype[i].hero.hero)) > 2700 then
                                        call SetUnitX(thistype[i].hero.hero,x)
                                        call SetUnitY(thistype[i].hero.hero,y)
                                    endif
                                endif
                            endif
                            set i = i + 1
                            exitwhen i > Game.PLAYER_MAX
                        endloop
                    endif
                endif
            endif
        endmethod
    endstruct
   
    function GetPlayerDummy takes player p returns unit
        return Players[GetPlayerId(p)].dummy
    endfunction
   
    function GetPlayerHero takes player p returns Hero
        return Players[GetPlayerId(p)].hero
    endfunction
   
    function GetPlayerTeamEx takes player p returns Team
        if Team[1].isPlayerInTeam(p) then
            return Team[1]
        endif
       
        if Team[2].isPlayerInTeam(p) then
            return Team[2]
        endif
        return 0
    endfunction
   
    function IsHeroInBase takes player p returns boolean
        local Hero h = GetPlayerHero(p)
        if GetPlayerTeamEx(p) == 1 then
            return RectContainsUnit(gg_rct_PickItemsHorde,h.hero)
        else
            return RectContainsUnit(gg_rct_PickItemsAlliance,h.hero)
        endif
        return false
    endfunction
   
    public function Setup takes nothing returns nothing
        local integer i = 2
        local player tempPlayer
        local Players p
        call SetPlayerName(Game.PLAYER_WARCHIEF_ALLIANCE,"The Alliance")
        call SetPlayerName(Game.PLAYER_WARCHIEF_HORDE,"The Horde")
        call SetPlayerOnScoreScreen(Game.PLAYER_WARCHIEF_ALLIANCE, false)
        call SetPlayerOnScoreScreen(Game.PLAYER_WARCHIEF_HORDE, false)
        call SetPlayerState(Game.PLAYER_NEUTRAL_HOSTILE,PLAYER_STATE_GIVES_BOUNTY,0)
       
        loop
            set tempPlayer = Player(i)
            if GetPlayerSlotState(tempPlayer) == PLAYER_SLOT_STATE_PLAYING then
                set p = Players.create(tempPlayer,GetPlayerName(tempPlayer))
                set Players.PlayersActive = Players.PlayersActive + 1
                set Players.PlayersTotal = Players.PlayersTotal + 1
                //Force
                call DamageTT[i].setup()
                call PlayerBounty.Init(i)
                if i <= 6 then
                    call Team[1].addPlayer(tempPlayer)
                    call SetPlayerAllianceStateBJ(Game.PLAYER_WARCHIEF_HORDE,tempPlayer,bj_ALLIANCE_ALLIED_VISION)
                    call SetPlayerAllianceStateBJ(tempPlayer,Game.PLAYER_WARCHIEF_HORDE,bj_ALLIANCE_ALLIED_VISION)
                else
                    call SetPlayerAllianceStateBJ(Game.PLAYER_WARCHIEF_ALLIANCE,tempPlayer,bj_ALLIANCE_ALLIED_VISION)
                    call SetPlayerAllianceStateBJ(tempPlayer,Game.PLAYER_WARCHIEF_ALLIANCE,bj_ALLIANCE_ALLIED_VISION)
                    call Team[2].addPlayer(tempPlayer)
                endif
                call AddPlayerGold(tempPlayer,Game.PLAYER_INITIAL_GOLD)
                set p.goldFactor = 1.00
                if GetPlayerController(tempPlayer) == MAP_CONTROL_COMPUTER then
                    call AddPlayerBountyPercent.evaluate(tempPlayer,0.10)
                    if GetAIDifficulty(tempPlayer) == AI_DIFFICULTY_NEWBIE then
                        set p.ai = "E"
                        set p.goldFactor = 0.80
                        call AddPlayerExpPercent.evaluate(tempPlayer,0.04)
                    elseif GetAIDifficulty(tempPlayer) == AI_DIFFICULTY_NORMAL then
                        set p.ai = "N"
                        set p.goldFactor = 0.60
                        //call AddPlayerBountyPercent.evaluate(tempPlayer,0.05)
                        call AddPlayerExpPercent.evaluate(tempPlayer,0.08)
                    elseif GetAIDifficulty(tempPlayer) == AI_DIFFICULTY_INSANE then
                        set p.ai = "I"
                        set p.goldFactor = 0.40
                        //call AddPlayerBountyPercent.evaluate(tempPlayer,0.07)
                        call AddPlayerExpPercent.evaluate(tempPlayer,0.12)
                    endif
                else    
                    if Game.FirstPlayer == null then
                        set Game.FirstPlayer = tempPlayer
                    else
                        set Game.IsSinglePlayer = false
                    endif
                endif
               
            endif
            set i = i + 1
            exitwhen i > Game.PLAYER_MAX
        endloop
        if Game.IsSinglePlayer then
            call TestCommands_Setup.evaluate()
        endif
        call Players.create(Game.PLAYER_WARCHIEF_HORDE,"The Horde")
        call Team[1].addPlayer(Game.PLAYER_WARCHIEF_HORDE)
        call PlayerBounty.Init(GetPlayerId(Game.PLAYER_WARCHIEF_HORDE))
        call RemoveUnit(Players[0].traitUnit)
        call Players.create(Game.PLAYER_WARCHIEF_ALLIANCE,"The Alliance")
        call Team[2].addPlayer(Game.PLAYER_WARCHIEF_ALLIANCE)
        call PlayerBounty.Init(GetPlayerId(Game.PLAYER_WARCHIEF_ALLIANCE))
        call RemoveUnit(Players[1].traitUnit)
        call Players.create(Game.PLAYER_NEUTRAL_HOSTILE,"Neutral Hostile")
        set tempPlayer = null
    endfunction
endlibrary
 
library TeamLib uses PlayerLib, GameMultiboard
    globals
    endglobals
   
    struct Team extends array
        string  name
        integer count
        force   forceP
        integer playerCount
        player  captain
        integer bases
        integer goldmines
        integer resources
        integer heroesDeath
        integer kills
        integer deaths
        rect    startReg
        real    startX
        real    startY
        real    waveTime
        WarChief warchief
        unit    gateTower1
        unit    gateTower2
       
        Base     AI_TeamBaseTarget1
        integer  AI_TeamBasePriority1
        GoldMine AI_TeamMineTarget1
        integer  AI_TeamMinePriority1
       
        //LMS
        integer  heroesIn
        integer  heroesTotal
        integer  rounds
        real     totalThreat
        integer  dangerLevel
       
       
        public static method UpdateResources takes nothing returns nothing
            call SetPlayerState(GetEnumPlayer(), PLAYER_STATE_RESOURCE_FOOD_USED, GetPlayerTeamEx(GetEnumPlayer()).resources)
        endmethod
       
        public method addPlayer takes player wichPlayer returns nothing
            set playerCount = playerCount + 1
            call ForceAddPlayer(forceP,wichPlayer)
        endmethod
       
        public method isPlayerInTeam takes player wichPlayer returns boolean
            return IsPlayerInForce(wichPlayer,forceP)
        endmethod
       
        public method addResource takes integer r returns nothing
            set resources = resources + r
            if Game.GameOver then
                return
            endif
            if Game.ResourcesToWin - resources <= 200 then
                if count == 10 then
                    set count = 0
                    call Message.Show(name + " needs "+I2S(Game.ResourcesToWin - resources)+" Resources to Win.",MESSAGE_STYLE_WARNING)
                else
                    set count = count + 1
                endif
            endif
            if resources >= Game.ResourcesToWin then
                set resources = Game.ResourcesToWin
                call Game.RunGameOver(this)  
                call MultiboardUpdateTittle()
            endif
            call MultiboardUpdateTeamResources(this)
            call ForForce(forceP,function thistype.UpdateResources)
        endmethod
       
        public method Create takes rect start, string n returns nothing
            set .forceP = CreateForce()
            set .name = n
            set .count = 10
            set .startReg = start
            set .resources = 0
            set .bases = 0
            set .goldmines = 0
            set .waveTime = 0
            set .heroesDeath = 0
            set .kills = 0
            set .deaths = 0
            set .rounds = 0
            set totalThreat = 0
            set dangerLevel = 0
            set AI_TeamBasePriority1 = 0
            set AI_TeamMinePriority1 = 0
            set .startX = GetRectCenterX(.startReg)
            set .startY = GetRectCenterY(.startReg)
        endmethod
    endstruct
   
    public function Setup takes nothing returns nothing
        call Team[1].Create(gg_rct_HordeStart,"The Horde")
        set Team[1].captain = Game.PLAYER_WARCHIEF_HORDE
        set Team[1].gateTower1 = gg_unit_h008_0036
        set Team[1].gateTower2 = gg_unit_h008_0123
        call SetUnitOwner(gg_unit_h008_0036,Game.PLAYER_WARCHIEF_HORDE,true)
        call SetUnitOwner(gg_unit_h008_0123,Game.PLAYER_WARCHIEF_HORDE,true)
        call RemoveGuardPosition(gg_unit_h008_0036)
        call RemoveGuardPosition(gg_unit_h008_0123)
        call Team[2].Create(gg_rct_AllianceStart,"The Alliance")
        set Team[2].captain = Game.PLAYER_WARCHIEF_ALLIANCE
        set Team[2].gateTower1 = gg_unit_h007_0115
        set Team[2].gateTower2 = gg_unit_h007_0121
        call SetUnitOwner(gg_unit_h007_0115,Game.PLAYER_WARCHIEF_ALLIANCE,true)
        call SetUnitOwner(gg_unit_h007_0121,Game.PLAYER_WARCHIEF_ALLIANCE,true)
        call RemoveGuardPosition(gg_unit_h007_0115)
        call RemoveGuardPosition(gg_unit_h007_0121)
    endfunction
endlibrary

 
scope PathingHidder initializer init
    globals
        destructable array Walls1
        integer count1 = 0
    endglobals

    function RemoveWalls takes integer op returns nothing
        local integer i = 0
        if op == 1 then
            loop
                call RemoveDestructable(Walls1[i])
                set Walls1[i] = null
                set i = i + 1
                exitwhen i == count1
            endloop
        endif
    endfunction

    function Enum takes nothing returns nothing
        local destructable d = GetEnumDestructable()
        local integer id = GetDestructableTypeId(d)
        if id == 'YTpb' or id == 'B009' or id == 'YTpc' then
            call ShowDestructable(d,false)
        else
            if id == 'B00B' then
                set Walls1[count1] = d
                set count1 = count1 + 1
            endif
        endif
        set d = null
    endfunction

    function PathingHidder takes nothing returns nothing
        call EnumDestructablesInRect(bj_mapInitialPlayableArea,null,function Enum)
        call DestroyTrigger(GetTriggeringTrigger())
    endfunction
   
    function init takes nothing returns nothing
        local trigger t = CreateTrigger()
        call TriggerRegisterTimerEvent(t,5.0,false)
        call TriggerAddAction(t,function PathingHidder)
        set t = null
    endfunction
endscope
 
function Trig_Animation_Actions takes nothing returns nothing
    local unit u = GetPlayerHero(GetTriggerPlayer()).hero
    local integer index = S2I(SubString(GetEventPlayerChatString(),6,StringLength(GetEventPlayerChatString())))
    call SetUnitAnimationByIndex(u,index)
    set u = null
endfunction

//===========================================================================
function InitTrig_Animation takes nothing returns nothing
    set gg_trg_Animation = CreateTrigger(  )
    call TriggerRegisterPlayerChatEvent( gg_trg_Animation, Player(2), "-anim", false )
    call TriggerRegisterPlayerChatEvent( gg_trg_Animation, Player(7), "-anim", false )
    call TriggerAddAction( gg_trg_Animation, function Trig_Animation_Actions )
endfunction

 
Order Tracker
  Events
    Unit - A unit Is issued an order targeting an object
    Unit - A unit Is issued an order targeting a point
    Unit - A unit Is issued an order with no target
  Conditions
    ((Triggering unit) is A Hero) Equal to True
  Actions
    Custom script: call BJDebugMsg("order ID: " + I2S(GetIssuedOrderId()))
    Game - Display to (All players) the text: (String((Issued order)))
scope GameCommands initializer init
    function WinResources takes nothing returns nothing
        local player p = EventChatPlayer
        local string s = EventChatCommand
        local string v = EventChatValue
        if p == Player(2) and not Game.GameStarted then
            if s == "rtw" then
                if v == "1" then
                    set Game.ResourcesToWin = 2000
                    call Message.Show("Resources to win the game set to 2000",MESSAGE_STYLE_COMMAND)
                elseif v == "2" then
                    set Game.ResourcesToWin = 3000
                    call Message.Show("Resources to win the game set to 3000",MESSAGE_STYLE_COMMAND)
                elseif v == "3" then
                    set Game.ResourcesToWin = 4000
                    call Message.Show("Resources to win the game set to 4000",MESSAGE_STYLE_COMMAND)
                endif
            endif
        endif
        set p = null
    endfunction
   
    function CameraZoom takes nothing returns nothing
        local player p = EventChatPlayer
        local string s = EventChatCommand
        local string v = EventChatValue
        local integer c = S2I(v)
        if s == "cam" then
            if c <= 3000 and c >= 1500 then
                set Players[GetPlayerId(p)].cameraDistance = c
                if Game.LocalPlayer == p then
                    call SetCameraField(CAMERA_FIELD_TARGET_DISTANCE,c,0.00)
                endif
            endif
        endif
        set p = null
    endfunction
   
    function Movement takes nothing returns nothing
        local player p = EventChatPlayer
        local string s = EventChatCommand
        local Hero h
        if s == "ms" then
            set h = GetPlayerHero(p)
            if h != 0 then
                call Message.ShowToPlayer(p,"Hero Movement Speed: "+I2S(R2I(GetUnitMoveSpeed(h.hero))),MESSAGE_STYLE_COMMAND)
            endif
        endif
        set p = null
    endfunction
   
    function CameraSmooth takes nothing returns nothing
        local player p = EventChatPlayer
        local string s = EventChatCommand
        if s == "camst" then
            if Players[GetPlayerId(p)].camSmooth then
                set Players[GetPlayerId(p)].camSmooth = false
                call Message.ShowToPlayer(p,"Camera smothing turned OFF",MESSAGE_STYLE_COMMAND)
                if Game.LocalPlayer == p then
                    call CameraSetSmoothingFactor(0.00)
                endif
            else
                set Players[GetPlayerId(p)].camSmooth = true
                call Message.ShowToPlayer(p,"Camera smothing turned ON",MESSAGE_STYLE_COMMAND)
                if Game.LocalPlayer == p then
                    call CameraSetSmoothingFactor(Game.CAMERA_SMOTH_FACTOR)
                endif
            endif  
        endif
        set p = null
    endfunction
   
    function Clear takes nothing returns nothing
        local player p = EventChatPlayer
        local string s = EventChatCommand
        if s == "clear" then
            if Game.LocalPlayer == p then
                call ClearTextMessages()
            endif  
        endif
        set p = null
    endfunction
   
    function Unstuck takes nothing returns nothing
        local player p = EventChatPlayer
        local string s = EventChatCommand
        local string v = EventChatValue
        local integer vi
        local Hero h
        local player ps
        if s == "unstuck" then
            set vi = S2I(v)
            set vi = vi + 1
            set ps = Player(vi)
            if GetPlayerController(ps) == MAP_CONTROL_COMPUTER and vi != 0 and vi != 1 then
                set h = GetPlayerHero(ps)
                if h != 0 then
                    call AICore.HeroOrderTP(h,null,h.heroAI.team.startX,h.heroAI.team.startY)
                endif
            endif
        endif
        set p = null
        set ps = null
    endfunction
   
    function AoEX takes nothing returns nothing
        local player p = EventChatPlayer
        local string s = EventChatCommand
        local string v = EventChatValue
        local real a
        local AoE aoe
        local Hero h
        if s == "aoe" then
            set a = S2R(v)
            set h = GetPlayerHero(p)
            if IsHeroInBase(p) and not IsUnitInCombat(h.hero) and (a > 0 and a < 2000) then
                set aoe = AoE.create(0,0,h.hero,a)
                call aoe.setTime(3.0)
            endif
        endif
        set p = null
    endfunction
   
    function AoEShow takes nothing returns nothing
        local player p = EventChatPlayer
        local string s = EventChatCommand
        if s == "aoeshow" then
            set Players[GetPlayerId(p)].aoeShow = not Players[GetPlayerId(p)].aoeShow
            if Players[GetPlayerId(p)].aoeShow then
                call Message.ShowToPlayer(p,"AoE sfx turn on",MESSAGE_STYLE_COMMAND)
            else
                call Message.ShowToPlayer(p,"AoE sfx turn off",MESSAGE_STYLE_COMMAND)
            endif
        endif
        set p = null
    endfunction
   
    function Weather takes nothing returns nothing
        local player p = EventChatPlayer
        local string s = EventChatCommand
        if s == "weather" then
            if Game.LocalPlayer == p then
                call RemoveWeatherEffect(bj_lastCreatedWeatherEffect)
            endif
        endif
        set p = null
    endfunction
   
    private function init takes nothing returns nothing
        call AddCommandListener("rtw",false,function WinResources)
        call AddCommandListener("cam",false,function CameraZoom)
        call AddCommandListener("ms",true,function Movement)
        call AddCommandListener("camst",true,function CameraSmooth)
        call AddCommandListener("clear",true,function Clear)
        call AddCommandListener("unstuck",false,function Unstuck)
        call AddCommandListener("aoe",false,function AoEX)
        call AddCommandListener("aoeshow",true,function AoEShow)
        call AddCommandListener("weather",true,function Weather)
    endfunction
endscope
 
scope TestCommands
    globals
        unit TEST_DUMMY = null
    endglobals
    private function levelx takes nothing returns nothing
        local player p = EventChatPlayer
        local string s = EventChatCommand
        local string v = EventChatValue
        local integer lvl
        local Hero h = GetPlayerHero(p)
        if s == "level" and h != 0 then
            set lvl = S2I(v)
            if lvl > 0 and lvl < 20 then
                loop
                    exitwhen lvl == 0
                    call SetHeroLevel(h.hero,GetHeroLevel(h.hero) + 1,false)
                    set lvl = lvl - 1
                endloop
            endif
        endif
        set p = null
    endfunction
   
    private function ailevel takes nothing returns nothing
        local string s = EventChatCommand
        local string v = EventChatValue
        local player p = Player(S2I(v) + 1)
        local Hero h = GetPlayerHero(p)
        if s == "ailevel" then
            if GetPlayerController(p) == MAP_CONTROL_COMPUTER and h != 0 then
                call SetHeroLevel(h.hero,GetHeroLevel(h.hero) + 1,false)
            endif
        endif
        set p = null
    endfunction
   
    private function goldhonor takes nothing returns nothing
        local player p = EventChatPlayer
        local string s = EventChatCommand
        local string v = EventChatValue
        if s == "gh" then
            call SetPlayerState(p,PLAYER_STATE_RESOURCE_GOLD,999999)
            call SetPlayerState(p,PLAYER_STATE_RESOURCE_LUMBER,999999)
        endif
        set p = null
    endfunction
   
    private function dummy takes nothing returns nothing
        local player p = EventChatPlayer
        local string s = EventChatCommand
        local string v = EventChatValue
        local Hero h = GetPlayerHero(p)
        local Team t = 2/GetPlayerTeamEx(p)
        if s == "dummy" and h != 0 then
            if TEST_DUMMY == null then
                set TEST_DUMMY = CreateUnit(t.captain,'Hmkg',GetUnitX(h.hero),GetUnitY(h.hero),0)
            else
                call RemoveUnit(TEST_DUMMY)
                set TEST_DUMMY = null
            endif
        endif
        set p = null
    endfunction
   
    private function tp takes nothing returns nothing
        local player p = EventChatPlayer
        local string s = EventChatCommand
        local string v = EventChatValue
        local Hero h = GetPlayerHero(p)
        if s == "tp" and h != 0 then
            if GetUnitAbilityLevel(h.hero,'AEbl') != 0 then
                call UnitRemoveAbility(h.hero,'AEbl')
            else
                call UnitAddAbility(h.hero,'AEbl')
            endif
        endif
        set p = null
    endfunction
   
    private function st takes nothing returns nothing
        local player p = EventChatPlayer
        local string s = EventChatCommand
        local string v = EventChatValue
        local Hero h = GetPlayerHero(p)
        if s == "status" and h != 0 then
            call Status.Add(S2I(v),h.hero,4.00,Status_EFFECT[S2I(v)])
        endif
        set p = null
    endfunction
   
    public function Setup takes nothing returns nothing
        local string s
        call AddCommandListener("level",false,function levelx)
        call AddCommandListener("ailevel",false,function ailevel)
        call AddCommandListener("gh",true,function goldhonor)
        call AddCommandListener("dummy",true,function dummy)
        call AddCommandListener("tp",true,function tp)
        call AddCommandListener("status",false,function st)
       
        set s = "|c0000ffffSingle Player Commands:|r|n|n-level x: sets the level of your hero to +x|n -ailevel x: sets the level of the AI number x, to +1|n -gh: gives gold and honor.|n -dummy: summon/unsummon a Dummy hero at hero's position.   |n -tp: gives global teleport ability.|n -status x: apply the status X to your hero for 4 seconds (1: Stun,2: Silence, etc)"
        set bj_lastCreatedQuest = CreateQuest()
        call QuestSetTitle(bj_lastCreatedQuest,"Single Player Commands")
        call QuestSetDescription(bj_lastCreatedQuest, s)
        call QuestSetIconPath(bj_lastCreatedQuest, "ReplaceableTextures\\CommandButtons\\BTNBansheeAdept.blp")
        call QuestSetRequired(bj_lastCreatedQuest, false)
        call QuestSetDiscovered(bj_lastCreatedQuest, true)
        call QuestSetCompleted(bj_lastCreatedQuest, false)
    endfunction
endscope
 
scope PlayerLeave initializer init
    function PlayerLeave takes nothing returns nothing
        local player p = GetTriggerPlayer()
        local Players ps = Players[GetPlayerId(p)]
        local Hero he = GetPlayerHero(p)
        local Team t = GetPlayerTeamEx(p)
        local integer g = GetPlayerState(p,PLAYER_STATE_RESOURCE_GOLD)
        local integer h = GetPlayerState(p,PLAYER_STATE_RESOURCE_LUMBER)
        set t.playerCount = t.playerCount - 1
        if ps.traitUnit == null then
            set Players.TraitCount = Players.TraitCount - 1
        else
            call RemoveUnit(ps.traitUnit)
            set ps.traitUnit = null
        endif
        call SetPlayerState(p,PLAYER_STATE_RESOURCE_GOLD,0)
        call SetPlayerState(p,PLAYER_STATE_RESOURCE_LUMBER,0)
        set Players[GetPlayerId(p)].isPlaying = false
        call DisplayTextToForce(GetPlayersAll(),(GetPlayerName(p)+ " has leave the game" ))
        call SetUnitX(he.hero,t.startX)
        call SetUnitY(he.hero,t.startY)
        call AddPlayersGold(t,g/t.playerCount)
        call AddPlayersHonor(t,h/t.playerCount,true)
        call MultiboardUpdatePlayerName(p,"|c00c0c0c0Leave|r")
        set p = null
    endfunction

    private function init takes nothing returns nothing
        local trigger t = CreateTrigger(  )
        call TriggerRegisterPlayerEvent(t, Player(2), EVENT_PLAYER_LEAVE)
        call TriggerRegisterPlayerEvent(t, Player(3), EVENT_PLAYER_LEAVE)
        call TriggerRegisterPlayerEvent(t, Player(4), EVENT_PLAYER_LEAVE)
        call TriggerRegisterPlayerEvent(t, Player(5), EVENT_PLAYER_LEAVE)
        call TriggerRegisterPlayerEvent(t, Player(6), EVENT_PLAYER_LEAVE)
        call TriggerRegisterPlayerEvent(t, Player(7), EVENT_PLAYER_LEAVE)
        call TriggerRegisterPlayerEvent(t, Player(8), EVENT_PLAYER_LEAVE)
        call TriggerRegisterPlayerEvent(t, Player(9), EVENT_PLAYER_LEAVE)
        call TriggerRegisterPlayerEvent(t, Player(10), EVENT_PLAYER_LEAVE)
        call TriggerRegisterPlayerEvent(t, Player(11), EVENT_PLAYER_LEAVE)
        call TriggerAddAction(t, function PlayerLeave)
        set t = null
    endfunction
endscope
 
library MapInfo
    private function CreateTowerDescription takes nothing returns nothing
        local string s = "|c0000ffffThe Towers are defensive structures that can be controled and spawn units periodically.|r|n|n- The Towers can be captured by placing the hero inside the |c00ff8080circle of power|r, after 15 seconds and if the hero not die or leaves the circle, the Tower will be controlled.|n- The hero need to be |c00ff8080out of combat|r to start controlling the Tower and take less time if more heroes are controlling the Tower at once."
        local string s2 = "|n- If the Tower is destroyed the will become |c00ff8080Neutral |rand will be able to get controlled again.|n- Every controlled Tower will |c00ff8080spawn units|r to attack the next enemy Tower or Gold Mine.|n- The Towers will be Upgraded every 10min (of constant controlled time), increasing his HP, Damage and abilities."
        set bj_lastCreatedQuest = CreateQuest()
        call QuestSetTitle(bj_lastCreatedQuest,"Towers")
        call QuestSetDescription(bj_lastCreatedQuest, s+s2)
        call QuestSetIconPath(bj_lastCreatedQuest, "ReplaceableTextures\\CommandButtons\\BTNHumanWatchTower.blp")
        call QuestSetRequired(bj_lastCreatedQuest, true)
        call QuestSetDiscovered(bj_lastCreatedQuest, true)
        call QuestSetCompleted(bj_lastCreatedQuest, false)
    endfunction
    private function CreateGoldMineDescription takes nothing returns nothing
        local string s = "|c0000ffffThe Gold mines are structures that generate the Resources required to win the game (in the normal game mode).|r|n|n - The Gold Mines generate |c00ff8080Resources |rperiodically, and are guarded by a group of units called |c00ff8080Guards|r.|n"
        local string s2 = "|n- The |c00ff8080Guards |rare elite units that defend the Gold Mine, but if they are defeated the Gold Mine will pass in to enemy hands.|n-|c00ff0000 |rThe |c00ff8080Guards |rare improved (HP, Armor, Abilities) based on the corresponding Base level.|n- Capturing/Losing a Gold Mine, results in a addition/reduction of the team |c00ff8080Resources|r."
        set bj_lastCreatedQuest = CreateQuest()
        call QuestSetTitle(bj_lastCreatedQuest,"Gold Mines")
        call QuestSetDescription(bj_lastCreatedQuest, s+s2)
        call QuestSetIconPath(bj_lastCreatedQuest, "ReplaceableTextures\\CommandButtons\\BTNGoldMine.blp")
        call QuestSetRequired(bj_lastCreatedQuest, true)
        call QuestSetDiscovered(bj_lastCreatedQuest, true)
        call QuestSetCompleted(bj_lastCreatedQuest, false)
    endfunction
    private function CreateCommanderDescription takes nothing returns nothing
        local string s = "|c0000ffffEach team has his Commander, placed on his base, The Warchief for the Horde and the King for the Alliance.|r|n|n"
        local string s2 = "- They have powerful abilities to defend or siege the enemies, these are |c00ff8080Refine|r and |c00ff8080Shout|r Abilities, only one of each type can be activated a a time and shares cooldown.|n- The |c00ff8080Refine |rabilities are applied to the Towers and the Gold Mines Guards.|n- The |c00ff8080Shout |rabilities are applied to all allied heroes."
        set bj_lastCreatedQuest = CreateQuest()
        call QuestSetTitle(bj_lastCreatedQuest,"Team Commander")
        call QuestSetDescription(bj_lastCreatedQuest, s + s2)
        call QuestSetIconPath(bj_lastCreatedQuest, "ReplaceableTextures\\CommandButtons\\BTNINV_helm_crown_C_01_silver.blp")
        call QuestSetRequired(bj_lastCreatedQuest, true)
        call QuestSetDiscovered(bj_lastCreatedQuest, true)
        call QuestSetCompleted(bj_lastCreatedQuest, false)
    endfunction
   
    private function CreateAncientObeliskDescription takes nothing returns nothing
        local string s = "|c0000ffffThe Ancient Obelisk it's a mystical structure that emanates power that recovers the energy of the heroes.|r|n
- It's enabled to capture since |c00ff808010 minutes|r of game.|n- To capture it, a single hero need to |c00ff8080canalize|r for 10 seconds, upon captured lasts |c00ff80805 minutes|r. The hero will be totally disabled during capture.|n- When the capture time ends, the Obelisk will be able to get captured again.|n- Every 5 seconds the Obelisk emits a |c00ff8080ray of healing|r that recovers HP of a random hero that are in combat."

        set bj_lastCreatedQuest = CreateQuest()
        call QuestSetTitle(bj_lastCreatedQuest,"Ancient Obelisk")
        call QuestSetDescription(bj_lastCreatedQuest, s)
        call QuestSetIconPath(bj_lastCreatedQuest, "ReplaceableTextures\\CommandButtons\\BTNIceCrownObelisk.blp")
        call QuestSetRequired(bj_lastCreatedQuest, true)
        call QuestSetDiscovered(bj_lastCreatedQuest, true)
        call QuestSetCompleted(bj_lastCreatedQuest, false)
    endfunction
   
    private function CreateEnchantDescription takes nothing returns nothing
        local string s = "|c0000ffffThe Items can be Enchanted, adding effects or bonuses.|r|n|n- There are 2 types of Enchantments, (|c00ff8080Bonus and Effect|r).|n- The |c00ff8080Bonus Enchantments|r can be applied to any classified item and cost 500 gold.|n- The |c00ff8080Effect Enchantments|r can be applied to a |c00ff8080Tier 3|r |c00ff8080Weapon|r or |c00ff8080Armor|r item types and cost 30 Honor.|n- A item can only have 1 enchant at a time, new purchased Enchantments will replace the current Enchantment."
        set bj_lastCreatedQuest = CreateQuest()
        call QuestSetTitle(bj_lastCreatedQuest,"Enchant Items")
        call QuestSetDescription(bj_lastCreatedQuest, s)
        call QuestSetIconPath(bj_lastCreatedQuest, "ReplaceableTextures\\CommandButtons\\BTNSnazzyScrollGreen.blp")
        call QuestSetRequired(bj_lastCreatedQuest, false)
        call QuestSetDiscovered(bj_lastCreatedQuest, true)
        call QuestSetCompleted(bj_lastCreatedQuest, false)
    endfunction
   
    private function CreateItemClassDescription takes nothing returns nothing
        local string s = "|c0000ffffThe Items are classified by type and can be upgraded up to Tier 3.|r|n|n- There are 4 main types of items |c00ba55d3Weapon,|r|c0000bfff |r|c0066cdaaArmor, |r|c007759eeTrinket |rand|c007759ee |r|c0000bfffMagic Accessory|r.|c0000bfff |r|n- This types of items can be |c00ff8080upgraded|r 2 times, increasing his attributes and the effect of his abilities."
        local string s2 = "|n- To |c00ff8080Upgrade|r an item, selects the item with the ability (Select Item) located in the 'Hero Information' ability and upgrade it by pressing (F), the ability tooltip will shows the information of the |c00ff8080Upgraded|r item.|n- A hero can only carry |c00ff80803 items|r of the same type."
        set bj_lastCreatedQuest = CreateQuest()
        call QuestSetTitle(bj_lastCreatedQuest,"Item Types and Tier System")
        call QuestSetDescription(bj_lastCreatedQuest, s+s2)
        call QuestSetIconPath(bj_lastCreatedQuest, "ReplaceableTextures\\CommandButtons\\BTNINV_Sword_113.blp")
        call QuestSetRequired(bj_lastCreatedQuest, false)
        call QuestSetDiscovered(bj_lastCreatedQuest, true)
        call QuestSetCompleted(bj_lastCreatedQuest, false)
    endfunction
   
    private function CreateSkillUpgradeDescription takes nothing returns nothing
        local string s = "|c0000ffffEvery ability of the hero can be Upgraded, increasing his effects or add new ones.|r|n|n- Each 2 levels starting from level 4, the hero will receive a |c00ff8080point|r to spent in a |c00ff8080Skill Upgrade|r.|n- In total 9 |c00ff8080points|r are given from level 4 to 20.|n- The first Upgrade that reach |c00ff8080level 3|r gives the (|c00ff8080Superior Upgrade|r) effect indicated in the Upgrade tooltip."
        local string s2 = "|n- When |c00ff80802 Skill Upgrades|r reach level 3 will enable the |c00ff80804th Upgrade|r that improves the heroe ultimate ability and bring with it the possibility to choose a |c00ff8080Mastery|r.|n- The |c00ff8080Mastery |rcan be learned at the Altar with Honor, there are 3 Mastery types (|c00ff8080Combat,Dexterity,Wisdom|r) only one of them can be chosen and are different for each hero."
        set bj_lastCreatedQuest = CreateQuest()
        call QuestSetTitle(bj_lastCreatedQuest,"Skill Upgrade/Mastery")
        call QuestSetDescription(bj_lastCreatedQuest, s+s2)
        call QuestSetIconPath(bj_lastCreatedQuest, "ReplaceableTextures\\CommandButtons\\BTNEngineeringUpgrade.blp")
        call QuestSetRequired(bj_lastCreatedQuest, false)
        call QuestSetDiscovered(bj_lastCreatedQuest, true)
        call QuestSetCompleted(bj_lastCreatedQuest, false)
    endfunction
   
    private function CreateNeutralHireDescription takes nothing returns nothing
        local string s = "|c00ffff80The players can hire neutrals with special abilities, from Mercenary Camps.|n|r|c00ff0000[*] |rEvery 5 min there are 2 new neutral unit to Hire in the Mercenary Camp.|n|c00ff0000[*] |rThe Hp and Mp of the neutrals increases based on the heros main attribute."
        set bj_lastCreatedQuest = CreateQuest()
        call QuestSetTitle(bj_lastCreatedQuest,"Neutral Hire")
        call QuestSetDescription(bj_lastCreatedQuest, s)
        call QuestSetIconPath(bj_lastCreatedQuest, "ReplaceableTextures\\CommandButtons\\BTNMercenaryCamp.blp")
        call QuestSetRequired(bj_lastCreatedQuest, false)
        call QuestSetDiscovered(bj_lastCreatedQuest, true)
        call QuestSetCompleted(bj_lastCreatedQuest, false)
    endfunction
   
    private function CreateInfoDescription takes nothing returns nothing
        local string s3 = "-Manuel-#8273"
        local string s = "|c0000ffffThe map has been developed by -ManueL-|r|n|n- Coded in vJass using WEX.|n- Hiveworkshop Account: -Manuel-.|n- Discord Account:"+s3+"|n|nThanks to all the people that makes awesome resources for Warcraft 3.|nSpecial thanks to the AoS Modders discord community and his leader Alexen."
        set bj_lastCreatedQuest = CreateQuest()
        call QuestSetTitle(bj_lastCreatedQuest,"Map Info")
        call QuestSetDescription(bj_lastCreatedQuest, s)
        call QuestSetIconPath(bj_lastCreatedQuest, "ReplaceableTextures\\CommandButtons\\BTNSelectHeroOn.blp")
        call QuestSetRequired(bj_lastCreatedQuest, false)
        call QuestSetDiscovered(bj_lastCreatedQuest, true)
        call QuestSetCompleted(bj_lastCreatedQuest, false)
    endfunction
   
    private function CreateGameCommandsDescription takes nothing returns nothing
        local string s = "|c0000ffffMap Commands|nGame Commands:|r
 -rtw #(1,2,3): set the resources quota to win the game. 1 = 2000, 2 = 3000, 3 = 4000.|n|c0000ffffPlayer Commands:|r
 -ms = Shows hero movement speed.|n -cam = Changes the cam distance (1500-3000)|n -camst = Enable/Disable camera smothing.|n -clear = clear all messages.|n|c0000ffffAI Commands:|r
 -unstuck #(1,10) = Order to the AI player # to use teleport to his base."

        set bj_lastCreatedQuest = CreateQuest()
        call QuestSetTitle(bj_lastCreatedQuest,"Game Commands")
        call QuestSetDescription(bj_lastCreatedQuest, s)
        call QuestSetIconPath(bj_lastCreatedQuest, "ReplaceableTextures\\CommandButtons\\BTNBansheeMaster.blp")
        call QuestSetRequired(bj_lastCreatedQuest, false)
        call QuestSetDiscovered(bj_lastCreatedQuest, true)
        call QuestSetCompleted(bj_lastCreatedQuest, false)
    endfunction
   
    public function Setup takes nothing returns nothing
        call CreateCommanderDescription()
        call CreateGoldMineDescription()
        call CreateTowerDescription()
        call CreateAncientObeliskDescription()
        //-----------------------//
        call CreateItemClassDescription()
        call CreateEnchantDescription()
        call CreateSkillUpgradeDescription()
        //call CreateNeutralHireDescription()
        call CreateGameCommandsDescription()
        call CreateInfoDescription()
    endfunction
endlibrary
 
scope LastManStanding
    globals
        rect array PlayerInitPos
        rect array AI_Stands
        rect array AI_Stands2
        timer       Timer
        timerdialog TimerDialog
        LinkedList  Heroes
        integer    I = 0
        constant integer GOLD_BONUS       = 700
        constant integer HONOR_BONUS      = 10
        Team Winner = 0
    endglobals
   
    private function EndRoundCallback takes nothing returns nothing
        local timer t = GetExpiredTimer()
        local Link h = Heroes.head
        local LoadingBar lb
        local integer gt
        local player ps
        local Players p
        local Team te
        local integer lvl
        local CobraK300 b
        local integer um
        loop
            exitwhen h == 0
            set p = h.data
            set ps = Player(p)
            set te = GetPlayerTeamEx(ps)
            set lvl = GetHeroLevel(p.hero.hero)
            set p.inArena = false
            if not UnitAlive(p.hero.hero) then
                if UnitHasBuff(p.hero.hero,DeadChecker.buff) then
                    call SetUnitX(p.hero.hero,te.startX)
                    call SetUnitY(p.hero.hero,te.startY)
                else
                    call ReviveHero(p.hero.hero,te.startX,te.startY,false)
                endif
                set um = GetUnitData(p.hero.hero,"UnMorph")
                if um != 0 then
                    call AddUnitAnimationProperties(p.hero.hero,"alternate",false)
                    call SetUnitData(p.hero.hero,"UnMorph",0)
                    call UnitAddAbility(p.hero.hero,um)
                    call UnitRemoveAbility(p.hero.hero,um)
                endif
                set lb = GetUnitData(p.hero.hero,"OHBar")
                if lb != 0 then
                    call lb.show(true)
                endif
            else
                call Status.Remove(STATUS_INVULNERABLE,p.hero.hero)
                set b = GetUnitBuff(p.hero.hero,CobraK300.buff).buffAllocIndex
                if b != 0 then
                    call UnitRemoveBuff(p.hero.hero,CobraK300.buff)    
                endif
                call SetUnitX(p.hero.hero,te.startX)
                call SetUnitY(p.hero.hero,te.startY)
            endif
            call IssueImmediateOrder(p.hero.hero,"stop")
            if Game.LocalPlayer == ps then
                call SetCameraPosition(te.startX,te.startY)
                call SelectUnit(p.hero.hero,true)
            endif
            set gt = 75 * p.heroesKilledTemp
            call AddPlayerGold(ps,GOLD_BONUS + gt)
            call AddPlayerHonor(ps,HONOR_BONUS + p.heroesKilledTemp)
            call Message.ShowToPlayer(ps,"You receive "+GOLD_COLOR+"700(+"+I2S(gt)+") Gold|r and "+HONOR_COLOR+"10(+"+I2S(p.heroesKilledTemp)+") Honor|r",MESSAGE_STYLE_LMS)
            set p.heroesKilledTemp = 0
            if Game.Round <= 9 then
                call SetHeroLevel(p.hero.hero,lvl + 1,true)
            else
                call SetHeroLevel(p.hero.hero,lvl + 1,false)
                call SetHeroLevel(p.hero.hero,lvl + 2,true)
            endif
            set h = h.next
        endloop
        set Game.RoundStarted = false
        call Heroes.destroy()
        set Heroes = LinkedList.create()
        call ReleaseTimer(t)
        call StartSound(gg_snd_TowerCapture)
        set t = null
        if Game.Round == 15 then
            if Team[1].rounds > Team[2].rounds then
                call Game.RunGameOver(1)  
            else
                call Game.RunGameOver(2)  
            endif
        else
            call LastManStanding_Start.evaluate()
        endif
    endfunction
   
    public function EndRound takes Team te returns nothing
        local timer t = NewTimer()
        local Link h = Heroes.head
        local Players p
        loop
            exitwhen h == 0
            set p = h.data
            if UnitAlive(p.hero.hero) then
                call Status.Add(STATUS_INVULNERABLE,p.hero.hero,0,0)
            endif
            set h = h.next
        endloop
        if te == 1 then
            call Message.Show("The winner of this round: "+HORDE_COLOR+te.name+"|r",MESSAGE_STYLE_LMS)
        else
            call Message.Show("The winner of this round: "+ALLIANCE_COLOR+te.name+"|r",MESSAGE_STYLE_LMS)
        endif
        call StartSound(gg_snd_GameStart)
        set te.rounds = te.rounds + 1
        set Winner = te
        call TimerStart(t,2.0,false,function EndRoundCallback)
        set t = null
    endfunction
   
    private function Counter takes nothing returns nothing
        local timer t = GetExpiredTimer()
        local Link h = Heroes.head
        local Players p
        set I = I + 1
        if I <= 3 then
            call Message.Show("The fight will begin in "+I2S(I),MESSAGE_STYLE_LMS)
            call StartSound(gg_snd_Clock)
        endif
        if I == 4 then
            set Game.RoundStarted = true
            call ReleaseTimer(t)
            loop
                exitwhen h == 0
                set p = h.data
                call Status.Remove(STATUS_PAUSE,p.hero.hero)
                set h = h.next
            endloop
            call StartSound(gg_snd_GameStart)
        endif
        set t = null
    endfunction
   
    private function StartRound takes nothing returns nothing
        local integer i = 2
        local timer t = NewTimer()
        local real x
        local real y
        local Players p
        local Team te
        set Team[1].heroesIn = 0
        set Team[2].heroesIn = 0
        loop
            set p = Players[i]
            if p.isPlaying and p.hero != 0 then
                set p.inArena = true
                set x = GetRectCenterX(PlayerInitPos[i])
                set y = GetRectCenterY(PlayerInitPos[i])
                set te = GetPlayerTeamEx(Player(i))
                call SetUnitX(p.hero.hero,x)
                call SetUnitY(p.hero.hero,y)
                if te == 1 then
                    call SetUnitFacing(p.hero.hero,0)
                else
                    call SetUnitFacing(p.hero.hero,180)
                endif
                call Status.Add(STATUS_PAUSE,p.hero.hero,0,0)
                call Heroes.add(p)
                set te.heroesIn = te.heroesIn + 1
                if Game.LocalPlayer == Player(i) then
                    call SetCameraPosition(x,y)
                    call SelectUnit(p.hero.hero,true)
                endif
            endif
            set i = i + 1
            exitwhen i > Game.PLAYER_MAX
        endloop
        set I = 0
        call TimerStart(t,1.0,true,function Counter)
    endfunction
   
    public function Start takes nothing returns nothing
        set Game.Round = Game.Round + 1
        set Winner = 0
        if Game.Round <= Game.Rounds then
            if Game.Round > 1 then
                call Message.Show("The next round will begin in 70 seconds",MESSAGE_STYLE_LMS)
                call TimerStart(Timer,70.00,false,function StartRound)
                call TimerDialogDisplay(TimerDialog,true)
                call TimerDialogSetTitle(TimerDialog,"Round: "+I2S(Game.Round))
            else
                call TimerStart(Timer,120.00,false,function StartRound)
                call TimerDialogDisplay(TimerDialog,true)
                call TimerDialogSetTitle(TimerDialog,"Round: "+I2S(Game.Round))
            endif
        endif
    endfunction
   
    public function Setup takes nothing returns nothing
        set PlayerInitPos[2] = gg_rct_StartHero1
        set PlayerInitPos[3] = gg_rct_StartHero2
        set PlayerInitPos[4] = gg_rct_StartHero3
        set PlayerInitPos[5] = gg_rct_StartHero4
        set PlayerInitPos[6] = gg_rct_StartHero5
        set PlayerInitPos[7] = gg_rct_StartHero6
        set PlayerInitPos[8] = gg_rct_StartHero7
        set PlayerInitPos[9] = gg_rct_StartHero8
        set PlayerInitPos[10] = gg_rct_StartHero9
        set PlayerInitPos[11] = gg_rct_StartHero10
        set AI_Stands[0] = gg_rct_StartHero8
        set AI_Stands[1] = gg_rct_Arena_Stand_1
        set AI_Stands[2] = gg_rct_Arena_Stand_2
        set AI_Stands[3] = gg_rct_Arena_Stand_3
        set AI_Stands[4] = gg_rct_Arena_Stand_4
        set AI_Stands[5] = gg_rct_Arena_Stand_5
        set AI_Stands[6] = gg_rct_Arena_Stand_6
        set AI_Stands[7] = gg_rct_StartHero3
        set Heroes = LinkedList.create()
        set Timer = CreateTimer()
        set TimerDialog = CreateTimerDialog(Timer)
    endfunction
endscope
scope ObeliskDefend
    globals
        private AoE Circle
        integer ODWinner = 0
        Team CurrentOwner = 0
    endglobals
   
    private function EndRoundCallback takes nothing returns nothing
        local timer t = GetExpiredTimer()
        local Link h = Heroes.head
        local LoadingBar lb
        local player ps
        local Players p
        local integer gt
        local Team te
        local integer lvl
        local CobraK300 b
        local integer um
        loop
            exitwhen h == 0
            set p = h.data
            set ps = Player(p)
            set te = GetPlayerTeamEx(ps)
            set lvl = GetHeroLevel(p.hero.hero)
            set p.inArena = false
            if not UnitAlive(p.hero.hero) then
                if UnitHasBuff(p.hero.hero,DeadChecker.buff) then
                    call SetUnitX(p.hero.hero,te.startX)
                    call SetUnitY(p.hero.hero,te.startY)
                else
                    call ReviveHero(p.hero.hero,te.startX,te.startY,false)
                endif
                set um = GetUnitData(p.hero.hero,"UnMorph")
                if um != 0 then
                    call AddUnitAnimationProperties(p.hero.hero,"alternate",false)
                    call SetUnitData(p.hero.hero,"UnMorph",0)
                    call UnitAddAbility(p.hero.hero,um)
                    call UnitRemoveAbility(p.hero.hero,um)
                endif
                set lb = GetUnitData(p.hero.hero,"OHBar")
                if lb != 0 then
                    call lb.show(true)
                endif
            else
                call Status.Remove(STATUS_INVULNERABLE,p.hero.hero)
                set b = GetUnitBuff(p.hero.hero,CobraK300.buff).buffAllocIndex
                if b != 0 then  
                    call UnitRemoveBuff(p.hero.hero,CobraK300.buff)    
                endif
                call SetUnitX(p.hero.hero,te.startX)
                call SetUnitY(p.hero.hero,te.startY)
            endif
            call IssueImmediateOrder(p.hero.hero,"stop")
            if Game.LocalPlayer == ps then
                call SetCameraPosition(te.startX,te.startY)
                call SelectUnit(p.hero.hero,true)
            endif
            set gt = 75 * p.heroesKilledTemp
            call AddPlayerGold(ps,GOLD_BONUS + gt)
            call AddPlayerHonor(ps,HONOR_BONUS + p.heroesKilledTemp)
            call Message.ShowToPlayer(ps,"You receive "+GOLD_COLOR+"700(+"+I2S(gt)+") Gold|r and "+HONOR_COLOR+"10(+"+I2S(p.heroesKilledTemp)+") Honor|r",MESSAGE_STYLE_LMS)
            set p.heroesKilledTemp = 0
            if Game.Round <= 9 then
                call SetHeroLevel(p.hero.hero,lvl + 1,true)
            else
                call SetHeroLevel(p.hero.hero,lvl + 1,false)
                call SetHeroLevel(p.hero.hero,lvl + 2,true)
            endif
            set h = h.next
        endloop
        set Game.RoundStarted = false
        call Heroes.destroy()
        set Heroes = LinkedList.create()
        call ReleaseTimer(t)
        call StartSound(gg_snd_TowerCapture)
        set t = null
        if Game.Round == 15 then
            if Team[1].rounds > Team[2].rounds then
                call Game.RunGameOver(1)  
            else
                call Game.RunGameOver(2)  
            endif
        else
            call ObeliskDefend_Start.evaluate()
        endif
    endfunction
   
    public function EndRound takes Team te returns nothing
        local timer t = NewTimer()
        local Link h = Heroes.head
        local Players p
        set Game.RoundStarted = false
        loop
            exitwhen h == 0
            set p = h.data
            if UnitAlive(p.hero.hero) then
                call Status.Add(STATUS_INVULNERABLE,p.hero.hero,0,0)
            endif
            set h = h.next
        endloop
        set AncientObelisk.owner = 0
        call AncientObelisk.ChangeOwner(true)
        call AncientObelisk.Enable(false)
        call BlzSetSpecialEffectColor(Circle.sfx,255,255,255)
        call SetUnitState(AncientObelisk.obelisk,UNIT_STATE_LIFE,100)
        if te == 1 then
            call Message.Show("The winner of this round: "+HORDE_COLOR+te.name+"|r",MESSAGE_STYLE_LMS)
        else
            call Message.Show("The winner of this round: "+ALLIANCE_COLOR+te.name+"|r",MESSAGE_STYLE_LMS)
        endif
        set te.rounds = te.rounds + 1
        set ODWinner = te
        call TimerStart(t,2.0,false,function EndRoundCallback)
        set t = null
    endfunction
   
    private function EndRoundTimer takes nothing returns nothing
        if ODWinner == 0 then
            if AncientObelisk.owner == CurrentOwner then
                call EndRound(CurrentOwner)
            endif
        endif
        call PauseTimer(Timer)
        call TimerDialogDisplay(TimerDialog,false)
    endfunction
   
    private function Counter takes nothing returns nothing
        local timer t = GetExpiredTimer()
        local Link h = Heroes.head
        local Players p
        set I = I + 1
        if I <= 3 then
            call Message.Show("The fight will begin in "+I2S(I),MESSAGE_STYLE_LMS)
            call StartSound(gg_snd_Clock)
        endif
        if I == 4 then
            set Game.RoundStarted = true
            call ReleaseTimer(t)
            loop
                exitwhen h == 0
                set p = h.data
                call Status.Remove(STATUS_PAUSE,p.hero.hero)
                set h = h.next
            endloop
            call StartSound(gg_snd_GameStart)
            if CurrentOwner == 1 then
                call BlzSetSpecialEffectColor(Circle.sfx,255,0,0)
            else
                call BlzSetSpecialEffectColor(Circle.sfx,0,0,255)
            endif
            call AncientObelisk.Enable(true)
            set AncientObelisk.owner = CurrentOwner
            call AncientObelisk.ChangeOwner(false)
            if CurrentOwner == 1 then
                call Message.Show(HORDE_COLOR+CurrentOwner.name + "|r will have to defend the Obelisk for 90s min to win",MESSAGE_STYLE_LMS)
            else
                call Message.Show(ALLIANCE_COLOR+CurrentOwner.name + "|r will have to defend the Obelisk for 90s min to win",MESSAGE_STYLE_LMS)
            endif
            call TimerStart(Timer,90.00,false,function EndRoundTimer)
            call TimerDialogSetTitle(TimerDialog,"Round End")
        endif
        set t = null
    endfunction
   
    private function StartRound takes nothing returns nothing
        local integer i = 2
        local integer r
        local real a
        local timer t = NewTimer()
        local real x
        local real y
        local Players p
        local Team te
        local LinkedList l = LinkedList.create()
        local Link link
        set Team[1].heroesIn = 0
        set Team[2].heroesIn = 0
        set CurrentOwner = GetRandomInt(1,2)
        if CurrentOwner == 1 then
            call l.add(1)
            call l.add(2)
            call l.add(3)
            call l.add(4)
            call l.add(5)
        else
            call l.add(0)
            call l.add(1)
            call l.add(2)
            call l.add(3)
            call l.add(4)
        endif
        loop
            set p = Players[i]
            if p.isPlaying and p.hero != 0 then
                set te = GetPlayerTeamEx(Player(i))
                if te == CurrentOwner then
                    set a = GetRandomReal(0,360) * bj_DEGTORAD
                    set x = AncientObelisk.x + GetRandomReal(50,500) * Cos(a)
                    set y = AncientObelisk.y + GetRandomReal(50,500) * Sin(a)
                    call SetUnitFacing(p.hero.hero,Angle(x,y,AncientObelisk.x,AncientObelisk.y) * bj_RADTODEG)
                else
                    set r = GetRandomInt(1,l.size)
                    set link = l.getByIndex(r)
                    if p.hero.heroAI != -1 then
                        set p.hero.heroAI.iniPlace = link.data
                    endif
                    set x = GetRectCenterX(AI_Stands2[link.data])
                    set y = GetRectCenterY(AI_Stands2[link.data])
                    call l.remove(link)
                    call SetUnitFacing(p.hero.hero,Angle(x,y,AncientObelisk.x,AncientObelisk.y) * bj_RADTODEG)
                endif
                call SetUnitX(p.hero.hero,x)
                call SetUnitY(p.hero.hero,y)
                call Status.Add(STATUS_PAUSE,p.hero.hero,0,0)
                call Heroes.add(p)
                set p.inArena = true
                set te.heroesIn = te.heroesIn + 1
                if Game.LocalPlayer == Player(i) then
                    call SetCameraPosition(x,y)
                    call SelectUnit(p.hero.hero,true)
                endif
            endif
            set i = i + 1
            exitwhen i > Game.PLAYER_MAX
        endloop
        set te.heroesTotal = te.heroesIn
        set I = 0
        call l.destroy()
        call TimerStart(t,1.0,true,function Counter)
    endfunction
   
    public function Start takes nothing returns nothing
        set Game.Round = Game.Round + 1
        set ODWinner = 0
        if Game.Round <= Game.Rounds then
            if Game.Round > 1 then
                call Message.Show("The next round will begin in 70 seconds",MESSAGE_STYLE_LMS)
                call TimerStart(Timer,70.00,false,function StartRound)
                call TimerDialogDisplay(TimerDialog,true)
                call TimerDialogSetTitle(TimerDialog,"Round: "+I2S(Game.Round))
                call TimerDialogDisplay(TimerDialog,true)
                call BlzSetUnitMaxHP(AncientObelisk.obelisk,100 + 10 * Game.Round)
                call SetUnitState(AncientObelisk.obelisk,UNIT_STATE_LIFE,10000)
            else
                call TimerStart(Timer,120.00,false,function StartRound)
                call TimerDialogDisplay(TimerDialog,true)
                call TimerDialogSetTitle(TimerDialog,"Round: "+I2S(Game.Round))
                call TimerDialogDisplay(TimerDialog,true)
            endif
        endif
    endfunction
   
    private function onPostDamage takes nothing returns nothing
        local DamageData data = DamageEvent.EventData
        if data.target == AncientObelisk.obelisk and not data.isMiss and not data.isAbsorbed then
            if IsUnitType(data.source,UNIT_TYPE_HERO) then
                if AncientObelisk.owner == 0 then
                    set data.damageMod = 0
                    set data.isAbsorbed = true
                else
                    set data.damageMod = 5
                    if GetUnitState(data.target,UNIT_STATE_LIFE) - data.damageMod <= 0.405 then
                        set data.damageMod = 0
                        set data.isAbsorbed = true
                        call EndRound(2/AncientObelisk.owner)
                    endif
                endif
            else
                set data.damageMod = 0
                set data.isAbsorbed = true
            endif
        endif
    endfunction
   
    public function Setup takes nothing returns nothing
        set PlayerInitPos[2] = gg_rct_StartHero1
        set PlayerInitPos[3] = gg_rct_StartHero2
        set PlayerInitPos[4] = gg_rct_StartHero3
        set PlayerInitPos[5] = gg_rct_StartHero4
        set PlayerInitPos[6] = gg_rct_StartHero5
        set PlayerInitPos[7] = gg_rct_StartHero6
        set PlayerInitPos[8] = gg_rct_StartHero7
        set PlayerInitPos[9] = gg_rct_StartHero8
        set PlayerInitPos[10] = gg_rct_StartHero9
        set PlayerInitPos[11] = gg_rct_StartHero10
        set AI_Stands[0] = gg_rct_StartHero8
        set AI_Stands[1] = gg_rct_Arena_Stand_1
        set AI_Stands[2] = gg_rct_Arena_Stand_2
        set AI_Stands[3] = gg_rct_Arena_Stand_3
        set AI_Stands[4] = gg_rct_Arena_Stand_4
        set AI_Stands[5] = gg_rct_Arena_Stand_5
        set AI_Stands[6] = gg_rct_Arena_Stand_6
        set AI_Stands[7] = gg_rct_StartHero3
        set AI_Stands2[0] = gg_rct_StartHero3
        set AI_Stands2[1] = gg_rct_Arena_Stand_1
        set AI_Stands2[2] = gg_rct_Arena_Stand_3
        set AI_Stands2[3] = gg_rct_Arena_Stand_4
        set AI_Stands2[4] = gg_rct_Arena_Stand_6
        set AI_Stands2[5] = gg_rct_StartHero8
        set Heroes = LinkedList.create()
        set Timer = CreateTimer()
        set TimerDialog = CreateTimerDialog(Timer)
        set Circle = AoE.create(AncientObelisk.x,AncientObelisk.y,null,600)
        call DamageEvent.RegisterPostCalculation(Filter(function onPostDamage))
    endfunction
endscope

 
library GameModes uses SpellEffectEvent
    globals
        Poll GameMode
        private constant integer MODE_1 = 'A0A8'
        private constant integer MODE_2 = 'A0A9'
        private constant integer MODE_3 = 'A0AA'
        private constant integer MODE_4 = 'A0BI'
        private constant integer MODE_5 = 'A0AA'
    endglobals
   
    private function onCast takes nothing returns nothing
        local integer id = GetSpellAbilityId()
        local player p = GetTriggerPlayer()
        if id == MODE_1 then
            call GameMode.vote(p,"Normal")
        elseif id == MODE_2 then
            call GameMode.vote(p,"Last Man Standing")
        elseif id == MODE_3 then
            call GameMode.vote(p,"Obelisk Defend")
        elseif id == MODE_4 then
            call GameMode.vote(p,"Survival")
        endif
        set p = null
    endfunction
   
    public function Setup takes nothing returns nothing
        set GameMode = Poll.create("GameMode")
        call GameMode.addOption("Normal")
        call GameMode.addOption("Last Man Standing")
        call GameMode.addOption("Obelisk Defend")
        call GameMode.addOption("Survival")
        call RegisterSpellEffectEvent(MODE_1, function onCast)
        call RegisterSpellEffectEvent(MODE_2, function onCast)
        call RegisterSpellEffectEvent(MODE_3, function onCast)
        call RegisterSpellEffectEvent(MODE_4, function onCast)
    endfunction
endlibrary
library VoteSystem
   
    struct Option extends array
        implement Alloc
        string name
        integer count
       
        public static method create takes string n returns thistype
            local thistype this = thistype.allocate()
            set name = n
            return this
        endmethod
       
        public method destroy takes nothing returns nothing
            set name = ""
            set count = 0
            call this.deallocate()
        endmethod
    endstruct
   
    struct Poll extends array
        implement Alloc
        LinkedList options
        string name
        Table tb
        Option winner
       
        public method verifyWinner takes nothing returns nothing
            local integer totalVotes = 0
            local integer max = 0
            local integer i = 0
            local integer array winners
            local Link h = options.head
            local Option o
            loop
                exitwhen h == 0
                set o = h.data
                set totalVotes = totalVotes + o.count
                if o.count > max then
                    set max = o.count
                endif
                set h = h.next
            endloop
            if totalVotes != 0 then
                set h = options.head
                loop    
                    exitwhen h == 0
                    set o = h.data
                    if o.count == max then
                        set winners[i] = o
                        set i = i + 1
                    endif
                    set h = h.next
                endloop
                if i > 1 then
                    set winner = winners[GetRandomInt(0,i - 1)]
                else
                    set winner = winners[0]
                endif
            endif
        endmethod
       
        public method vote takes player p, string op returns nothing
            local Link h = options.head
            local integer id = GetPlayerId(p)
            local Option o = tb.integer[id]
            local integer sw = 0
            if o != 0 then
                if o.name != op then
                    set o.count = o.count - 1
                    set sw = 1
                else
                    call Message.ShowToPlayer(p,"You already vote for "+HIGHLIGHT+op+"|r"+" mode",MESSAGE_STYLE_INFO)
                    return
                endif
            endif
            loop
                exitwhen h == 0
                set o = h.data
                if o.name == op then
                    set o.count = o.count + 1
                    set tb.integer[id] = o
                    exitwhen true
                endif
                set h = h.next
            endloop
            if h == 0 then
                //no existe
            else
                if sw == 1 then
                    call Message.ShowToPlayer(p,"You has changed your vote for "+HIGHLIGHT+op+"|r"+" mode",MESSAGE_STYLE_INFO)
                else
                    call Message.ShowToPlayer(p,"You has voted for "+HIGHLIGHT+op+"|r"+" mode",MESSAGE_STYLE_INFO)
                endif
            endif
        endmethod
       
        public method addOption takes string name returns nothing
            call options.addLast(Option.create(name))
        endmethod
       
        public static method create takes string n returns thistype
            local thistype this = thistype.allocate()
            set options = LinkedList.create()
            set name = n
            set tb = Table.create()
            set winner = 0
            return this
        endmethod
       
        public method destroy takes nothing returns nothing
            local Link h = options.head
            local Option o
            set name = ""
            loop
                exitwhen h == 0
                set o = h.data
                call o.destroy()
                set h = h.next
            endloop
            call options.destroy()
            call tb.flush()
            call tb.destroy()
        endmethod
    endstruct
endlibrary
library PickHeroSystem uses HeroLibrary, AdvBook, GameConstants, NewGroup
    globals
        private constant integer    PHS_VISION_DUMMY_ID     = 'n00K'
        private constant integer    PHS_BACK_TO_BOOK_ID     = 'nul2'
        private constant integer    PHS_SELECT_HERO_ID      = 'nul1'
        private constant integer    PHS_RANDOM_HERO_ID      = 'A01I'
        private constant string     CHOOSE_USED_MSG         = "This Hero is already Picked"
       
        private constant integer    MENU_NEUTRAL_ID         = 'AHCN'
        private constant integer    MENU_HUMAN_ID           = 'AHCH'
        private constant integer    MENU_ORC_ID             = 'AHCO'
        private constant integer    MENU_NIGHTELF_ID        = 'AHCE'
        private constant integer    MENU_UNDEAD_ID          = 'AHCU'
       
        private constant string     SELECT_HERO_SFX         = "Abilities\\Spells\\Other\\Levelup\\LevelupCaster.mdl"
        private constant string     SELECT_SFX              = "Abilities\\Spells\\Other\\Aneu\\AneuCaster.mdl"
       
        private AdvBookElement      MainMenuHorde
        private AdvBookElement      MainMenuAlliance
        private AdvBookElement      MenuNeutral
        private AdvBookElement      MenuHuman
        private AdvBookElement      MenuOrc
        private AdvBookElement      MenuNightElf
        private AdvBookElement      MenuUndead
    endglobals
   
    private function DisableHeroPick takes integer id returns nothing
        local integer i = 2
        local PickHeroSystem phs
        loop
            set phs = PickHeroSystem[i]
            call BlzUnitDisableAbility(phs.circleDummy,id,true,false)
            set i = i + 1
            exitwhen i > 11
        endloop
    endfunction
   
    struct PickHeroSystem extends array
        unit        previewDummy
        unit        circleDummy
        effect      sfx
        boolean     active
        HeroData    heroData
       
        public static unit     VisionDummy1
        public static unit     VisionDummy2
        static integer PicksCount = 0
        public  static trigger RT
        public  static unit    lockcamera
       
        public static method DestroyAll takes nothing returns nothing
            local integer i = 2
            call TriggerClearConditions(RT)
            call DestroyTrigger(RT)
           
            loop
                if PickHeroSystem[i].active then
                    call RemoveUnit(PickHeroSystem[i].previewDummy)
                    set PickHeroSystem[i].previewDummy = null
                    call BookUnit[GetUnitUserData(PickHeroSystem[i].circleDummy)].destroy()
                    //set PickHeroSystem[i].circleDummy = null
                    call DestroyEffect(PickHeroSystem[i].sfx)
                    set PickHeroSystem[i].sfx = null
                    set PickHeroSystem[i].heroData = 0
                endif
                set i = i + 1
                exitwhen i > Game.PLAYER_MAX
            endloop
           
            call MainMenuHorde.destroy()
            call MainMenuAlliance.destroy()
            call ShowUnit(VisionDummy1,false)
            call ShowUnit(VisionDummy2,false)
            call ShowUnit(lockcamera,false)
            set gg_unit_ddot_0113 = null
            set RT = null
        endmethod
       
        public static method SelectHero takes player p returns boolean
            local thistype phs = PickHeroSystem[GetPlayerId(p)]
            if phs.previewDummy != null then
                if phs.heroData.IsSelected then
                    call Message.ShowToPlayer(p,CHOOSE_USED_MSG,MESSAGE_STYLE_INFO)
                else
                    set phs.heroData.IsSelected = true
                    call DisableHeroPick(phs.heroData.ChooseIconID)
                    call HeroData.RemoveRandomData(phs.heroData)
                    set PicksCount = PicksCount + 1
                    call CreateHeroForPlayer(p,phs.heroData)
                    call DestroyEffect(AddSpecialEffectTarget(SELECT_HERO_SFX,phs.previewDummy,"origin"))
                    call SetUnitAnimation(phs.previewDummy,"attack")
                    call QueueUnitAnimation(phs.previewDummy,"stand")
                    call PauseUnit(phs.previewDummy,true)
                    if Game.LocalPlayer == p then
                        call StartSound(gg_snd_HeroPick)
                        call EnablePreSelect( true, true )
                    endif
                endif
               
                if PicksCount == Players.PlayersActive then
                    call PickHeroSystem.DestroyAll()
                    if Game.GameStarted then
                        call LoadFunction.Destroy()
                    endif
                endif    
            else
                call Message.ShowToPlayer(p,"Before select a Preview Hero.",MESSAGE_STYLE_INFO)
            endif
           
            set p = null
            return false
        endmethod
       
        public static method createHeroDummyByID takes integer iconid, HeroData d, player p returns boolean
            local integer pid
            local thistype phs
            local real a
            if d == 0 then
                set d = HeroData.GetDataByChooseIconID(iconid)
            endif
            if d != 0 then
                set pid = GetPlayerId(p)
                set phs = thistype[pid]
                if GetUnitTypeId(phs.previewDummy) != d.ChooseDummy then
                    call RemoveUnit(phs.previewDummy)
                    if pid > 6 then
                        set a = 225
                    else
                        set a = 45
                    endif
                    set phs.previewDummy = CreateUnit(p,d.ChooseDummy,GetUnitX(phs.circleDummy),GetUnitY(phs.circleDummy),a)
                    call SetUnitAbilityLevel(phs.previewDummy,d.HeroAbility1,4)
                    call BlzUnitDisableAbility(phs.previewDummy,d.HeroAbility1,true,false)
                    call SetUnitAbilityLevel(phs.previewDummy,d.HeroAbility2,4)
                    call BlzUnitDisableAbility(phs.previewDummy,d.HeroAbility2,true,false)
                    call SetUnitAbilityLevel(phs.previewDummy,d.HeroAbility3,4)
                    call BlzUnitDisableAbility(phs.previewDummy,d.HeroAbility3,true,false)
                    call SetUnitAbilityLevel(phs.previewDummy,d.HeroAbility4,3)
                    call BlzUnitDisableAbility(phs.previewDummy,d.HeroAbility4,true,false)
                    call SetUnitAbilityLevel(phs.previewDummy,d.HeroAbility5,1)
                    call BlzUnitDisableAbility(phs.previewDummy,d.HeroAbility5,true,false)
                    call SetUnitAbilityLevel(phs.previewDummy,d.HeroAbility6,1)
                    call BlzUnitDisableAbility(phs.previewDummy,d.HeroAbility6,true,false)
                    call buildDescription(d.HeroUp1,0,0,p)
                    call buildDescription(d.HeroUp2,0,0,p)
                    call buildDescription(d.HeroUp3,0,0,p)
                    call SetUnitAbilityLevel(phs.previewDummy,d.HeroUp4.UpId,2)
                    call SelectUnitForPlayer(phs.previewDummy,p,true)
                    set phs.heroData = d
                    if d.IsSelected then
                        call BlzUnitDisableAbility(phs.previewDummy,PHS_SELECT_HERO_ID,true,false)
                    endif
                    return true
                else
                    call SelectUnitForPlayer(phs.previewDummy,p,true)
                endif
            endif
            return false
        endmethod
       
        public static method onInit takes nothing returns nothing
            set RT = CreateTrigger()
        endmethod
    endstruct
   
    private function OnMenuClick takes nothing returns boolean
        local integer id = AdvBookEvent.EventIconID
        local unit u = AdvBookEvent.EventUnit
        local player p = GetOwningPlayer(u)
       
        if id == PHS_RANDOM_HERO_ID then
            call PickHeroSystem.createHeroDummyByID(0,HeroData.GetRandomData(p),p)
        else
            call PickHeroSystem.createHeroDummyByID(id,0,p)    
        endif
       
        set u = null
        set p = null
        return false
    endfunction
   
    private function AddHerosToMenu takes AdvBookElement b,integer faction returns nothing
        local integer i = 1
        loop
            exitwhen i > HeroData.COUNT
            if HeroData[i].HeroFaction == faction then
                call b.addElement(AdvBookElement.create(HeroData[i].ChooseIconID,false,HeroData[i]))
            endif
            set i = i + 1
        endloop
    endfunction
   
    private function onCast takes nothing returns boolean
        local player p = GetTriggerPlayer()
        if GetUnitAbilityLevel(GetTriggerUnit(),PHS_BACK_TO_BOOK_ID) > 0 then
            if GetSpellAbilityId() == PHS_BACK_TO_BOOK_ID  then
                call SelectUnitForPlayer(PickHeroSystem[GetPlayerId(p)].circleDummy,p,true)
            elseif GetSpellAbilityId() == PHS_SELECT_HERO_ID then
                call PickHeroSystem.SelectHero(p)
            endif
        endif
        set p = null
        return false
    endfunction
   
    private function SetMenus takes nothing returns nothing
        set MainMenuHorde = AdvBookElement.create('BRI3',true,0)
        set MainMenuAlliance = AdvBookElement.create('BRI3',true,0)
        set MenuNeutral = AdvBookElement.create(MENU_NEUTRAL_ID,true,0)
        set MenuHuman = AdvBookElement.create(MENU_HUMAN_ID,true,0)
        set MenuOrc = AdvBookElement.create(MENU_ORC_ID,true,0)
        set MenuNightElf = AdvBookElement.create(MENU_NIGHTELF_ID,true,0)
        set MenuUndead = AdvBookElement.create(MENU_UNDEAD_ID,true,0)
       
        call MainMenuHorde.addElement(MenuNeutral)
        call MainMenuHorde.addElement(MenuOrc)
        call MainMenuHorde.addElement(MenuNightElf)
        call MainMenuHorde.addElement(MenuUndead)
       
        call MainMenuAlliance.addElement(MenuNeutral)
        call MainMenuAlliance.addElement(MenuHuman)
        call MainMenuAlliance.addElement(MenuNightElf)
        call MainMenuAlliance.addElement(MenuUndead)
       
        call AddHerosToMenu(MenuNeutral,Game.FACTION_NEUTRAL)
        call AddHerosToMenu(MenuHuman,Game.FACTION_HUMAN)
        call AddHerosToMenu(MenuOrc,Game.FACTION_ORC)
        call AddHerosToMenu(MenuNightElf,Game.FACTION_NIGHTELF)
        call AddHerosToMenu(MenuUndead,Game.FACTION_UNDEAD)
        call MainMenuHorde.addElement(AdvBookElement.create(PHS_RANDOM_HERO_ID,false,0))
        call MainMenuAlliance.addElement(AdvBookElement.create(PHS_RANDOM_HERO_ID,false,0))
    endfunction
   
    private function SetDummys takes nothing returns nothing
        set PickHeroSystem[2].circleDummy = gg_unit_n00H_0078
        set PickHeroSystem[3].circleDummy = gg_unit_n00H_0020
        set PickHeroSystem[4].circleDummy = gg_unit_n00H_0073
        set PickHeroSystem[5].circleDummy = gg_unit_n00H_0099
        set PickHeroSystem[6].circleDummy = gg_unit_n00H_0076
       
        set PickHeroSystem[7].circleDummy = gg_unit_n00H_0077
        set PickHeroSystem[8].circleDummy = gg_unit_n00H_0084
        set PickHeroSystem[9].circleDummy = gg_unit_n00H_0086
        set PickHeroSystem[10].circleDummy = gg_unit_n00H_0087
        set PickHeroSystem[11].circleDummy = gg_unit_n00H_0100
    endfunction
   
    public function LockCameraVision takes nothing returns nothing
        local real x = GetRectCenterX(gg_rct_PickRegion)
        local real y = GetRectCenterY(gg_rct_PickRegion)
        //call EnablePreSelect( true, false )
        set PickHeroSystem.lockcamera = gg_unit_ddot_0113
        call SetCameraPosition(x,y)
        //call SetCameraTargetController(PickHeroSystem.lockcamera, 0, 0, false)
        set PickHeroSystem.VisionDummy1 = CreateUnit(Game.PLAYER_WARCHIEF_HORDE,PHS_VISION_DUMMY_ID,x,y,0)
        set PickHeroSystem.VisionDummy2 = CreateUnit(Game.PLAYER_WARCHIEF_ALLIANCE,PHS_VISION_DUMMY_ID,x,y,0)
    endfunction
   
    public function Setup takes nothing returns nothing
        local integer i = 2
        local player tempPlayer
        local real x = GetRectCenterX(gg_rct_PickRegion)
        local real y = GetRectCenterY(gg_rct_PickRegion)
        local real xc
        local real yc
        call SetDummys()
        call SetMenus()
        loop
            set tempPlayer = Player(i)
            if GetPlayerSlotState(tempPlayer) == PLAYER_SLOT_STATE_PLAYING then
                set xc = GetUnitX(PickHeroSystem[i].circleDummy)
                set yc = GetUnitY(PickHeroSystem[i].circleDummy)
                set PickHeroSystem[i].sfx = AddSpecialEffect(SELECT_SFX,xc,yc)
                set PickHeroSystem[i].active = true
                call BlzSetSpecialEffectHeight(PickHeroSystem[i].sfx,200)
                if Game.LocalPlayer != tempPlayer then
                    call BlzSetSpecialEffectScale(PickHeroSystem[i].sfx,0)
                else
                    call EnablePreSelect( true, false )
                    call SetCameraTargetController(PickHeroSystem.lockcamera, 0, 0, false)
                endif
                call BookUnit.create(PickHeroSystem[i].circleDummy)
                if i <= 6 then
                    call BookUnit[GetUnitUserData(PickHeroSystem[i].circleDummy)].open(MainMenuHorde)
                else
                    call BookUnit[GetUnitUserData(PickHeroSystem[i].circleDummy)].open(MainMenuAlliance)
                endif
                call SelectUnitForPlayer(PickHeroSystem[i].circleDummy,tempPlayer,true)
                call UnitGenerateAlarms(PickHeroSystem[i].circleDummy,false)
            else
                call SetUnitColor(PickHeroSystem[i].circleDummy,PLAYER_COLOR_LIGHT_GRAY)
                set PickHeroSystem[i].previewDummy = null
            endif
            set i = i + 1
            exitwhen i > Game.PLAYER_MAX
        endloop
       
        call RegisterAdvBookClickEvent(function OnMenuClick,EVENT_ADVBOOK_CLICK)
        call TriggerRegisterAnyUnitEventBJ(PickHeroSystem.RT,EVENT_PLAYER_UNIT_SPELL_EFFECT)
        call TriggerAddCondition(PickHeroSystem.RT,Condition(function onCast))
        set tempPlayer = null
    endfunction
endlibrary
 
library PreloadGen uses TimerUtils
    globals
        constant integer PRELOAD_FIRST  = 1
        constant integer PRELOAD_SECOND = 2
        constant integer PRELOAD_UNIT   = 3
        private  unit    PreloadDummy  
    endglobals
   
    private function UnitPreload takes integer id returns nothing
        call RemoveUnit(CreateUnit(Game.PLAYER_NEUTRAL_EXTRA,id,0,0,0))
    endfunction
   
    private function AbilityPreload takes integer id returns nothing
        if UnitAddAbility(PreloadDummy, id) then
            call UnitRemoveAbility(PreloadDummy,id)
        endif
    endfunction
   
    private function CreatePreloader takes nothing returns nothing
        set PreloadDummy = CreateUnit(Game.PLAYER_NEUTRAL_EXTRA,'u001', Game.HIDE_X, Game.HIDE_Y, 0.)
        call UnitApplyTimedLife(PreloadDummy,'BTLF',Game.TIME_PRELOADING)
    endfunction
   
    struct PreloadGen extends array
        private static integer array    A
        private static integer array    B
        private static integer array    C
        private static integer          countF = 0
        private static integer          countS = 0
        private static integer          countU = 0
       
        private static method CallbackF takes nothing returns nothing
            if countF > 0 then
                set countF = countF - 1
                call AbilityPreload(A[countF])
            else
                call ReleaseTimer(GetExpiredTimer())
            endif
        endmethod
       
        private static method CallbackS takes nothing returns nothing
            if countS > 0 then
                set countS = countS - 1
                call AbilityPreload(B[countS])
            else
                call ReleaseTimer(GetExpiredTimer())
            endif
        endmethod
       
        private static method CallbackU takes nothing returns nothing
            if countU > 0 then
                set countU = countU - 1
                call UnitPreload(C[countU])
            else
                call ReleaseTimer(GetExpiredTimer())
            endif
        endmethod
       
        public static method Start takes nothing returns nothing
            call CreatePreloader()
            call TimerStart(NewTimer(),0.05,true,function thistype.CallbackF)
            call TimerStart(NewTimer(),0.05,true,function thistype.CallbackS)
            call TimerStart(NewTimer(),0.05,true,function thistype.CallbackU)
        endmethod
       
        public static method Add takes integer id, integer t returns nothing
            if t == PRELOAD_FIRST then
                set A[countF] = id
                set countF = countF + 1
            elseif t == PRELOAD_SECOND then
                set B[countS] = id
                set countS = countS + 1
            elseif t == PRELOAD_UNIT then
                set C[countU] = id
                set countU = countU + 1
            endif
        endmethod
    endstruct
endlibrary
library AdvBook initializer init uses LinkedList, Event, NewGroup
    globals
        private constant integer     CANCEL_BUTTON   = 'AHCC'  
        private constant integer     NEXT_BUTTON     = 'AHCP'  
        private constant integer     PAGE_MAX_ELEM   = 11  
       
        Event EVENT_ADVBOOK_CLICK
    endglobals
   
    struct AdvBookEvent extends array
        static unit     EventUnit
        static integer  EventIconID
        static integer  EventElement
       
        private static method onInit takes nothing returns nothing
            set EVENT_ADVBOOK_CLICK = Event.create()
        endmethod
    endstruct
   
    struct AdvBookElement
        LinkedList  list
        boolean     isBook
        integer     iconID
        integer     data
        boolean     destroyed
       
        private static integer  count = 0
       
        public static method GetElementByID takes integer id returns thistype
            local integer i = 0
            loop
                set  i = i + 1
                if thistype(i).iconID == id then
                    return thistype(i)
                endif
                exitwhen i == count
            endloop
           
            return 0
        endmethod
       
        public method addElement takes AdvBookElement e returns nothing
            call list.add(e)
        endmethod
       
        public method isEmpty takes nothing returns boolean
            return list.size == 0
        endmethod
       
        public static method create takes integer id ,boolean b, integer d returns thistype
            local thistype this = thistype.allocate()
            set iconID = id
            set list = LinkedList.create()
            set isBook = b
            set data = d
            set destroyed = false
            set count = count + 1
            return this
        endmethod
       
        public method destroy takes nothing returns nothing
            local Link temp = list.head
            local thistype b
           
            loop
                exitwhen temp == 0
                set b = temp.data
                if not b.destroyed then
                    call b.destroy()
                endif
                set temp = temp.next
            endloop
           
            call list.destroy()
            set count = count - 1
            set list = 0
            set isBook = false
            set iconID = 0
            set destroyed = true
            call this.deallocate()
        endmethod
    endstruct
   
   
    struct BookUnit extends array
        AdvBookElement      currentBook
        LinkedList          prevBooks
        Link                lastElement
        integer             count
       
        static group        RegisterGroup
        static trigger      OnClickTrigger
       
        private static method IsValid takes unit u returns boolean
            return GetUnitAbilityLevel(u,'aatk') == 0 and GetUnitAbilityLevel(u,'amov') == 0 and GetWidgetLife(u) > 0.405 and IsUnitInGroup(u,RegisterGroup)
        endmethod
       
        private static method OnClick takes nothing returns boolean
            local unit u = GetTriggerUnit()
            local integer sid = GetSpellAbilityId()
            local integer id = GetUnitUserData(u)
            local AdvBookElement b
            if IsUnitInGroup(u,RegisterGroup) then
                if sid == CANCEL_BUTTON then
                    call BookUnit[id].cancel()
                elseif sid == NEXT_BUTTON then
                        call BookUnit[id].next()
                    else
                        set b = AdvBookElement.GetElementByID(sid)
                        if b != 0 then
                            if b.isBook then
                                call BookUnit[id].open(b)
                            endif
                            set AdvBookEvent.EventUnit = u
                            set AdvBookEvent.EventIconID = sid
                            set AdvBookEvent.EventElement = b
                            call EVENT_ADVBOOK_CLICK.fire()
                            set AdvBookEvent.EventUnit = null
                        endif
                endif
            endif
           
            set u = null
            return false
        endmethod
       
        public method next takes nothing returns nothing
            call close(false)
            call open(currentBook)
        endmethod
       
        public method cancel takes nothing returns nothing
            call close(true)
        endmethod
       
         public method open takes AdvBookElement book returns boolean  
            local Link temp
            local AdvBookElement b
            local integer limit
            local HeroData hd
           
            if IsValid(Index[this].u) and book.list.size != 0 then
                if currentBook != book then
                    if currentBook == 0 then
                        set currentBook = book
                    else
                        call close(false)
                        call prevBooks.addLast(currentBook)
                        set currentBook = book
                        set lastElement = 0
                    endif
                endif
               
                if lastElement != 0 then
                    set temp = lastElement.next
                    if temp.next == 0 then
                        set temp = currentBook.list.head
                    endif
                else
                    set temp = currentBook.list.head
                endif
           
                if currentBook.list.size > PAGE_MAX_ELEM then
                    set limit = PAGE_MAX_ELEM - 1
                    call UnitAddAbility(Index[this].u,NEXT_BUTTON)
                else
                    set limit = PAGE_MAX_ELEM
                endif
               
                if prevBooks.size != 0 then
                    call UnitAddAbility(Index[this].u,CANCEL_BUTTON)
                endif
           
                call UnitRemoveAbility(Index[this].u,currentBook.iconID)
                set count = 0
               
                loop
                    exitwhen temp == 0 or count == limit
                    set b = temp.data
                    set hd = b.data
                    call UnitAddAbility(Index[this].u,b.iconID)
                    if hd.IsSelected and hd != 0 then
                        call BlzUnitDisableAbility(Index[this].u,b.iconID,true,false)
                    endif
                    set count = count + 1
                    set lastElement = temp
                    set temp = temp.next
                endloop
                return true
            endif
           
            return false
        endmethod
       
        public method close takes boolean openPrev returns boolean
            local Link temp
            local AdvBookElement b
           
            if count != 0 and currentBook != 0 then
                set temp = lastElement
            else
                return false
            endif
           
            call UnitRemoveAbility(Index[this].u,CANCEL_BUTTON)
            call UnitRemoveAbility(Index[this].u,NEXT_BUTTON)
           
            loop
                exitwhen count == 0
                set b = temp.data
                call UnitRemoveAbility(Index[this].u,b.iconID)
                set count = count - 1
                set temp = temp.prev
            endloop
           
            if openPrev then
                if prevBooks.size > 0 then
                    set b = prevBooks.last.data
                    call prevBooks.remove(prevBooks.last)
                    set currentBook = b
                    set lastElement = 0
                    call open(b)
                else
                    call UnitAddAbility(Index[this].u,currentBook.iconID)
                endif
            endif
           
            return true
        endmethod
       
        public static method create takes unit u returns thistype
            local thistype this = GetUnitUserData(u)
            set prevBooks = LinkedList.create()
            set currentBook = 0
            set lastElement = 0
            call GroupAddUnit(RegisterGroup,u)
            set count = 0
            return this
        endmethod
       
        public method destroy takes nothing returns nothing
            call close(false)
            call GroupRemoveUnit(RegisterGroup,Index[this].u)
            if FirstOfGroup(RegisterGroup) == null then
                call ReleaseGroup(RegisterGroup)
                set RegisterGroup = null
                call DestroyTrigger(OnClickTrigger)
                set OnClickTrigger = null
            endif
            call prevBooks.destroy()
        endmethod
       
        public static method onInit takes nothing returns nothing
            set OnClickTrigger = CreateTrigger()
            set RegisterGroup = NewGroup()
            call TriggerRegisterAnyUnitEventBJ(OnClickTrigger,EVENT_PLAYER_UNIT_SPELL_EFFECT)
            call TriggerAddCondition(OnClickTrigger,Condition(function thistype.OnClick))
        endmethod
    endstruct
   
    function RegisterAdvBookClickEvent takes code c, Event e returns nothing
        call e.register(Filter(c))
    endfunction
   
    private function init takes nothing returns nothing
        call PreloadGen.Add(CANCEL_BUTTON,PRELOAD_SECOND)
        call PreloadGen.Add(NEXT_BUTTON,PRELOAD_SECOND)
    endfunction
endlibrary

 
library IndexEvent uses MiscLibrary, GuardPath
    private function onIndex takes nothing returns nothing
        local Index index = INDEX_EVENT
        call MakeFly(index.u)
        call SetUnitGuardPath(index.u,0)
        set InCombat_CombatTime[index] = 0
        //call BJDebugMsg("indexado "+I2S(index)+"-"+GetUnitName(index.u))
        if UnitAlive(index.u) and not IsUnitIllusion(index.u) and (IsUnitType(index.u,UNIT_TYPE_HERO) or GetUnitAbilityLevel(index.u,Game.FLAG_HERO_CREEP) != 0) then
            call HeroRegenPeriod.AddUnit(index)
        endif
        if GetUnitAbilityLevel(index.u,'AInv') != 0 then
            call SetUnitData(index.u,"UnitItems",LinkedList.create())
        endif
        if not IsUnitType(index.u,UNIT_TYPE_STRUCTURE) then
            set UB[index] = LinkedList.create()
        endif
    endfunction
   
    private function onDeIndex takes nothing returns nothing
        local Index index = INDEX_EVENT
        //call BJDebugMsg("deindexado "+I2S(index)+"-"+GetUnitName(index.u))
        call UnitRemoveAllBuffs(index.u)
        call UB[index].destroy()
        call flushUnitData(index.u)
        call BonusStruct.ResetAll(index.u,index)
    endfunction
   
    public function Setup takes nothing returns nothing
        call RegisterOnIndexEvent(function onIndex)
        call RegisterOnDeIndexEvent(function onDeIndex)
    endfunction
endlibrary

 
library UnitIndex uses UnitData
    globals
        boolean ENABLE_INDEXER = true
        Index    INDEX_EVENT
        Event    ON_INDEX
        Event    ON_DEINDEX
    endglobals
   
    function RegisterOnIndexEvent takes code c returns nothing
        call ON_INDEX.register(Filter(c))
    endfunction
   
    function RegisterOnDeIndexEvent takes code c returns nothing
        call ON_DEINDEX.register(Filter(c))
    endfunction
   
    struct Index extends array
        implement Alloc
        unit u
        boolean lock
        integer listIndex
       
        static LinkedList All
        public static method create takes unit x returns thistype
            local thistype this = thistype.allocate()
            set u = x
            set lock = false
            call SetUnitUserData(u,this)
            set listIndex = All.add(this)
            set INDEX_EVENT = this
            call ON_INDEX.fire()
            return this
        endmethod
       
        public method destroy takes nothing returns nothing
            set INDEX_EVENT = this
            call ON_DEINDEX.fire()
            call All.remove(listIndex)
            set listIndex = 0
            call SetUnitUserData(u,0)
            set u = null
            call this.deallocate()
        endmethod
    endstruct
   
    function GetUnitIndexObj takes unit u returns Index
        return Index[GetUnitUserData(u)]
    endfunction
   
    function GetUnitByIndex takes integer index returns unit
        if index <= 0 then
            return null
        endif
        return Index[index].u
    endfunction
   
    function LockIndex takes integer index, boolean flag returns nothing
        set Index[index].lock = flag
    endfunction
   
    private function IsValidToIndex takes unit u returns boolean
        return not IsUnitType(u,UNIT_TYPE_UNDEAD) and GetUnitUserData(u) == 0 and ENABLE_INDEXER
    endfunction
   
    private function OnEnterMap takes nothing returns nothing
        local unit u = GetEnteringUnit()
        if IsValidToIndex(u) then
            call Index.create(u)
        endif
        set u = null
    endfunction
   
    private function FilterIni takes nothing returns boolean
        local unit u = GetFilterUnit()
        if IsValidToIndex(u) then
            call Index.create(u)
        endif
        set u = null
        return false
    endfunction
   
    private function onDeath takes nothing returns nothing
        local unit u = GetTriggerUnit()
        local Index i
        if (IsUnitType(u,UNIT_TYPE_SUMMONED) or IsUnitIllusion(u)) and GetUnitAbilityLevel(u,'A07B') == 1 then
            set i = GetUnitIndexObj(u)
            if i != 0 and not i.lock then
                call i.destroy()
            endif
        endif
        if IsUnitType(u,UNIT_TYPE_UNDEAD) then
            call flushDummyData(u)
        endif
        set u = null
    endfunction
   
    public function Setup takes nothing returns nothing
        local integer i = 27
        local boolexpr b = Filter(function FilterIni)
        local region re = CreateRegion()
        local rect r = GetWorldBounds()
        local trigger t = CreateTrigger()
        set Index.All = LinkedList.create()
        call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_DEATH,function onDeath)
        call RegionAddRect(re, r)
        call TriggerRegisterEnterRegion(t, re, b)
        call TriggerAddAction(t, function OnEnterMap)
        set bj_lastCreatedGroup = CreateGroup()
        loop
            set i = i - 1
            call GroupEnumUnitsOfPlayer(bj_lastCreatedGroup, Player(i), b)
            call GroupClear(bj_lastCreatedGroup)
            exitwhen i == 0
        endloop
        call RemoveRect(r)
        call DestroyGroup(bj_lastCreatedGroup)
        set re = null
        set r = null
        set t = null
        set b = null
    endfunction
endlibrary
 
library AoEMeter uses MiscLibrary
    globals
        private constant string SFX = "war3mapImported\\RangeCircleZ.mdl"
    endglobals
   
    struct AoEPeriodic extends array
        static timer T = CreateTimer()
        public static method Periodic takes nothing returns nothing
            local AoE a
            local Link h = AoE.list.head
            local Link n
            local real x
            local real y
            loop
                exitwhen h == 0
                set a = h.data
                set n = h.next
                if a.attach != null then
                    set x = GetUnitX(a.attach)
                    set y = GetUnitY(a.attach)
                    call BlzSetSpecialEffectX(a.sfx,x)
                    call BlzSetSpecialEffectY(a.sfx,y)
                    call BlzSetSpecialEffectHeight(a.sfx,GetLocZ(x,y))
                endif
                if a.expire then
                    set a.time = a.time - 0.03125
                    if a.time <= 0 then
                        call a.destroy()
                    endif
                endif
                set h = n
            endloop
            if AoE.list.size == 0 then
                call PauseTimer(T)
            endif
        endmethod
        public static method Start takes nothing returns nothing
            call TimerStart(T,0.03125,true,function thistype.Periodic)
        endmethod
    endstruct
   
    struct AoE extends array
        implement Alloc
        unit attach
        real x
        real y
        real size
        effect sfx
        real time
        boolean expire
        integer index
       
        static LinkedList list
       
        public method setTime takes real t returns nothing
            if t == 0 then
                set expire = false
                set time = 0
            else
                set expire = true
                set time = t
            endif
        endmethod
       
        public static method create takes real xc, real yc, unit u, real s returns thistype
            local thistype this = thistype.allocate()
            set attach = u
            set x = xc
            set y = yc
            set size = s / 2
            if s != 0 then
                if u != null then
                    set sfx = AddSpecialEffect(SFX,GetUnitX(u),GetUnitY(u))
                else
                    set sfx = AddSpecialEffect(SFX,x,y)
                endif
                call BlzSetSpecialEffectScale(sfx,size/32*1.03)
            endif
            if not Players[GetPlayerId(Game.LocalPlayer)].aoeShow then
                call BlzSetSpecialEffectAlpha(sfx,0)
            endif
            set index = list.add(this)
            if list.size == 1 then
                call AoEPeriodic.Start()
            endif
            return this
        endmethod
       
        public method destroy takes nothing returns nothing
            call list.remove(index)
            set index = 0
            set attach = null
            call DestroyEffect(sfx)
            set sfx = null
            set time = 0
            set expire = false
            call this.deallocate()
        endmethod
       
        public static method onInit takes nothing returns nothing
            set list = LinkedList.create()
        endmethod
    endstruct
endlibrary
 
scope AbilityDescription
    globals
        private constant string HIGHLIGHT = "|c0087cefa"
    endglobals
   
    struct AbilityTag extends array
        implement Alloc
        string name
        Table values
        real  add
        integer stype
        boolean single
       
        public method setValue takes integer lvl, string v returns nothing
            set values.string[lvl] = v
        endmethod
       
        public static method create takes string n, integer st returns thistype
            local thistype this = thistype.allocate()
            set name = n
            set values = Table.create()
            set stype = st
            set single = false
            return this
        endmethod
    endstruct
   
    struct DescriptionData extends array
        implement Alloc
        string description
        LinkedList tags
       
        public method addTag takes string name, integer st returns AbilityTag
            local AbilityTag t = AbilityTag.create(name,st)
            call tags.addLast(t)
            return t
        endmethod
       
        public static method create takes string d returns thistype
            local thistype this = thistype.allocate()
            set tags = LinkedList.create()
            set description = d
            return this
        endmethod
    endstruct
   
    struct AbilityDesc extends array
        implement Alloc
        delegate DescriptionData data
        Ability abi
       
        public method build takes nothing returns nothing
            local string d = description + "|n"
            local Link h = tags.head
            local AbilityTag = t
            loop
                exitwhen h == 0
                set t = h.data
                if t.single then
                    set d = d + "|n" + HIGHLIGHT + t.name + ":|r " + t.values.string[1]
                else
                    set d = d + "|n" + HIGHLIGHT + t.name + ":|r " + t.values.string[abi.level]
                endif
                set h = h.next
            endloop
            call BlzSetAbilityExtendedTooltip(abi.objectID,d,abi.level - 1)
        endmethod
       
        public static method create takes Ability a, DescriptionData d returns thistype
            local thistype this = thistype.allocate()
            set abi = a
            set data = d
            return this
        endmethod
    endstruct
endscope
library AbilityLibrary uses RegisterPlayerUnitEvent, MiscLibrary, LinkedList
    globals
        Event EVENT_UNIT_SPELL_CD_END
        private Ability TriggerAbility
        constant integer ACTIVATION_TYPE_TARGET     = 0
        constant integer ACTIVATION_TYPE_INSTANT    = 1
        constant integer ACTIVATION_TYPE_POINT      = 2
        constant integer ACTIVATION_TYPE_NONE       = 3
       
        private constant string STR_ABILITY_NAME_COLOR = "|cffc0c0c0"
        private constant string STR_ABILITY_SPECIAL_COLOR = "|cffffcc00"
    endglobals
   
    function GetEventAbilityCD takes nothing returns Ability
        return TriggerAbility
    endfunction
   
    struct AbilityData extends array
        integer     objectID
        boolean     UseAuxDummy
        boolean     AuxDummyAttacker
        boolean     isCharged
        string      hotkey
        integer     activationType
        DescriptionData desc
        static integer ABILITY_COUNT = 0
       
        public static method GetDataByID takes integer id returns AbilityData
            local integer i = 1
            loop
                exitwhen i > ABILITY_COUNT
                if thistype[i].objectID == id then
                    return thistype[i]
                endif
                set i = i + 1
            endloop
            return 0
        endmethod
       
        public static method create takes nothing returns thistype
            set ABILITY_COUNT  = ABILITY_COUNT + 1
            return thistype(ABILITY_COUNT)
        endmethod
    endstruct
   
    struct Ability extends array
        implement Alloc
        delegate AbilityData data
        integer     maxCharges
        unit        owner
        integer     level
        real        cdTime
        integer     currentCharges
        real        originalCooldown
        real        finalCooldown
        real        cooldown
        real        flatCooldown
        real        percentCooldown
        real        tempFlatCooldown
        real        tempPercentCooldown
        unit        auxDummy
        integer     cdCountIndex
        boolean     nextReset
        AbilityDesc  adesc
        Upgrade      upID
        static HashTable HT
        static timer TIMER
        static LinkedList ONCD
       
        private static method periodic takes nothing returns nothing
            local Link node = ONCD.head
            local Link temp
            local thistype a
            local integer sw
            loop
                exitwhen node == 0
                set sw = 0
                set a = node.data
                set a.cdTime = a.cdTime - 0.03125
                if a.cdTime <= 0 then
                    if a.isCharged then
                        if a.currentCharges < a.maxCharges then
                            set a.currentCharges = a.currentCharges + 1
                            call BlzEndUnitAbilityCooldown(a.owner,a.objectID)
                            if a.currentCharges < a.maxCharges then
                                set a.cdTime = BlzGetUnitAbilityCooldown(a.owner,a.objectID,a.level-1)
                            endif
                        else
                            set sw = 1
                        endif
                    else
                        set sw = 1
                    endif
                endif
               
                if sw == 1 then
                    call a.updateTooltip(true)
                    set TriggerAbility = a
                    call EVENT_UNIT_SPELL_CD_END.fire()
                    set temp = node.next
                    call ONCD.remove(node)
                    set a.cdCountIndex = 0
                    set node = temp
                else
                    set node = node.next
                endif
            endloop
           
            if ONCD.size == 0 then
                call PauseTimer(TIMER)
            endif
        endmethod
       
        public method updateTooltip takes boolean calc returns nothing
            local real c
            local string s = ""
            local string up = ""
            if GetUnitAbilityLevel(owner,objectID) == 0 then
                return
            endif
            if hotkey != "Passive" then
                if calc then
                    call calculateCooldown()
                    if isCharged then
                        call BlzSetUnitAbilityCooldown(owner,objectID,level-1,0)
                    else
                        if objectID == 'A0BV' or objectID == 'A0BW' or objectID == 'A0BU' then
                            call BlzSetUnitAbilityCooldown(owner,objectID,0,finalCooldown)
                        else
                            call BlzSetUnitAbilityCooldown(owner,objectID,level-1,finalCooldown)
                        endif
                       
                    endif
                endif
                set c = finalCooldown
                if c < 0 then
                    set c = 0.00
                endif
                set s = STR_ABILITY_NAME_COLOR+GetObjectName(objectID)+"|r"+STR_ABILITY_SPECIAL_COLOR+" [|r"+"Lvl "+I2S(level)+STR_ABILITY_SPECIAL_COLOR+"] CD: |r"+R2SW(c,0,2)
                call BlzSetAbilityTooltip(objectID,s,level-1)
                //call BlzSetAbilityActivatedExtendedTooltip(objectID,up,level-1)
            else
                set level = GetUnitAbilityLevel(owner,objectID)
                set s = STR_ABILITY_NAME_COLOR+GetObjectName(objectID)+"|r"+STR_ABILITY_SPECIAL_COLOR+" [|r"+"Lvl "+I2S(level)+STR_ABILITY_SPECIAL_COLOR+"]"+"("+hotkey+")|r"
                call BlzSetAbilityTooltip(objectID,s,level-1)
                //call BlzSetAbilityActivatedExtendedTooltip(objectID,up,level-1)
            endif
            if adesc != 0 then
                //call adesc.build()
            endif
        endmethod
       
        public method isOnCooldown takes nothing returns boolean
            if isCharged then
               return currentCharges == 0
            endif
            return cdCountIndex != 0
        endmethod
       
        public static method AddCooldownTimer takes thistype a, real r returns nothing
            if a.cdCountIndex == 0 then
                set a.cdCountIndex = ONCD.add(a)
                set a.cdTime = r
            endif
            if ONCD.size == 1 then
                call TimerStart(TIMER,0.03125,true,function thistype.periodic)
            endif
        endmethod
       
        public method calculateCooldown takes nothing returns nothing
            local integer lvl = GetUnitAbilityLevel(owner,objectID)
            local real flat
            local real percent
            local real unitReduction = BonusStruct.GetTotalBonusSpecial(BONUS_TYPE_CD_REDUCTION,owner)
            if lvl != level then
                set originalCooldown = BlzGetUnitAbilityCooldown(owner,objectID,lvl-1)
                set level = lvl
            endif
            if isCharged then
                set finalCooldown = originalCooldown
            else
                set flat = flatCooldown + tempFlatCooldown
                set percent = originalCooldown * (percentCooldown + tempPercentCooldown + unitReduction)
                set cooldown = flat + percent
                set finalCooldown = originalCooldown + cooldown
            endif
        endmethod
       
        public method addTempFlatCooldown takes real cd returns nothing
            set tempFlatCooldown = tempFlatCooldown + cd
            call updateTooltip(true)
        endmethod
       
        public method addTempPercentCooldown takes real cd returns nothing
            set tempPercentCooldown = tempPercentCooldown + cd
            call updateTooltip(true)
        endmethod
       
        public method addFlatCooldown takes real cd returns nothing
            set flatCooldown = flatCooldown + cd
            call updateTooltip(true)
        endmethod
       
        public method addPercentCooldown takes real pcd returns nothing
            set percentCooldown = percentCooldown + pcd
            call updateTooltip(true)
        endmethod
       
        public method addCharges takes integer c returns nothing
            set currentCharges = currentCharges + c
            if currentCharges > maxCharges then
                set currentCharges = maxCharges
            endif
            call BlzEndUnitAbilityCooldown(owner,objectID)
        endmethod
       
        public method addMaxCharges takes integer mc returns nothing
            set maxCharges = maxCharges + mc
            call addCharges(mc)
        endmethod
       
        public method resetCooldown takes nothing returns nothing
            if not isCharged then
                if cdCountIndex != 0 then
                    set cdTime = 0
                    call ONCD.remove(cdCountIndex)
                    set cdCountIndex = 0
                    if ONCD.size == 0 then
                        call PauseTimer(TIMER)
                    endif
                    call BlzEndUnitAbilityCooldown(owner,objectID)
                    //call UnitResetAbilityCooldown(owner,objectID)
                endif
            endif
        endmethod
       
        public static method create takes AbilityData d, unit u returns thistype
            local thistype this = thistype.allocate()
            local integer i = 0
            set data = d
            set owner = u
            set flatCooldown = 0
            set percentCooldown = 0
            set maxCharges = 0
            set currentCharges = 0
            set cooldown = 0
            set tempFlatCooldown = 0
            set tempPercentCooldown = 0
            set cdCountIndex = 0
            set level = 0
            if d.UseAuxDummy then
                if AuxDummyAttacker then
                    set auxDummy = CreateUnit(GetOwningPlayer(u),'u000',GetUnitX(u),GetUnitY(u),0)
                else
                    set auxDummy = CreateUnit(GetOwningPlayer(u),'u001',GetUnitX(u),GetUnitY(u),0)
                endif
            endif
            set adesc = 0
            set HT[GetUnitUserData(u)][d.objectID] = this
            return this
        endmethod
       
        public static method GetUnitAbilityByID takes integer id, unit u returns thistype
            return HT[GetUnitUserData(u)][id]
        endmethod
    endstruct
   
    function CooldownProcess takes unit u, integer id returns nothing
        local Ability a = Ability.GetUnitAbilityByID(id,u)
        if a != 0 then
            if a.isCharged then
                set a.currentCharges = a.currentCharges - 1
                //call BJDebugMsg(I2S(a.currentCharges))
                call Ability.AddCooldownTimer(a,a.finalCooldown)
                if a.currentCharges == 0 then
                    if a.cdCountIndex != 0 then
                        call BlzSetUnitAbilityCooldown(a.owner,a.objectID,a.level-1,a.cdTime)
                    else
                        call BlzSetUnitAbilityCooldown(a.owner,a.objectID,a.level-1,a.finalCooldown)
                    endif
                endif
            else
                if not a.nextReset then
                    call a.calculateCooldown()
                    set a.tempPercentCooldown = 0
                    set a.tempFlatCooldown = 0
                    call BlzSetUnitAbilityCooldown(a.owner,a.objectID,a.level-1,a.finalCooldown)
                    call Ability.AddCooldownTimer(a,a.finalCooldown)
                    call a.updateTooltip(false)
                else
                    set a.nextReset = false
                    //call UnitResetAbilityCooldown(u,id)
                    call BlzEndUnitAbilityCooldown(u,id)
                endif
            endif
        endif
    endfunction
   
    public function Setup takes nothing returns nothing
        set Ability.HT = HashTable.create()
        set Ability.TIMER = CreateTimer()
        set Ability.ONCD = LinkedList.create()
        set EVENT_UNIT_SPELL_CD_END = Event.create()
    endfunction
endlibrary  
 
library HeroLibrary initializer init uses UnitStats, TeamLib, GameConstants, UpgradeSkill, AbilityLibrary, HeroRevive, LinkedList, UnitData
   
    globals
        private trigger ON_LEVEL_TRIGGER
        boolean INIT_AI
        Hero    HERO_AI
    endglobals
   
    function CreateHeroForPlayer takes player p,HeroData d returns nothing
        local integer pid = GetPlayerId(p)
        local unit u = CreateUnit(p,d.TypeID,GetPlayerStartLocationX(p),GetPlayerStartLocationY(p),0)
        local integer id = GetUnitUserData(u)
        local string n = ""
        call UnitAddAbility(u,'A02Y')
        call UnitMakeAbilityPermanent(u,true,'A02Y')
        set Index[id].lock = true
        set Players[pid].hero = Hero.create(u,d)
        call SelectUnitForPlayer(u,p,true)
        call RegisterHeroRespawn(u)
        if Team[1].isPlayerInTeam(p) then
            call SetCameraPositionForPlayer(p,Team[1].startX,Team[1].startY)
            call Message.ShowToForce(Team[2].forceP,GetPlayerName(p) + " has choosen "+GetUnitName(u),MESSAGE_STYLE_INFO)
        elseif Team[2].isPlayerInTeam(p) then
            call SetCameraPositionForPlayer(p,Team[2].startX,Team[2].startY)
            call Message.ShowToForce(Team[1].forceP,GetPlayerName(p) + " has choosen "+GetUnitName(u),MESSAGE_STYLE_INFO)
        endif
        if p != Game.PLAYER_WARCHIEF_HORDE and p != Game.PLAYER_WARCHIEF_ALLIANCE then
            if GetPlayerController(p) == MAP_CONTROL_COMPUTER then
                set n = Players[pid].ai+I2S(pid-1)+" ("+d.Name+")"
                call SetPlayerName(p,n)
                set Players[pid].name = n
                call MultiboardUpdatePlayerName(p,n)
                call AddPlayerGold(p,-(Players[pid].hero.heroAI.itemBuild.purchaseExtras(Game.PLAYER_INITIAL_GOLD)))
            else
                set n = GetPlayerName(p)+" ("+d.Name+")"
                call SetPlayerName(p,n)
            endif
        endif
        set u = null
    endfunction
   
    function GetHeroPrimaryAttribute takes unit u, boolean all returns integer
        local Hero h = GetUnitData(u,"HeroIndex")
        if h != 0 then
            if h.PrimaryAttribute == 1 then
                return GetHeroAgi(h.hero,all)
            elseif h.PrimaryAttribute == 2 then
                return GetHeroInt(h.hero,all)
            elseif h.PrimaryAttribute == 3 then
                return GetHeroStr(h.hero,all)
            endif
        endif
        return 0
    endfunction
   
    struct HeroData extends array
        static integer COUNT = 0
       
        integer     TypeID
        string      IconID
        string      WinAni
        string      Name
        real        Evasion
        real        Block
        real        Resistance
        real        LifeRegen
        real        ManaRegen
        integer     Armor
        integer     AttackRange
        integer     HpLvl
        integer     MpLvl
        integer     PrimaryAttribute
        UpgradeData  HeroUp1
        UpgradeData  HeroUp2
        UpgradeData  HeroUp3
        UpgradeData  HeroUp4
        integer     HeroAbility1
        integer     HeroAbility2
        integer     HeroAbility3
        integer     HeroAbility4
        integer     HeroAbility5
        integer     HeroAbility6
        integer     ChooseIconID
        integer     ChooseDummy
        integer     HeroFaction
        integer     InfoID
       
       
        boolean     IsSelected
        Link        randomIDH
        Link        randomIDA
       
        static LinkedList RandomListHorde
        static LinkedList RandomListAlliance
       
        public static method GetDataByChooseIconID takes integer id returns thistype
            local integer i = 0
            loop
                set i = i + 1
                if thistype[i].ChooseIconID == id then
                    return thistype[i]
                endif
                exitwhen i == COUNT
            endloop
           
            return 0
        endmethod
       
        public static method RemoveRandomData takes thistype d returns nothing
            if d.HeroFaction == Game.FACTION_ORC then
                call RandomListHorde.remove(d.randomIDH)
            elseif d.HeroFaction == Game.FACTION_HUMAN then
                call RandomListAlliance.remove(d.randomIDA)
            else
                call RandomListHorde.remove(d.randomIDH)
                call RandomListAlliance.remove(d.randomIDA)
            endif
        endmethod
       
        public static method GetRandomData takes player p returns thistype
            local Team t = GetPlayerTeamEx(p)
            local thistype d
            local integer r = 0
            if t == 1 then
                set r = GetRandomInt(1,RandomListHorde.size)
                set d = RandomListHorde.getByIndex(r).data
            else
                set r = GetRandomInt(1,RandomListAlliance.size)
                set d = RandomListAlliance.getByIndex(r).data
            endif
            return d
        endmethod
       
        public static method AddRandomData takes thistype d returns nothing
            if d.HeroFaction == Game.FACTION_ORC then
                set d.randomIDH = RandomListHorde.add(d)
            elseif d.HeroFaction == Game.FACTION_HUMAN then
                set d.randomIDA = RandomListAlliance.add(d)
            else
                set d.randomIDH = RandomListHorde.add(d)
                set d.randomIDA = RandomListAlliance.add(d)
            endif
        endmethod
       
        public static method create takes nothing returns thistype
            set COUNT = COUNT + 1
            return COUNT
        endmethod
    endstruct
   
    struct Hero extends array
        implement Alloc
        delegate HeroData   data
        unit        hero
        integer     masteryType  
        integer     supUp
        Upgrade     up1
        Upgrade     up2
        Upgrade     up3
        Upgrade     up4
        boolean    supUpgrade
        integer    upgradePoints
        integer    upgradeLvl
        HeroAtt     heroAtt
        Perks       perks
        Table       Abilities
        AICore      heroAI
       
        public method updateAbilityTooltip takes integer i returns nothing
            local Ability a = Abilities.integer[i]
            if a != 0 then
                call a.updateTooltip(true)
            endif
        endmethod
       
        public method updateTooltips takes nothing returns nothing
            local integer i = 1
            local Ability a
            loop
                set a = Abilities.integer[i]
                if a != 0 then
                    call a.updateTooltip(true)
                endif
                set i = i + 1
                exitwhen a == 0
            endloop
        endmethod
       
        public method GetUpgradeByID takes integer id returns Upgrade
            if up1.UpId == id then
                return up1
            endif
            if up2.UpId == id then
                return up2
            endif
            if up3.UpId == id then
                return up3
            endif
            if up4.UpId == id then
                return up4
            endif
           
            return 0
        endmethod
       
        public method GetAbiltyByID takes integer id returns Ability
            local integer i = 1
            local Ability a
            loop
                set a = Abilities.integer[i]
                if a != 0 then
                    if a.objectID == id then
                        return a
                    endif
                else
                    exitwhen true
                endif
                set i = i + 1
            endloop
           
            return 0
        endmethod
       
        public method GetUpgradeLevel takes integer upkey returns integer
            if upkey == 1 then
                return up1.level
            elseif upkey == 2 then
                return up2.level
            elseif upkey == 3 then
                return up3.level
            elseif upkey == 4 then
                return up4.level
            endif
            return 0
        endmethod
       
        public method HeroAddAbility takes integer abilityid, integer pos returns nothing
            local AbilityData d
            local Ability a
            if abilityid == 0 then
                return
            endif
            set d = AbilityData.GetDataByID(abilityid)
            if d != 0 then
                set a = Ability.create(d,hero)
                set Abilities.integer[pos] = a
                if pos == 1 then
                    set a.upID = up1
                elseif pos == 2 then
                    set a.upID = up2
                elseif pos == 3 then
                    set a.upID = up3
                elseif pos == 4 then
                    set a.upID = up4
                endif
                if abilityid == 'A011' then
                    call BlzUnitDisableAbility(hero,abilityid,true,false)
                endif
            else
                set Abilities.integer[pos] = 0
            endif
        endmethod
       
        public static method create takes unit hero,HeroData data returns thistype
            local thistype this = thistype.allocate()
            local integer id = GetUnitUserData(hero)
            local player p = GetOwningPlayer(hero)
            local integer pid = GetPlayerId(p)
            set .hero = hero
            set .data = data
            set .heroAI = -1
            call SetUnitData(hero,"HeroIndex",this)
            set heroAtt = HeroAtt.create(this)
            set INIT_AI = GetPlayerController(p) == MAP_CONTROL_COMPUTER
            if not INIT_AI then
                set perks = Perks.create(hero)
                call UnitMakeAbilityPermanent(hero,true,UPGRADE1_ID)
                call UnitMakeAbilityPermanent(hero,true,UPGRADE2_ID)
                call UnitMakeAbilityPermanent(hero,true,UPGRADE3_ID)
                call UnitMakeAbilityPermanent(hero,true,data.HeroUp4.UpId)
                call UnitMakeAbilityPermanent(hero,true,'A01M')
                call UnitMakeAbilityPermanent(hero,true,'A04C')
                call UnitMakeAbilityPermanent(hero,true,'A01N')
                call UnitMakeAbilityPermanent(hero,true,'A07D')
                call UnitMakeAbilityPermanent(hero,true,'A08A')
                call SetUnitAbilityLevel(hero,'A01M',pid+1)
                call SetUnitAbilityLevel(hero,'A04C',pid+1)
                call SetUnitAbilityLevel(hero,'A01N',pid+1)
            else
                //call RemoveGuardPosition(hero)
            endif
            call BlzUnitDisableAbility(hero,data.HeroUp4.UpId,true,false)
            call TriggerRegisterUnitEvent(ON_LEVEL_TRIGGER,hero,EVENT_UNIT_HERO_LEVEL)
            call BonusStruct.Add(BONUS_TYPE_HP,hero,data.HpLvl,0,false)
            call BonusStruct.Add(BONUS_TYPE_MP,hero,data.MpLvl,0,false)
            call BonusStruct.AddSpecial(BONUS_TYPE_BLOCK,hero,data.Block,0)
            call BonusStruct.AddSpecial(BONUS_TYPE_EVASION,hero,data.Evasion,0)
            call BonusStruct.AddSpecial(BONUS_TYPE_RESISTANCE,hero,data.Resistance,0)
            call BonusStruct.AddSpecial(BONUS_TYPE_LIFE_REGEN,hero,data.LifeRegen,0)
            call BonusStruct.AddSpecial(BONUS_TYPE_MANA_REGEN,hero,data.ManaRegen,0)
            set HERO_AI = this
            set Abilities = Table.create()
            call LoadFunction.RunFunction(data.TypeID)
            call HeroAddAbility(HeroAbility1,1)
            call HeroAddAbility(HeroAbility2,2)
            call HeroAddAbility(HeroAbility3,3)
            call HeroAddAbility(HeroAbility4,4)
            call HeroAddAbility(HeroAbility5,5)
            call HeroAddAbility(HeroAbility6,6)
            if pid != 0 and pid != 1 then
                set up1 = Upgrade.create(data.HeroUp1,this)
                set up2 = Upgrade.create(data.HeroUp2,this)
                set up3 = Upgrade.create(data.HeroUp3,this)
                set up4 = Upgrade.create(data.HeroUp4,this)
            else
                set up1 = 0
                set up2 = 0
                set up3 = 0
                set up4 = 0
            endif
            set upgradePoints = 0
            set upgradeLvl = 4
            call MultiboardUpdateHeroIcon(p,data.IconID)
            if heroAI != -1 then
                call heroAI.abilityBuild.learnNextSkill()
            endif
            if p != Game.PLAYER_WARCHIEF_HORDE and p != Game.PLAYER_WARCHIEF_ALLIANCE then
                if Game.Mode == GAME_MODE_NORMAL then
                    call AIRegion.RegisterHero(hero)
                    call AncientObelisk.RegisterHero(hero)
                endif
                if Game.Mode == GAME_MODE_LMS or Game.Mode == GAME_MODE_OD then
                    call SetHeroLevel(hero,2,true)
                    call SetHeroLevel(hero,3,true)
                endif
            endif
            set p = null
            return this
        endmethod
       
        public static method onLevel takes nothing returns nothing
            local Hero h = GetUnitData(GetTriggerUnit(),"HeroIndex")
            local integer lvl = GetHeroLevel(h.hero)
            local player p = GetTriggerPlayer()
            if h != 0 then
                call MultiboardUpdateLevel(p,GetHeroLevel(GetTriggerUnit()))
                //call BonusStruct.Add(BONUS_TYPE_HP,h.hero,h.HpLvl,0,false)
                //call BonusStruct.Add(BONUS_TYPE_MP,h.hero,h.MpLvl,0,false)
                call h.heroAtt.recalculate()
                if lvl == h.upgradeLvl then
                    set h.upgradeLvl = h.upgradeLvl + 2
                    call Upgrade.AddUpgradePoints(h)
                    if h.heroAI != -1 then
                        call h.heroAI.upgradeBuild.learnUpgrade()
                    endif
                endif
                if h.heroAI != -1 then
                    call h.heroAI.abilityBuild.learnNextSkill()
                else
                    if lvl == 4 or lvl == 8 or lvl == 12 or lvl == 16 or lvl == 20 then
                        if lvl != 20 then
                            call UnitModifySkillPoints(h.hero, -1)
                        endif
                        call h.perks.addPerkBook(lvl)
                        call BlzUnitDisableAbility(h.hero,'AHer',true,true)
                    endif
                endif
            endif
            set p = null
        endmethod
    endstruct
   
    private function init takes nothing returns nothing
        set ON_LEVEL_TRIGGER = CreateTrigger()
        call TriggerAddCondition(ON_LEVEL_TRIGGER,Condition(function Hero.onLevel))
        set HeroData.RandomListHorde = LinkedList.create()
        set HeroData.RandomListAlliance = LinkedList.create