wc3campaigns
WC3C Homepage - www.wc3c.netUser Control Panel (Requires Log-In)Engage in discussions with other users and join contests in the WC3C forums!Read one of our many tutorials, ranging in difficulty from beginner to advanced!Show off your artistic talents in the WC3C Gallery!Download quality models, textures, spells (vJASS/JASS), systems, and scripts!Download maps that have passed through our rigorous approval process!

Go Back   Wc3C.net > Warcraft III Modding > Developer's Corner > Triggers & Scripts
User Name
Password
Register Rules Get Hosted! Chat Pastebin FAQ and Rules Members List Calendar



Reply
 
Thread Tools Search this Thread
Old 02-19-2007, 11:28 PM   #1
Lordy
User
 
Lordy's Avatar
 
Join Date: May 2006
Posts: 72

Submissions (1)

Lordy has little to show at this moment (7)

Send a message via MSN to Lordy
Default A pile of code. Did I code it right?

Hi,

I'm here with a big request :). I have been working on a map for a while, of which all the code is written in Jass. I now have about 7000 lines of code. The map is not finished and I still have a lot of code ahead of me! Now comes my problem: before I resume my work, I'd like to get some feedback on the code I've already written. While coding I have never asked for feedback so it seems inevitable to me that I must have been doing sómething wrong! If someone or some people could take some peeks into my code and say what they think about it then I'd be very happy. You might say "O you've got some minor leaks here and there, fix them and it's good"; or maybe you'll say "You're using a completely wrong approach. Read this thread and then maybe you'll figure it out". Whatever you'll say, it'll help me. So please read my code! :).

While working on my map I tried to keep somewhat up to date on the current way of doing things in Jass. I have been coding in Jasscraft; have made use of Handle-vars, null'ing; avoided some strange bugs, and what not. A leak that I have not yet removed is the boolexp leak, of which I learned recently. Some of the comments I have made are in Dutch, but all the naming is done in English.

Edit: Code is now in the post, instead of being attached.
Code:
globals
    // User-defined
    trigger                 udg_unitdamaged            = null
    integer array           udg_habils
    integer array           udg_uabils
    unit                    udg_caster                 = null
    group                   udg_availablecasters       = null
    integer array           udg_unittypes
    integer array           udg_buffs
    integer                 udg_tempint                = 0
    real                    udg_tempreal               = 0
    string array            udg_orders
    unit                    udg_tempunit               = null
    effect                  udg_tempeffect             = null
    boolean                 udg_tempbool               = false
    gamecache               udg_gamecache              = null
    integer array           udg_herotypes
    unit array              udg_boats
    dialog                  udg_dialog                 = null
    button array            udg_dialogbuttons
    integer array           udg_scores
    integer                 udg_gamemode               = 0
    multiboard              udg_multiboard             = null
    integer array           udg_multiboardindex
    force array             udg_forces
    rect array              udg_startrects
    trigger                 udg_unitdies               = null
    boolean                 udg_allpick                = false
    integer                 udg_xp                     = 0
    group                   udg_heroesgroup            = null
    unit array              udg_god
    trigger                 udg_unitselected           = null
    group array             udg_heroteamgroups
    integer array           udg_buffabils
    integer array           udg_showbuffs
    boolean                 udg_tempbool2              = false
    real                    udg_tempreal2              = 0
    unit                    udg_tempunit2              = null
    string array            udg_bufforders
    integer array           udg_dummyunittypes
    integer array           udg_tempints
    real array              udg_tempreals
    destructable            udg_tempdest               = null
    group                   udg_busyunits              = null
    integer array           udg_desttypes
    location array          udg_boatfirelocs
    boolean                 udg_chooseattributes       = false
    integer array           udg_shrine2controller
    integer array           udg_player2force
    integer array           udg_player2boardrow
    integer array           udg_deaths
    integer array           udg_kills
    integer                 udg_gamemode2              = 0
    integer                 udg_victorytarget          = 0
    leaderboard             udg_leaderboard            = null
    integer                 udg_bestplayer             = 0
    integer                 udg_secondbestplayer       = 0
    integer                 udg_playersleft            = 0
    location array          udg_revivelocs
    integer                 udg_teamcount              = 0
    unit array              udg_shrines
    integer                 udg_playercount            = 0
    boolean                 udg_killxpgold             = false
    boolean                 udg_noherotypelimit        = false
    boolean                 udg_level4start            = false
    player                  udg_host                   = null
    boolean                 udg_mirrormatch            = false
    boolean                 udg_oneherotype            = false
    integer                 udg_gamelength             = 0
    integer                 udg_dialogstep             = 0
    force                   udg_tempforce              = null
    integer array           udg_player2colorcode
    integer                 udg_mapmaxteams            = 0
    texttag array           udg_boattags
    rect                    udg_roughplayground        = null
    region                  udg_playground             = null
    trigger                 udg_temptrig               = null
    integer array           udg_heronumbers
    string                  udg_tempstring
    group                   udg_tempgroup              = null
    real                    udg_gravity                = 0
    real                    udg_pointspermeter         = 0
    boolean                 udg_day                    = false
    boolean                 udg_igniteburns            = false
    boolean                 udg_test_refreshheroes     = false
    unit                    udg_test_lunatic           = null

    // Generated
    rect                    gg_rct_Rect_000            = null
    rect                    gg_rct_Rect_001            = null
    rect                    gg_rct_Rect_002            = null
    sound                   gg_snd_Shockwave           = null
    trigger                 gg_trg_Init_Heroes_isCOMMON = null
    trigger                 gg_trg_Init_Debug_isCOMMON = null
    trigger                 gg_trg_Init_HeroTestMap    = null
    trigger                 gg_trg_Init_TwoShrinesMap  = null
    trigger                 gg_trg_InitTwoShrinesMapDebug = null
    unit                    gg_unit_O001_0000          = null
    rect                    gg_rct_Playground          = null


//JASSHelper struct globals:

endglobals

//=================================================================================================
//Changables
//constant functions AgiAdd, StrAdd and IntAdd

//===============================================================================================================
//CONSTANTS

constant function AgiAdd takes integer heronumber returns real
    local real array agiadds
    set agiadds[0] = 2
    set agiadds[1] = 2
    set agiadds[2] = 2
    set agiadds[3] = 2
    set agiadds[4] = 2
    set agiadds[5] = 2
    set agiadds[6] = 2
    set agiadds[7] = 2
    set agiadds[8] = 2
    set agiadds[9] = 2
    set agiadds[10] = 2
    set agiadds[11] = 2
    return agiadds[heronumber]
endfunction

constant function IntAdd takes integer heronumber returns real
    local real array intadds
    set intadds[0] = 2
    set intadds[1] = 2
    set intadds[2] = 2
    set intadds[3] = 2
    set intadds[4] = 2
    set intadds[5] = 2
    set intadds[6] = 2
    set intadds[7] = 2
    set intadds[8] = 2
    set intadds[9] = 2
    set intadds[10] = 2
    set intadds[11] = 2
    return intadds[heronumber]
endfunction

constant function StrAdd takes integer heronumber returns real
    local real array stradds
    set stradds[0] = 2
    set stradds[1] = 2
    set stradds[2] = 2
    set stradds[3] = 2
    set stradds[4] = 2
    set stradds[5] = 2
    set stradds[6] = 2
    set stradds[7] = 2
    set stradds[8] = 2
    set stradds[9] = 2
    set stradds[10] = 2
    set stradds[11] = 2
    return stradds[heronumber]
endfunction

//HERO2NUMBER
constant function Hero2Number takes integer hero returns integer
    if hero == 'O001' then
        return 0
    elseif hero == 'N002' then
        return 1
    elseif hero == 'O003' then
        return 2
    elseif hero == 'N000' then
        return 3
    elseif hero == 'O000' then
        return 4
    elseif hero == 'N001' then
        return 5
    elseif hero == 'O008' then
        return 6
    elseif hero == 'U000' then
        return 7
    elseif hero == 'H002' then
        return 8
    elseif hero == 'H00J' then
        return 9
    elseif hero == 'U001' then
        return 10
    elseif hero == 'E000' then
        return 11
    endif
    return 0
endfunction

//PowerOf2
constant function TwoPowInt takes integer i returns integer
    local integer a
    local integer b
    if i == 0 then
        return 0
    elseif i == 1 then
        return 2
    elseif i == 2 then
        return 4
    elseif i == 3 then
        return 8
    elseif i == 4 then
        return 16
    elseif i == 5 then
        return 32
    elseif i == 6 then
        return 64
    elseif i == 7 then
        return 128
    elseif i == 8 then
        return 256
    elseif i == 9 then
        return 512
    elseif i == 10 then
        return 1024
    elseif i == 11 then
        return 2048
    elseif i == 12 then
        return 4096
    elseif i > 12 then
        set a = 12
        set b = 4096
        loop
            exitwhen a == i
            set b = b * 2
            set a = a + 1
        endloop
        return b
    endif
    return 0
endfunction

constant function BonusAbilityId takes integer i returns integer
    local integer array BonusAbilityIds
    set BonusAbilityIds[0] = 'A001'
    set BonusAbilityIds[1] = 'A010'
    set BonusAbilityIds[2] = 'A00Z'
    set BonusAbilityIds[3] = 'A00Y'
    set BonusAbilityIds[4] = 'A00X'
    set BonusAbilityIds[5] = 'A012'
    set BonusAbilityIds[6] = 'A013'
    set BonusAbilityIds[7] = 'A00W'
    set BonusAbilityIds[8] = 'A011'
    set BonusAbilityIds[9] = 'A015'
    set BonusAbilityIds[10] = 'A016'
    set BonusAbilityIds[11] = 'A014'
    set BonusAbilityIds[12] = 'A00K'
    set BonusAbilityIds[13] = 'A00N'
    set BonusAbilityIds[14] = 'A00O'
    set BonusAbilityIds[15] = 'A00R'
    set BonusAbilityIds[16] = 'A00S'
    set BonusAbilityIds[17] = 'A017'
    set BonusAbilityIds[18] = 'A01L'
    set BonusAbilityIds[19] = 'A01M'
    set BonusAbilityIds[20] = 'A01P'
    set BonusAbilityIds[21] = 'A01Q'
    set BonusAbilityIds[22] = 'A01R'
    set BonusAbilityIds[23] = 'A01S'
    set BonusAbilityIds[24] = 'A01Y'
    set BonusAbilityIds[25] = 'A01X'
    set BonusAbilityIds[26] = 'A01Z'
    set BonusAbilityIds[27] = 'A020'
    set BonusAbilityIds[28] = 'A021'
    set BonusAbilityIds[29] = 'A022'
    set BonusAbilityIds[30] = 'A023'
    set BonusAbilityIds[31] = 'A024'
    set BonusAbilityIds[32] = 'A025'
    set BonusAbilityIds[33] = 'A026'
    set BonusAbilityIds[34] = 'A027'
    set BonusAbilityIds[35] = 'A028'
    set BonusAbilityIds[36] = 'A029'
    set BonusAbilityIds[37] = 'A02A'
    set BonusAbilityIds[38] = 'A02B'
    set BonusAbilityIds[39] = 'A04B'
    set BonusAbilityIds[40] = 'A049'
    set BonusAbilityIds[41] = 'A048'
    set BonusAbilityIds[42] = 'A047'
    set BonusAbilityIds[43] = 'A046'
    set BonusAbilityIds[44] = 'A045'
    set BonusAbilityIds[45] = 'A044'
    set BonusAbilityIds[46] = 'A043'
    set BonusAbilityIds[47] = 'A042'
    set BonusAbilityIds[48] = 'A03I'
    set BonusAbilityIds[49] = 'A01C'
    return BonusAbilityIds[i]
endfunction
//================================================================================================
//DEBUG

function Msg takes string text returns nothing
    call DisplayTextToPlayer(Player(0),0,0,text)
    
endfunction

//Changebonus
function ChangeBonus takes unit subject, real ammount, integer index, boolean add returns nothing
    local integer i=1
    local integer array ChangeBonusTypeStartInts
    //RemoveOldAbilities
    set ChangeBonusTypeStartInts[0]=0        
    set ChangeBonusTypeStartInts[1]=ChangeBonusTypeStartInts[0]+12 //DMG   
    set ChangeBonusTypeStartInts[2]=ChangeBonusTypeStartInts[1]+12 //IAS 
    set ChangeBonusTypeStartInts[3]=ChangeBonusTypeStartInts[2]+15 //LIFE
    set ChangeBonusTypeStartInts[4]=ChangeBonusTypeStartInts[3]+12 //ARMOUR
    set i = ChangeBonusTypeStartInts[index]
    loop
        exitwhen i==ChangeBonusTypeStartInts[index+1]
        if add then
            if UnitRemoveAbility(subject, BonusAbilityId(i)) then
                set ammount = ammount + TwoPowInt(i-ChangeBonusTypeStartInts[index])
            endif
        else
            call UnitRemoveAbility(subject, BonusAbilityId(i))
        endif
        set i=i+1
    endloop
    
    //AddNewAbilities
    set i = (ChangeBonusTypeStartInts[index+1] - ChangeBonusTypeStartInts[index]) - 1
    loop
        exitwhen i == 0
        if ammount >= TwoPowInt(i) then
            call UnitAddAbility(subject, BonusAbilityId(ChangeBonusTypeStartInts[index] + i))
            call UnitMakeAbilityPermanent(subject,true,BonusAbilityId(ChangeBonusTypeStartInts[index] + i))
            set ammount = ammount - TwoPowInt(i)
        endif
        exitwhen ammount == 0
        set i = i - 1
    endloop
endfunction

//===================================================================================================================
//Attaching Handle-Vars
function H2I takes handle h returns integer
    return h
    return 0
endfunction

function SetHandleHandle takes handle subject, string name, handle value returns nothing
    if value==null then
        call FlushStoredInteger(udg_gamecache,I2S(H2I(subject)),name)
    else
        call StoreInteger(udg_gamecache, I2S(H2I(subject)), name, H2I(value))
    endif
endfunction

function SetHandleInt takes handle subject, string name, integer value returns nothing
    if value==0 then
        call FlushStoredInteger(udg_gamecache,I2S(H2I(subject)),name)
    else
        call StoreInteger(udg_gamecache, I2S(H2I(subject)), name, value)
    endif
endfunction

function SetHandleBoolean takes handle subject, string name, boolean value returns nothing
    if value==false then
        call FlushStoredBoolean(udg_gamecache,I2S(H2I(subject)),name)
    else
        call StoreBoolean(udg_gamecache, I2S(H2I(subject)), name, value)
    endif
endfunction

function SetHandleReal takes handle subject, string name, real value returns nothing
    if value==0 then
        call FlushStoredReal(udg_gamecache, I2S(H2I(subject)), name)
    else
        call StoreReal(udg_gamecache, I2S(H2I(subject)), name, value)
    endif
endfunction

function SetHandleString takes handle subject, string name, string value returns nothing
    if value==null then
        call FlushStoredString(udg_gamecache, I2S(H2I(subject)), name)
    else
        call StoreString(udg_gamecache, I2S(H2I(subject)), name, value)
    endif
endfunction

function GetHandleHandle takes handle subject, string name returns handle
    return GetStoredInteger(udg_gamecache, I2S(H2I(subject)), name)
    return null
endfunction

function GetHandleInt takes handle subject, string name returns integer
    return GetStoredInteger(udg_gamecache, I2S(H2I(subject)), name)
endfunction

function GetHandleBoolean takes handle subject, string name returns boolean
    return GetStoredBoolean(udg_gamecache, I2S(H2I(subject)), name)
endfunction

function GetHandleReal takes handle subject, string name returns real
    return GetStoredReal(udg_gamecache, I2S(H2I(subject)), name)
endfunction

function GetHandleString takes handle subject, string name returns string
    return GetStoredString(udg_gamecache, I2S(H2I(subject)), name)
endfunction

function FlushHandleLocals takes handle subject returns nothing
    call FlushStoredMission(udg_gamecache, I2S(H2I(subject)) )
endfunction

function I2Unit takes integer i returns unit
    return i
    return null
endfunction

function I2Timer takes integer i returns timer
    return i
    return null
endfunction

function I2Trigger takes integer i returns trigger
    return i
    return null
endfunction

function I2Group takes integer i returns group
    return i
    return null
endfunction

function I2Lightning takes integer i returns lightning
    return i
    return null
endfunction

function I2Effect takes integer i returns effect
    return i
    return null
endfunction

function I2Player takes integer i returns player
    return i
    return null
endfunction

function I2Location takes integer i returns location
    return i
    return null
endfunction

function GetHandleUnit takes handle subject, string name returns unit
    return GetHandleHandle(subject,name)
    return null
endfunction

function GetHandleGroup takes handle subject, string name returns group
    return GetHandleHandle(subject,name)
    return null
endfunction

function GetHandleTimer takes handle subject, string name returns timer
    return GetHandleHandle(subject,name)
    return null
endfunction

function GetHandleTrigger takes handle subject, string name returns trigger
    return GetHandleHandle(subject,name)
    return null
endfunction

function GetHandleEffect takes handle subject, string name returns effect
    return GetHandleHandle(subject,name)
    return null
endfunction

//===============================================================================================================
//Caster

function GetaCaster takes player owner, integer abil, integer level, real x, real y, real z returns unit
    if IsUnitGroupEmptyBJ(udg_availablecasters) == true then
        set udg_caster = CreateUnit(Player(15),udg_dummyunittypes[0], x, y, 0)
    else
        set udg_caster = FirstOfGroup(udg_availablecasters)
        call SetUnitPosition(udg_caster, x,y)
        call GroupRemoveUnitSimple(udg_caster, udg_availablecasters )
    endif
    call SetUnitOwner(udg_caster, owner, false)
    if abil != 0 then
        call UnitAddAbility(udg_caster, abil)
        call SetUnitAbilityLevel(udg_caster, abil, level)
    endif
    call SetUnitFlyHeight(udg_caster,z,0)
    return udg_caster
endfunction

function RecycleCaster takes nothing returns nothing
    local unit caster = udg_caster
    local integer index = udg_tempint
    local real delay = udg_tempreal
    call TriggerSleepAction(delay)
    call FlushHandleLocals(caster)
    call UnitRemoveAbility(caster, udg_uabils[index])
    call GroupAddUnitSimple(caster, udg_availablecasters )
    set caster = null
endfunction

function CastCorAbilityCor takes player owner, integer index, integer level, real x2, real y2, real delay, real x, real y, real z returns unit
    local unit caster = GetaCaster(owner, udg_uabils[index], level, x, y, z)
    if udg_orders[index] == null then
        call IssuePointOrder(udg_caster, "channel", x2, y2)
    else
        call IssuePointOrder(udg_caster, udg_orders[index], x2, y2)
    endif
    if delay != -1 then
        set udg_tempint = index
        set udg_tempreal = delay
        call ExecuteFunc("RecycleCaster")
    endif
    return caster
endfunction

function CastLocAbilityCor takes player owner, integer index, integer level, location spellloc, real delay, real x, real y, real z returns unit
    return CastCorAbilityCor(owner, index, level, GetLocationX(spellloc), GetLocationY(spellloc), delay, x, y, z)
    
endfunction

function CastCorAbilityLoc takes player owner, integer index, integer level, real x, real y, real delay, location casterloc, real z returns unit
    return CastCorAbilityCor(owner, index, level, x, y, delay, GetLocationX(casterloc), GetLocationY(casterloc), z)
endfunction

function CastLocAbilityLoc takes player owner, integer index, integer level, location spellloc, real delay, location casterloc, real z returns unit
    return CastLocAbilityCor(owner, index, level, spellloc, delay, GetLocationX(casterloc), GetLocationY(casterloc), z)
endfunction

function CastCorAbility takes player owner, integer index, integer level, real x, real y, real delay returns unit
    return CastCorAbilityCor(owner, index, level, x, y, delay, 0, 0, 0)
endfunction

function CastWidgetAbilityCor takes player owner, integer index, integer level, widget target, real delay, real x, real y, real z returns unit
    local unit caster = GetaCaster(owner, udg_uabils[index], level, x, y, z)
    if udg_orders[index] == null then
        call IssueTargetOrder(udg_caster, "channel", target)
    else
        call IssueTargetOrder(udg_caster, udg_orders[index], target)
    endif
    if delay != -1 then
        set udg_tempint = index
        set udg_tempreal = delay
        call ExecuteFunc("RecycleCaster")
    endif
    return caster
endfunction

function CastWidgetAbilityLoc takes player owner, integer index, integer level, widget target, real delay, location casterloc, real z returns unit
    return CastWidgetAbilityCor(owner, index, level, target, delay, GetLocationX(casterloc), GetLocationY(casterloc), z)
endfunction

function CastWidgetAbility takes player owner, integer index, integer level, widget target, real delay returns unit
    return CastWidgetAbilityCor(owner, index, level, target, delay, 0, 0, 0)
endfunction

function CastAbilityCor takes player owner, integer index, integer level, real delay, real x, real y, real z returns unit
    local unit caster = GetaCaster(owner, udg_uabils[index], level, x, y, z)
    if udg_orders[index] == null then
        call IssueImmediateOrder(udg_caster, "channel")
    else
        call IssueImmediateOrder(udg_caster, udg_orders[index])
    endif
    if delay != -1 then
        set udg_tempint = index
        set udg_tempreal = delay
        call ExecuteFunc("RecycleCaster")
    endif
    return caster
endfunction

function CastAbilityLoc takes player owner, integer index, integer level, real delay, location casterloc, real z returns unit
    return CastAbilityCor(owner, index, level, delay, GetLocationX(casterloc), GetLocationY(casterloc), z)
endfunction

function CastAbility takes player owner, integer index, integer level, real delay returns unit
    return CastAbilityCor(owner, index, level, delay, 0, 0, 0)
endfunction

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

//BUFFING
function Addbuff takes unit target, integer index, real duration returns nothing
    call GetaCaster(Player(0), udg_buffabils[index], 1, 0, 0, 0)
    if udg_bufforders[index] == null then
        call IssueImmediateOrder(udg_caster, "absorb")
    else
        call IssueTargetOrder(udg_caster, udg_bufforders[index], target)
    endif
    set udg_tempint = index
    call ExecuteFunc("BuffCasterRefresh")
    if duration != -1 then
        set udg_tempreal = duration
        set udg_tempunit = target
        call ExecuteFunc("BuffRemove")
    endif
    set target = null
    call DisplayTextToPlayer(Player(0),0,0,"buffcast")
endfunction

function BuffCasterRefresh takes nothing returns nothing
    local unit caster = udg_caster
    local integer index = udg_tempint
    call TriggerSleepAction(0)
    call FlushHandleLocals(caster)
    call UnitRemoveAbility(caster, udg_buffabils[index])
    call GroupAddUnitSimple(caster, udg_availablecasters)
    set caster = null
endfunction

function BuffRemove takes nothing returns nothing
    local real duration = udg_tempreal
    local unit target = udg_tempunit
    local integer index = udg_tempint
    call TriggerSleepAction(duration)
    call DisplayTextToPlayer(Player(0),0,0,"buffend")
    call UnitRemoveBuffBJ(udg_showbuffs[index], target)
    set target = null
endfunction


//SLOW + STUN
function Stun takes unit target, real duration returns nothing
    call Addbuff(target, 7,duration)
endfunction

function Slow takes unit target, real speed, real duration returns nothing
    call SetUnitMoveSpeed(target, GetUnitMoveSpeed(target) - speed)
    if duration != -1 then
        set udg_tempreal = duration
        set udg_tempunit = target
        set udg_tempreal2 = speed
        call ExecuteFunc("SlowReverse")
    endif
endfunction

function SlowReverse takes nothing returns nothing
    local real duration = udg_tempreal
    local unit target = udg_tempunit
    local real speed = udg_tempreal2
    call TriggerSleepAction(duration)
    call SetUnitMoveSpeed(target, GetUnitMoveSpeed(target) + speed)
    set target = null
endfunction

//Dot
function Dot takes unit subject, unit target, integer dmg, real duration, real interval returns nothing
    set udg_tempunit = subject
    set udg_tempunit2 = target
    set udg_tempint = dmg
    set udg_tempreal = duration
    set udg_tempreal2 = interval
    call ExecuteFunc("DotUpdate")
endfunction

function DotUpdate takes nothing returns nothing
    local unit subject = udg_tempunit
    local unit target = udg_tempunit2
    local integer dmg = udg_tempint
    local real duration = udg_tempreal
    local real interval = udg_tempreal2
    local real r = 0
    loop
        exitwhen r > duration
        call UnitDamageTargetBJ(subject,target,dmg,ATTACK_TYPE_CHAOS,DAMAGE_TYPE_UNIVERSAL)
        set r = r + interval
        call TriggerSleepAction(interval)
    endloop
    set subject = null
    set target = null
endfunction

//Hot
function Hot takes unit subject, integer heal, real duration, real interval returns nothing
    set udg_tempunit = subject
    set udg_tempint = heal
    set udg_tempreal = duration
    set udg_tempreal2 = interval
    call ExecuteFunc("HotUpdate")
endfunction

function HotUpdate takes nothing returns nothing
    local unit subject = udg_tempunit
    local integer heal = udg_tempint
    local real duration = udg_tempreal
    local real interval = udg_tempreal2
    local real r = 0
    loop
        exitwhen r > duration
        call SetUnitState(subject,UNIT_STATE_LIFE,GetUnitState(subject,UNIT_STATE_LIFE)+heal)
        set r = r + interval
        call TriggerSleepAction(interval)
    endloop
    set subject = null
endfunction

//Misc
function GetHeroAbilityLevel takes unit hero, integer index returns integer
    return GetUnitAbilityLevel(hero, udg_habils[index])
endfunction

//MATH

function Angle takes real x, real y, real x2, real y2 returns real
    return Atan2((y2 - y),(x2 - x))
endfunction

function DistanceSqr takes real x, real y, real x2, real y2 returns real
    return x*x+2*x*-x2+x2*x2+y*y+2*y*-y2+y2*y2
endfunction

function Distance takes real x, real y, real x2, real y2 returns real
    return SquareRoot(DistanceSqr(x,y,x2,y2))
endfunction

//MOVE UNIT
function SetUnitCor takes unit subject, real x, real y returns nothing
    call SetUnitX(subject, x)
    call SetUnitY(subject, y)
endfunction

function MoveUnit takes unit subject, real x, real y returns nothing
    call SetUnitCor(subject, GetWidgetX(subject) + x, GetWidgetY(subject) + y)
    set subject = null
endfunction

//DESTROY EFFECT
function DestroyEffectWait takes effect target, real delay returns nothing
    set udg_tempeffect = target
    set udg_tempreal = delay
    call ExecuteFunc("DestroyEffectWait2")
endfunction

function DestroyEffectWait2 takes nothing returns nothing
    local effect target = udg_tempeffect
    call TriggerSleepAction(udg_tempreal)
    call DestroyEffect(target)
    set target = null
endfunction

//DAMAGE
function UnitDamageTargetNew takes unit subject, unit target, integer dmg, integer type1, integer type2, integer type3 returns nothing
    if type1 == 0 then
        call UnitDamageTarget(subject, target, dmg, true, false, ConvertAttackType(type2), DAMAGE_TYPE_UNIVERSAL, WEAPON_TYPE_WHOKNOWS)
    else
        if type1 == 1 then
            call UnitDamageTarget(subject, target, dmg, true, true, ConvertAttackType(type2), DAMAGE_TYPE_UNIVERSAL, WEAPON_TYPE_WHOKNOWS)
        else
            call UnitDamageTarget(subject, target, dmg, false, true, ConvertAttackType(type2), DAMAGE_TYPE_UNIVERSAL, WEAPON_TYPE_WHOKNOWS)
        endif
    endif
endfunction

function UnitDamageArea2 takes nothing returns nothing
    call UnitDamageTargetNew(udg_tempunit, GetEnumUnit(), udg_tempints[0], udg_tempints[1], udg_tempints[2], udg_tempints[3])
endfunction

function IsGameUnitId takes integer i returns boolean
    local integer i2 = 0
    loop
        exitwhen udg_dummyunittypes[i2] == 0
        if i == udg_dummyunittypes[i2] then
            return false
        endif
        set i2 = i2 + 1
    endloop
    return true
endfunction

function IsGameUnit takes unit subject returns boolean
    return IsGameUnitId(GetUnitTypeId(subject))
endfunction

function TargetTypeCondition takes unit subject, unit object, integer i returns boolean
    local boolean b = true
    if IsGameUnit(subject) then
        if i >= 32768 then //Unit must be alive
            set i = i - 32768
            if GetUnitState(subject, UNIT_STATE_LIFE) == 0 then
                set b = false
            endif
        endif
        if i >= 16384 then
            set i = i - 16384
            if IsUnitType(subject, UNIT_TYPE_FLYING) then
                set b = false
            endif
        endif
        if i >= 8192 then
            set i = i - 8192
            if not IsUnitType(subject, UNIT_TYPE_FLYING) then
                set b = false
            endif
        endif
        if i >= 4096 then
            set i = i - 4096
            if IsUnitType(subject, UNIT_TYPE_ETHEREAL) then
                set b = false
            endif
        endif
        if i >= 2048 then
            set i = i - 2048
            if not IsUnitType(subject, UNIT_TYPE_ETHEREAL) then
                set b = false
            endif
        endif
        if i >= 1024 then
            set i = i - 1024
            if IsUnitType(subject, UNIT_TYPE_MAGIC_IMMUNE) then
                set b = false
            endif
        endif
        if i >= 512 then
            set i = i - 512
            if not IsUnitType(subject, UNIT_TYPE_SUMMONED) then
                set b = false
            endif
        endif
        if i >= 256 then
            set i = i - 256
            if IsUnitType(subject, UNIT_TYPE_UNDEAD) then
                set b = false
            endif
        endif
        if i >= 128 then
            set i = i - 128
            if not IsUnitType(subject, UNIT_TYPE_UNDEAD) then
                set b = false
            endif
        endif
        if i >= 64 then
            set i = i - 64
            if IsUnitType(subject, UNIT_TYPE_MECHANICAL) then
                set b = false
            endif
        endif
        if i >= 32 then
            set i = i - 32
            if not IsUnitType(subject, UNIT_TYPE_MECHANICAL) then
                set b = false
            endif
        endif
        if i >= 16 then
            set i = i - 16
            if GetOwningPlayer(subject) == GetOwningPlayer(object) then
                set b = false
            endif
        endif
        if i >= 8 then
            set i = i - 8
            if GetOwningPlayer(subject) != GetOwningPlayer(object) then
                set b = false
            endif
        endif
        if i >= 4 then //unit must be enemy
            set i = i - 4
            if not IsUnitEnemy(subject,GetOwningPlayer(object)) then
                set b = false
            endif
        endif
        if i >= 2 then
            set i = i - 2
            if not IsUnitAlly(subject,GetOwningPlayer(object)) then
                set b = false
            endif
        endif
        if i == 1 then
            set i = i - 1
            if subject == object then
                set b = false
            endif
        endif
    else
        set b = false
    endif
    return b
endfunction

function UnitDamageAreaCondition takes nothing returns boolean
    return TargetTypeCondition(GetFilterUnit(),udg_tempunit,udg_tempint)
endfunction

function UnitDamageArea takes unit subject, real x, real y, real radius, integer targettypeint, integer dmg, integer type1, integer type2, integer type3 returns nothing
    local location loc = Location(x,y)
    set udg_tempunit = subject
    set udg_tempint = targettypeint
    set udg_tempints[0] = dmg
    set udg_tempints[1] = type1
    set udg_tempints[2] = type2
    set udg_tempints[3] = type3
    call ForGroup(GetUnitsInRangeOfLocMatching(radius, loc, Condition(function UnitDamageAreaCondition)), function UnitDamageArea2)
    call RemoveLocation(loc)
    set loc = null
endfunction

//GET HOST
function GetHost takes nothing returns player
    call StoreInteger(udg_gamecache, "players", "host", GetPlayerId(GetLocalPlayer()) + 1)
    call TriggerSyncStart()
    call SyncStoredInteger(udg_gamecache, "players", "host")
    call TriggerSyncReady()
    return Player(GetStoredInteger(udg_gamecache, "players", "host") - 1)
endfunction

//Flying
function DumbVerticalFlightUpdate takes nothing returns nothing
    local timer updatetimer = GetExpiredTimer()
    local string updatetimerstring = I2S(H2I(updatetimer))
    local unit subject = I2Unit(GetStoredInteger(udg_gamecache,updatetimerstring,"subject"))
    local real dt = 0.02
    local real ticks = GetStoredReal(udg_gamecache,updatetimerstring,"ticks")+1
    local real zvelocity0 = GetStoredReal(udg_gamecache,updatetimerstring,"zvelocity0")
    local real height = udg_pointspermeter * (zvelocity0*ticks*dt - 0.5*udg_gravity*ticks*dt*ticks*dt)
    local string endfunc
    local real x = GetWidgetX(subject)+GetStoredReal(udg_gamecache,updatetimerstring,"xppt")
    local real y = GetWidgetY(subject)+GetStoredReal(udg_gamecache,updatetimerstring,"yppt")
    call SetUnitCor(subject,x,y)
    call Msg("DumbVerticalFlightUpdate")
    call Msg(R2S(height))
    call Msg(R2S(x))
    call Msg(R2S(y))
    if not IsPointInRegion(udg_playground,x,y) then    
        call Msg("point not in region bug")
    endif
    //if height <= 0 or not IsPointInRegion(udg_playground,x,y) then
    if height <= 0 then
        call Msg("DumbVerticalFlightEnd")
        set height = 0
        call GroupRemoveUnit(udg_busyunits,subject)
        call UnitRemoveAbility(subject, 'Avul')
        set endfunc = GetStoredString(udg_gamecache,updatetimerstring,"endfunc")
        call ExecuteFunc(endfunc)
        call PauseUnit(subject,false)
        call PauseTimer(updatetimer)
        call DestroyTimer(updatetimer)
        call FlushStoredMission(udg_gamecache,updatetimerstring)
    else    
        call StoreReal(udg_gamecache,updatetimerstring,"ticks",ticks)
    endif
    call SetUnitFlyHeight(subject, height, 0)
    set subject = null
    set updatetimer = null
endfunction

function DumbMissileUpdate takes nothing returns nothing
    local timer updatetimer = GetExpiredTimer()
    local string updatetimerstring = I2S(H2I(updatetimer))
    local unit missile = I2Unit(GetStoredInteger(udg_gamecache,updatetimerstring,"missile"))
    local real dt = 0.02
    local real ticks = GetStoredReal(udg_gamecache,updatetimerstring,"ticks")+1
    local real zvelocity0 = GetStoredReal(udg_gamecache,updatetimerstring,"zvelocity0")
    local real deltah = GetUnitFlyHeight(missile)
    local real h0 = GetStoredReal(udg_gamecache,updatetimerstring,"h0")
    local real height = h0 + udg_pointspermeter * (zvelocity0*ticks*dt - 0.5*udg_gravity*ticks*dt*ticks*dt)
    local real xppt = GetStoredReal(udg_gamecache,updatetimerstring,"xppt")
    local real yppt = GetStoredReal(udg_gamecache,updatetimerstring,"yppt")
    local real x = GetWidgetX(missile)+xppt
    local real y = GetWidgetY(missile)+yppt
    local string endfunc
    call Msg("DumbMissileUpdate")
    call Msg(R2S(height))
    if not IsPointInRegion(udg_playground,x,y) then
        call Msg("playgroundregionnotsetright")
    endif
    set deltah = height-deltah
    call SetUnitX(missile,x)
    call SetUnitY(missile,y)
    call SetUnitLookAt(missile,"bone_chest",missile,xppt,yppt,deltah)
    if height <= h0 or not IsPointInRegion(udg_playground,x,y) then
        call Msg("DumbMissileEnd")
        set height = h0
        set endfunc = GetStoredString(udg_gamecache,updatetimerstring,"endfunc")
        call ExecuteFunc(endfunc)
        call PauseUnit(missile,false)
        call PauseTimer(updatetimer)
        call DestroyTimer(updatetimer)
        call FlushStoredMission(udg_gamecache,updatetimerstring)
    else    
        call StoreReal(udg_gamecache,updatetimerstring,"ticks",ticks)
    endif
    call SetUnitFlyHeight(missile, height, 0)
    set missile = null
    set updatetimer = null
endfunction

function StartDumbFlight takes unit subject, real angle, real missilespeed, real zvelocity0, real h0, string endfunc returns timer
    local timer t = CreateTimer()
    local string tstring = I2S(H2I(t))
    local real x = GetWidgetX(subject)
    local real y = GetWidgetY(subject)
    local real dt = 0.02
    local real xppt = missilespeed*dt*Cos(angle)
    local real yppt = missilespeed*dt*Sin(angle)
    call Msg("StartDumbFlight")
    call StoreInteger(udg_gamecache,tstring,"subject",H2I(subject))
    call StoreReal(udg_gamecache,tstring,"xppt",xppt)
    call StoreReal(udg_gamecache,tstring,"yppt",yppt)
    call StoreReal(udg_gamecache,tstring,"zvelocity0",zvelocity0)
    call StoreString(udg_gamecache,tstring,"endfunc",endfunc)
    if h0 != 0 then
        call StoreReal(udg_gamecache,tstring,"h0",h0)
        call TimerStart(t,dt,true,function DumbMissileUpdate)
    else
        call TimerStart(t,dt,true,function DumbVerticalFlightUpdate)
    endif
    return t
endfunction

function SmartMissileUpdate takes nothing returns nothing
    local timer updatetimer = GetExpiredTimer()
    local string updatetimerstring = I2S(H2I(updatetimer))
    local unit missile = I2Unit(GetStoredInteger(udg_gamecache,updatetimerstring,"missile"))
    local unit target = I2Unit(GetStoredInteger(udg_gamecache,updatetimerstring,"target"))
    local real dt = 0.02
    local real mheight = GetUnitFlyHeight(missile)
    local real theight = GetUnitFlyHeight(target)
    local real mx = GetWidgetX(missile)
    local real my = GetWidgetY(missile)
    local real tx = GetWidgetX(target)
    local real ty = GetWidgetY(target)
    local real dist = Distance(mx,my,tx,ty)
    local real mhorispeed = GetStoredReal(udg_gamecache,updatetimerstring,"speed")
    local integer ticksleft = 1+R2I(dist/mhorispeed/dt)
    local real hitheight = GetStoredReal(udg_gamecache,updatetimerstring,"hitheight")
    local real targetdheight = hitheight-mheight+theight
    local real vppt = GetStoredReal(udg_gamecache,updatetimerstring,"vppt")
    local real vpptpt = (targetdheight - vppt*ticksleft)/ticksleft/ticksleft
    local real newvppt = vppt + vpptpt
    local real dx = (tx - mx)/ticksleft
    local real dy = (ty - my)/ticksleft
    local real newmx = mx + dx
    local real newmy = my + dy
    local string endfunc
    local boolean b = false
    set mheight = mheight + newvppt
    call StoreReal(udg_gamecache,updatetimerstring,"vppt",newvppt)
    call Msg("SmartBlizzardMissileUpdate")
    if IsPointInRegion(udg_playground,newmx,newmy) then
        set b = true
    endif
    if b then
        call SetUnitCor(missile,newmx,newmy)
        call SetUnitLookAt(missile,"bone_chest",missile,1000*dx,1000*dy,1000*newvppt)
    endif
    if ticksleft == 1 or not b then
        call Msg("SmartBlizzardMissileEnd")
        set mheight = hitheight
        set endfunc = GetStoredString(udg_gamecache,updatetimerstring,"endfunc")
        call ExecuteFunc(endfunc)
        call PauseTimer(updatetimer)
        call DestroyTimer(updatetimer)
        call FlushStoredMission(udg_gamecache,updatetimerstring)
    endif
    call SetUnitFlyHeight(missile, mheight, 0)
    set missile = null
    set target = null
    set updatetimer = null
endfunction

function SmartUnitUpdate takes nothing returns nothing
    local timer updatetimer = GetExpiredTimer()
    local string updatetimerstring = I2S(H2I(updatetimer))
    local unit missile = I2Unit(GetStoredInteger(udg_gamecache,updatetimerstring,"missile"))
    local unit target = I2Unit(GetStoredInteger(udg_gamecache,updatetimerstring,"target"))
    local real dt = 0.02
    local real mheight = GetUnitFlyHeight(missile)
    local real theight = GetUnitFlyHeight(target)
    local real mx = GetWidgetX(missile)
    local real my = GetWidgetY(missile)
    local real tx = GetWidgetX(target)
    local real ty = GetWidgetY(target)
    local real dist = Distance(mx,my,tx,ty)
    local real mhorispeed = GetStoredReal(udg_gamecache,updatetimerstring,"speed")
    local integer ticksleft = 1+R2I(dist/mhorispeed/dt)
    local real hitheight = GetStoredReal(udg_gamecache,updatetimerstring,"hitheight")
    local real targetdheight = hitheight-mheight+theight
    local real vppt = GetStoredReal(udg_gamecache,updatetimerstring,"vppt")
    local real vpptpt = (targetdheight - vppt*ticksleft)/ticksleft/ticksleft
    local real newvppt = vppt + vpptpt
    local real dx = (tx - mx)/ticksleft
    local real dy = (ty - my)/ticksleft
    local real newmx = mx + dx
    local real newmy = my + dy
    local string endfunc
    local boolean b
    set mheight = mheight + newvppt
    call StoreReal(udg_gamecache,updatetimerstring,"vppt",newvppt)
    call Msg("SmartNolookMissileUpdate")
    if IsPointInRegion(udg_playground,newmx,newmy) then
        set b = true
    endif
    if b then
        call SetUnitCor(missile,newmx,newmy)
    endif
    if ticksleft == 1 or not b then
        call Msg("SmartNolookMissileEnd")
        set mheight = hitheight
        set endfunc = GetStoredString(udg_gamecache,updatetimerstring,"endfunc")
        call PauseTimer(updatetimer)
        call ExecuteFunc(endfunc)
        call DestroyTimer(updatetimer)
        call FlushStoredMission(udg_gamecache,updatetimerstring)
    endif
    call SetUnitFlyHeight(missile, mheight, 0)
    set missile = null
    set target = null
    set updatetimer = null
endfunction

// this is currently not being used.

function SmartCustomUpdate takes nothing returns nothing
    local timer updatetimer = GetExpiredTimer()
    local string updatefunc
    local string endfunc
    local boolean b
    set udg_tempstring = I2S(H2I(updatetimer))
    set updatefunc = GetStoredString(udg_gamecache,udg_tempstring,"updatefunc")
    set udg_tempreals[0] = 0.02
    set udg_tempunit = I2Unit(GetStoredInteger(udg_gamecache,udg_tempstring,"missile"))
    set udg_tempunit2 = I2Unit(GetStoredInteger(udg_gamecache,udg_tempstring,"target"))
    set udg_tempreals[1] = GetStoredReal(udg_gamecache,udg_tempstring,"mx")
    set udg_tempreals[2] = GetStoredReal(udg_gamecache,udg_tempstring,"my")
    set udg_tempreals[3] = GetWidgetX(udg_tempunit2)
    set udg_tempreals[4] = GetWidgetY(udg_tempunit2)
    set udg_tempreals[5] = GetUnitFlyHeight(udg_tempunit)
    set udg_tempreals[6] = GetUnitFlyHeight(udg_tempunit2)
    set udg_tempreals[7] = Distance(udg_tempreals[1],udg_tempreals[2],udg_tempreals[3],udg_tempreals[4])
    set udg_tempreals[8] = GetStoredReal(udg_gamecache,udg_tempstring,"speed")
    set udg_tempreals[9] = udg_tempreals[8]*udg_tempreals[0]
    set udg_tempint = 1+R2I(udg_tempreals[7]/udg_tempreals[9]) 
    set udg_tempreals[10] = GetStoredReal(udg_gamecache,udg_tempstring,"hitheight")
    set udg_tempreals[11] = udg_tempreals[10]-udg_tempreals[5]+udg_tempreals[6]
    set udg_tempreals[12] = GetStoredReal(udg_gamecache,udg_tempstring,"vppt")
    set udg_tempreals[13] = (udg_tempreals[11] - udg_tempreals[12]*udg_tempint)/udg_tempint/udg_tempint
    set udg_tempreals[14] = udg_tempreals[12] + udg_tempreals[13]
    set udg_tempreals[15] = (udg_tempreals[3] - udg_tempreals[1])/udg_tempint
    set udg_tempreals[16] = (udg_tempreals[4] - udg_tempreals[2])/udg_tempint
    set udg_tempreals[1] = udg_tempreals[1] + udg_tempreals[15]
    set udg_tempreals[2] = udg_tempreals[2] + udg_tempreals[16]
    set udg_tempreals[5] = udg_tempreals[5] + udg_tempreals[14]
    call StoreReal(udg_gamecache,udg_tempstring,"vppt",udg_tempreals[14])
    //call Msg("SmartMissile3Update")
    if IsPointInRegion(udg_playground,udg_tempreals[1],udg_tempreals[2]) then
        set b = true
    endif
    if udg_tempint == 1 or not b then
        call Msg("SmartMissile3End")
        set udg_tempreals[5] = udg_tempreals[10]
        set endfunc = GetStoredString(udg_gamecache,udg_tempstring,"endfunc")
        call ExecuteFunc(endfunc)
        call PauseTimer(updatetimer)
        call DestroyTimer(updatetimer)
        call FlushStoredMission(udg_gamecache,udg_tempstring)
    endif
    call SetUnitFlyHeight(udg_tempunit, udg_tempreals[5], 0)
    if b then
        call ExecuteFunc(updatefunc)
        call SetUnitCor(udg_tempunit,udg_tempreals[1],udg_tempreals[2])
        call StoreReal(udg_gamecache,udg_tempstring,"mx",udg_tempreals[1])
        call StoreReal(udg_gamecache,udg_tempstring,"my",udg_tempreals[2])
    endif
    set updatetimer = null
endfunction

function StartSmartFlight takes unit missile, unit target, real hitheight, real aoa, real h0, real speed, string endfunc, boolean lookat, string updatefunc returns timer
    local timer t = CreateTimer()
    local string ts = I2S(H2I(t))
    local real dt = 0.02
    call Msg("setting aoa to: "+R2S(aoa))
    call SetUnitFlyHeight(missile,h0,0)
    call StoreInteger(udg_gamecache,ts,"missile",H2I(missile))
    call StoreInteger(udg_gamecache,ts,"target",H2I(target))
    call StoreReal(udg_gamecache,ts,"hitheight",hitheight)
    call StoreReal(udg_gamecache,ts,"vppt",Sin(aoa)*speed*dt)
    call StoreReal(udg_gamecache,ts,"taoa",-aoa)
    call StoreReal(udg_gamecache,ts,"speed",speed)
    call StoreString(udg_gamecache,ts,"endfunc",endfunc)
    if lookat then
        call TimerStart(t,dt,true,function SmartMissileUpdate)
    else
        if updatefunc == null then
            call TimerStart(t,dt,true,function SmartUnitUpdate)
        else
        call StoreString(udg_gamecache,ts,"updatefunc",updatefunc)
        call TimerStart(t,dt,true,function SmartCustomUpdate)
        endif
    endif
    return t
endfunction

function SmartRocketFilter takes nothing returns boolean
    return TargetTypeCondition(GetFilterUnit(),udg_tempunit,5)
endfunction

function SmartRocketUpdate takes nothing returns nothing
    local timer Timer = GetExpiredTimer()
    local string TimerString = I2S(H2I(Timer))
    local unit Missile = I2Unit(GetStoredInteger(udg_gamecache,TimerString,"missile"))
    local unit Target = I2Unit(GetStoredInteger(udg_gamecache,TimerString,"target"))
    local real dt = 0.02
    local real MX = GetWidgetX(Missile)
    local real MY = GetWidgetY(Missile)
    local real TX = GetWidgetX(Target)
    local real TY = GetWidgetY(Target)
    local real Dist = Distance(MX,MY,TX,TY)
    local real HitHeight = GetStoredReal(udg_gamecache,TimerString,"hitheight")
    local real oldMHeight = GetUnitFlyHeight(Missile)
    local real THeight = GetUnitFlyHeight(Target)
    
    local real Speed = GetStoredReal(udg_gamecache,TimerString,"speed")
    local real oldAoA = GetStoredReal(udg_gamecache,TimerString,"aoa")
    local real oldFacing = GetStoredReal(udg_gamecache,TimerString,"facing")
    local real TAoA = Angle(0,oldMHeight,Dist,THeight+HitHeight)
    local real TFacing = Angle(MX,MY,TX,TY)
    local real TdAoA = TAoA-oldAoA
    local real TdFacing = TFacing-oldFacing
    local real SteerAngle
    local real SteerSpeed = GetStoredReal(udg_gamecache,TimerString,"steerspeed")
    local real dAoA
    local real dFacing
    local real newAoA
    local real newFacing
    local real dHeight
    local real newMHeight
    local real HoriSpeed
    local real dX
    local real dY
    local group G = CreateGroup()
    local real radius = 40
    local string endfunc
    
    if not IsPointInRegion(udg_playground,MX+dX,MY+dY) then    
        call Msg("point not in region bug")
    endif
    
    if TdAoA > bj_PI then
        set TdAoA = TdAoA-2*bj_PI
    else
        if TdAoA < -bj_PI then
            set TdAoA = TdAoA+2*bj_PI
        endif
    endif
    if TdFacing > bj_PI then
        set TdFacing = TdFacing-2*bj_PI
    else
        if TdFacing < -bj_PI then
            set TdFacing = TdFacing+2*bj_PI
        endif
    endif
    set SteerAngle = Atan2(TdAoA,-TdFacing)
    set dAoA = SteerSpeed*Sin(SteerAngle)
    set dFacing = SteerSpeed*-Cos(SteerAngle)
    if dFacing > 0 then
        if dFacing > TdFacing then
            set dFacing = TdFacing
        endif
    else
        if dFacing < TdFacing then
            set dFacing = TdFacing
        endif
    endif
    if dAoA > 0 then
        if dAoA > TdAoA then
            set dAoA = TdAoA
        endif
    else
        if dAoA < TdAoA then
            set dAoA = TdAoA
        endif
    endif
    set newAoA = oldAoA+dAoA
    set newFacing = oldFacing+dFacing
    set dHeight = Speed*dt*Sin(newAoA)
    set newMHeight = oldMHeight + dHeight
    set HoriSpeed = Speed*Cos(newAoA)
    set dX = dt * HoriSpeed * Cos(newFacing)
    set dY = dt * HoriSpeed * Sin(newFacing)
    
    if newAoA > bj_PI then
        set newAoA = newAoA-2*bj_PI
    else
        if newAoA < -bj_PI then
            set newAoA = newAoA+2*bj_PI
        endif
    endif
    if newFacing > bj_PI then
        set newFacing = newFacing-2*bj_PI
    else
        if newFacing < -bj_PI then
            set newFacing = newFacing+2*bj_PI
        endif
    endif
    
//    call Msg("SmartRocketUpdate")
//    call Msg("oldAoA: "+R2S(oldAoA))
//    call Msg("oldFacing: "+R2S(oldFacing))
//    call Msg("TAoA: "+R2S(TAoA))
//    call Msg("TFacing: "+R2S(TFacing))
//    call Msg("TdAoA: "+R2S(TdAoA))
//    call Msg("TdFacing: "+R2S(TdFacing))
//    call Msg("SteerAngle: "+R2S(SteerAngle))
//    call Msg("SteerSpeed: "+R2S(SteerSpeed))
//    call Msg("dAoA: "+R2S(dAoA))
//    call Msg("dFacing: "+R2S(dFacing))
//    call Msg("newAoA: "+R2S(newAoA))
//    call Msg("newFacing: "+R2S(newFacing))

    set udg_tempunit = Missile
    call GroupEnumUnitsInRange(G,MX,MY,radius,Condition(function SmartRocketFilter))
    
    //call SetUnitLookAt(Missile,"bone_chest",Missile,1000*dX,1000*dY,1000*dHeight)
    call SetUnitLookAt(Missile,"bone_chest",Missile,0,0,1000*dHeight)
    
    //if FirstOfGroup(G) != null or not IsPointInRegion(udg_playground,MX+dX,MY+dY) then
    if FirstOfGroup(G) != null then
        call Msg("HomingRocketEnd")
        set newMHeight = HitHeight
        call SetUnitCor(Missile,TX,TY)
        call SetUnitFlyHeight(Missile, newMHeight, 0)
        set udg_tempunit = FirstOfGroup(G)
        set udg_tempunit2 = Missile
        set udg_tempstring = TimerString
        set endfunc = GetStoredString(udg_gamecache,TimerString,"endfunc")
        call ExecuteFunc(endfunc)
        call PauseTimer(Timer)
        call DestroyTimer(Timer)
        call FlushStoredMission(udg_gamecache,TimerString)
    else
        call SetUnitFacing(Missile,newFacing*bj_RADTODEG)
        call StoreReal(udg_gamecache,TimerString,"AoA",newAoA)
        call StoreReal(udg_gamecache,TimerString,"facing",newFacing)
        call SetUnitCor(Missile, MX+dX, MY+dY)
        call SetUnitFlyHeight(Missile, newMHeight, 0)
    endif
    call DestroyGroup(G)
    set G = null
    set Missile = null
    set Target = null
    set Timer = null
endfunction

function StartRocket takes unit missile, unit target, real hitheight, real aoa, real h0, real speed, string endfunc, real steerspeed, real facing returns timer
    local timer t = CreateTimer()
    local string ts = I2S(H2I(t))
    local real dt = 0.02
    call Msg("setting aoa to: "+R2S(aoa))
    call Msg("setting steerspeed to: "+R2S(steerspeed))
    call Msg("setting facing to: "+R2S(facing*bj_RADTODEG))
    call SetUnitFlyHeight(missile,h0,0)
    call StoreInteger(udg_gamecache,ts,"missile",H2I(missile))
    call StoreInteger(udg_gamecache,ts,"target",H2I(target))
    call StoreReal(udg_gamecache,ts,"hitheight",hitheight)
    call StoreReal(udg_gamecache,ts,"aoa",aoa)
    call StoreReal(udg_gamecache,ts,"speed",speed)
    call StoreString(udg_gamecache,ts,"endfunc",endfunc)
    call StoreReal(udg_gamecache,ts,"steerspeed",steerspeed)
    call StoreReal(udg_gamecache,ts,"facing",facing)
    call TimerStart(t,dt,true,function SmartRocketUpdate)
    return t
endfunction

//====================================================================================================================
//Flood
function FloodHits takes nothing returns nothing
    local unit target = GetTriggerUnit()
    local unit caster = GetEventDamageSource()
    local real dayduration = 5
    local string casters = I2S(H2I(caster))
    local group g = I2Group(GetStoredInteger(udg_gamecache,casters,"floodgroup"))
    local unit hero = I2Unit(GetStoredInteger(udg_gamecache,casters,"floodhero"))
    local real slow = 120 * GetHeroAbilityLevel(hero,0) / GetHeroLevel(hero)
    local real nightduration = 10
    local real duration
    //debug
    call Msg(R2S(slow))
    //debugend
    if udg_day then
        set duration = dayduration
    else
        set duration = nightduration
    endif
    if not IsUnitInGroup(target,g) then
        call GroupAddUnit(g,target)
        call Msg("unitdmgedbyflood")
        call Addbuff(target,4,duration)
        call Slow(target,slow,duration)
    endif
    set target = null
    set caster = null
    set hero = null
    set g = null
endfunction

function FloodCast takes nothing returns nothing
    local unit hero = GetTriggerUnit()
    local unit heroclone = GetHandleUnit(hero,"clone")
    local real facing = GetUnitFacing(hero)
    local real x = GetWidgetX(hero)
    local real y = GetWidgetY(hero)
    local real delay = 1
    local string casterstring
    local unit caster
    local group g = CreateGroup()
    local player p = GetTriggerPlayer()
    local real casttime = 1.1
    local integer floodforbid = GetHandleInt(hero,"floodforbid")
    if floodforbid > 0 then
        call SetHandleInt(hero,"floodforbid",floodforbid-1)
        call Msg("floodfakecast")
    else
        if heroclone != null then
            call SetHandleInt(heroclone,"floodforbid",GetHandleInt(heroclone,"floodforbid")+1)
            call IssueImmediateOrder(heroclone, "taunt")
        endif
        set caster = CreateUnit(p,udg_dummyunittypes[23],x+900*CosBJ(facing),y+900*SinBJ(facing),facing+180)
        call IssuePointOrder(caster,"carrionswarm",x+300*CosBJ(facing),y+300*SinBJ(facing))
        set casterstring = I2S(H2I(caster))
        call StoreInteger(udg_gamecache,casterstring,"floodgroup",H2I(g))
        call StoreInteger(udg_gamecache,casterstring,"floodhero",H2I(hero))
        call Msg("floodcast")
    endif    
    call IssueImmediateOrder(hero,"stop")
    call TriggerSleepAction(0)
    call PauseUnit(hero,true)
    if udg_day then
        call SetUnitAnimationByIndex(hero,4)
    else
        call SetUnitAnimationByIndex(hero,3)
    endif
    call TriggerSleepAction(casttime)
    call ResetUnitAnimation(hero)
    call PauseUnit(hero,false)
    if floodforbid == 0 then
        call ShowUnitHide(caster)
        call TriggerSleepAction(delay)
        call DestroyGroup(g)
        call RemoveUnit(caster)
        call FlushStoredMission(udg_gamecache,casterstring)
    endif
    set hero = null
    set p = null
    set heroclone = null
    set g = null
    set caster = null
endfunction

//Moon Crave
function MoonCraveCast takes nothing returns nothing
    local unit hero = GetTriggerUnit()
    local integer scale = R2I(5 * (1+8*I2R(GetUnitAbilityLevel(hero,udg_habils[49])) / I2R(GetHeroLevel(hero))))
    local real duration = 30
    call DisplayTextToPlayer(Player(0),0,0,"mooncravecast")
    call SetTimeOfDayScale(GetTimeOfDayScale()+I2R(scale)/10)
    call TriggerSleepAction(duration)
    call SetTimeOfDayScale(GetTimeOfDayScale()-I2R(scale)/10)
    set hero = null
endfunction

//Cannibalize
function CannibalizeHits takes nothing returns nothing
    local unit target = GetTriggerUnit()
    local unit hero = GetEventDamageSource()
    local integer dmg = R2I(GetEventDamage())
    local integer lifesteal = 2 * GetHeroAbilityLevel(hero,1)
    local integer manasteal = 2 * GetHeroAbilityLevel(hero,1)
    local integer targetmana
    if lifesteal > dmg then
        set lifesteal = dmg
    endif
    call Msg("canihits")
    call SetUnitState(hero, UNIT_STATE_LIFE, GetUnitState(hero, UNIT_STATE_LIFE) + lifesteal)
    if not udg_day then
        set targetmana = R2I(GetUnitState(target,UNIT_STATE_MANA))
        if manasteal > targetmana then
            set manasteal = targetmana
        endif
        call Msg("manasteal = "+I2S(manasteal))
        call SetUnitState(hero, UNIT_STATE_MANA, GetUnitState(hero, UNIT_STATE_MANA) + manasteal)
        call SetUnitState(target, UNIT_STATE_MANA, targetmana - manasteal)
    endif
    set target = null
    set hero = null
endfunction

//Scizofrenia
function ScizofreniaCast takes nothing returns nothing
    local unit hero = GetTriggerUnit()
    local player p = GetOwningPlayer(hero)
    local string heros = I2S(H2I(hero))
    local string ps = I2S(H2I(p))
    call StoreBoolean(udg_gamecache,ps,"scizcast",true)
    call ExplodeUnitBJ(I2Unit(GetStoredInteger(udg_gamecache,heros,"clone")))
    call FlushStoredInteger(udg_gamecache,heros,"clone")
    call StoreInteger(udg_gamecache,ps,"lunatic",H2I(hero))
    call DisplayTextToPlayer(Player(0),0,0,"scizocast")
endfunction

function ScizofreniaArrive takes nothing returns nothing
    local integer levelcount = 0
    local unit illusion = GetTriggerUnit()
    local unit lunatic
    local player p = GetOwningPlayer(illusion)
    local string ps = I2S(H2I(p))
    local real delay = 0
    local integer index
    local item    indexItem
    local real oldRatio
    local integer ias
    local integer dmg
    local integer haste
    local integer heritagelevel
    local string hs
    local unit newlunatic
    //local boolean wasHidden
    local real time = GetTimeOfDay()
    if IsUnitIllusion(illusion) == true then
        if GetStoredBoolean(udg_gamecache,ps,"scizcast") then
            call StoreBoolean(udg_gamecache,ps,"scizcast",false)

            set lunatic = I2Unit(GetStoredInteger(udg_gamecache,ps,"lunatic"))

            call ShowUnit(illusion, false)
            if udg_day then
                set newlunatic = CreateUnit(p, udg_herotypes[0], GetUnitX(illusion), GetUnitY(illusion), GetUnitFacing(illusion))
            else
                set newlunatic = CreateUnit(p, udg_unittypes[2], GetUnitX(illusion), GetUnitY(illusion), GetUnitFacing(illusion))
            endif
            //could cause problems.
            call RemoveUnit(illusion)          
            
            set oldRatio = GetUnitState(lunatic, UNIT_STATE_LIFE) / GetUnitState(lunatic, UNIT_STATE_MAX_LIFE)
            call SetUnitState(newlunatic, UNIT_STATE_LIFE, oldRatio * GetUnitState(newlunatic, UNIT_STATE_MAX_LIFE))
            set oldRatio = GetUnitState(lunatic, UNIT_STATE_MANA) / GetUnitState(lunatic, UNIT_STATE_MAX_MANA)
            call SetUnitState(newlunatic, UNIT_STATE_MANA, oldRatio * GetUnitState(newlunatic, UNIT_STATE_MAX_MANA))
            call SetResourceAmount(newlunatic, GetResourceAmount(lunatic))
            call SetHeroXP(newlunatic, GetHeroXP(lunatic), false)
            call SetHeroInt(newlunatic,GetHeroInt(lunatic,false),true)
            call SetHeroAgi(newlunatic,GetHeroAgi(lunatic,false),true)
            call SetHeroStr(newlunatic,GetHeroStr(lunatic,false),true)
            set index = 0
            loop
                set indexItem = UnitItemInSlot(lunatic, index)
                if (indexItem != null) then
                    call UnitRemoveItem(lunatic, indexItem)
                    call UnitAddItem(newlunatic, indexItem)
                endif
                set index = index + 1
                exitwhen index >= bj_MAX_INVENTORY
            endloop
            call SetHandleHandle(newlunatic,"clone",lunatic)
            call SetHandleHandle(lunatic,"clone",newlunatic)
            if not udg_day then
                set heritagelevel = GetUnitAbilityLevel(lunatic,udg_habils[3])
                set hs = I2S(H2I(newlunatic))
                set ias = 10 * heritagelevel
                set dmg = 20 * heritagelevel
                set haste = 80 * heritagelevel / GetHeroLevel(newlunatic)
                call ChangeBonus(newlunatic,dmg,0,true)
                call ChangeBonus(newlunatic,ias,1,true)
                call SetUnitMoveSpeed(newlunatic,GetUnitMoveSpeed(newlunatic)+haste)
                call StoreBoolean(udg_gamecache,hs,"morphdone",true)
                call StoreReal(udg_gamecache,hs,"heritagehaste",haste)
                call StoreInteger(udg_gamecache,hs,"heritagedmg",dmg)
                call StoreInteger(udg_gamecache,hs,"heritageias",ias)
            endif
            set index = 0
            loop
                set levelcount = GetHeroAbilityLevel(lunatic, index)
                loop
                    exitwhen levelcount == 0
                    call SelectHeroSkill(newlunatic, udg_habils[index])
                    set levelcount = levelcount - 1
                endloop
                exitwhen index == 3
                set index = index + 1
            endloop
            set levelcount = GetUnitAbilityLevel(lunatic, udg_habils[49])
            loop
                exitwhen levelcount == 0
                call SelectHeroSkill(newlunatic, udg_habils[49])
                set levelcount = levelcount - 1
            endloop
            call CastCorAbility(p, 3, 1,0,0,0)
            call CastWidgetAbilityCor(p, 2, 1, newlunatic, 0, GetWidgetX(newlunatic), GetWidgetY(newlunatic), 0)
            call TriggerSleepAction(delay)
            call UnitRemoveAbility(newlunatic, udg_buffs[0])
            set newlunatic = null
            set lunatic = null
        else
            call RemoveUnit(illusion)
        endif
    endif
    set illusion = null
    set p = null
endfunction

function ScizofreniaSelect takes nothing returns nothing
    local unit hero = GetTriggerUnit()
    local player p = GetTriggerPlayer()
    local real delay = 0
    call CastCorAbility(p, 3, 1,0,0,0)
    call TriggerSleepAction(delay)
    if GetUnitAbilityLevel(GetHandleUnit(hero,"clone"),udg_buffs[0]) == 1 then
        call UnitRemoveBuffBJ(udg_buffs[0], hero)
    endif
    set hero = null
    set p = null
    call Msg("ScizofreniaSelect")
endfunction

function ScizofreniaSkillLearned takes nothing returns nothing
    local unit hero = GetTriggerUnit()
    call SelectHeroSkill(GetHandleUnit(hero,"clone"), GetLearnedSkill())
    set hero = null
endfunction

//Heritage
function HeritageCondition takes nothing returns boolean
    local unit hero = GetFilterUnit()
    if GetUnitTypeId(hero) == udg_tempint and (not GetHandleBoolean(hero,"morphdone")) then
        return true
    endif
    set hero = null
    return false
endfunction

function HeritageMorph takes nothing returns nothing
    local unit hero = GetEnumUnit()
    local string hs
    local real delay = 0.5
    local integer ias
    local integer dmg
    local effect polyeffect
    local real haste
    local group morphgroup
    local player p = GetOwningPlayer(hero)
    local integer heritagelevel = GetUnitAbilityLevel(hero,udg_habils[3])
    call Msg("heritagemorphstart")
    if heritagelevel != 0 then
        if udg_day then
            call Msg("daymorphStart")
            call UnitAddAbility(hero, udg_uabils[34])
            call TriggerSleepAction(delay)
            
            //debug. I have commented three lines because they are not working correctly and are therefore bugged.
            //The code might also work without these three lines, and the bug will disappear.   
                    
            //set udg_tempint = udg_herotypes[0]
            //set morphgroup = GetUnitsOfPlayerMatching(p,Condition(function HeritageCondition))
            //set hero = GroupPickRandomUnit(morphgroup)
    
            //debugend        
            set hs = I2S(H2I(hero))
            call StoreBoolean(udg_gamecache,hs,"morphdone",true)
            set ias = GetStoredInteger(udg_gamecache,hs,"heritageias")
            set dmg = GetStoredInteger(udg_gamecache,hs,"heritagedmg")
            set haste = GetStoredReal(udg_gamecache,hs,"heritagehaste")
            call ChangeBonus(hero,-dmg,0,true)
            call ChangeBonus(hero,-ias,1,true)
            call SetUnitMoveSpeed(hero,GetUnitMoveSpeed(hero)-haste)
            call SetPlayerAbilityAvailable(p,udg_habils[49],true)
            call Msg("daymorphEns")
        else
            call Msg("nightmorphStart")
            call UnitAddAbility(hero, udg_uabils[46])
            call TriggerSleepAction(delay)
            call Msg(GetUnitName(hero))
            
            //debug. I have commented three lines because they are not working correctly and are therefore bugged.
            //The code might also work without these three lines, and the bug will disappear.
            
            //set udg_tempint = udg_unittypes[2]
            //set morphgroup = GetUnitsOfPlayerMatching(p,Condition(function HeritageCondition))
            //set hero = GroupPickRandomUnit(morphgroup)
            
            //debugend
            set hs = I2S(H2I(hero))
            set ias = 10 * heritagelevel
            set dmg = 20 * heritagelevel
            set haste = 320 * heritagelevel / GetHeroLevel(hero)
            call ChangeBonus(hero,dmg,0,true)
            call ChangeBonus(hero,ias,1,true)
            call SetUnitMoveSpeed(hero,GetUnitMoveSpeed(hero)+haste)
            call StoreBoolean(udg_gamecache,hs,"morphdone",true)
            call StoreReal(udg_gamecache,hs,"heritagehaste",haste)
            call StoreInteger(udg_gamecache,hs,"heritagedmg",dmg)
            call StoreInteger(udg_gamecache,hs,"heritageias",ias)
            call SetPlayerAbilityAvailable(p,udg_habils[49],false)                     
            set ias = GetStoredInteger(udg_gamecache,hs,"heritageias")
            set dmg = GetStoredInteger(udg_gamecache,hs,"heritagedmg")
            set haste = GetStoredReal(udg_gamecache,hs,"heritagehaste")
            call Msg("ias = "+I2S(ias))
            call Msg("dmg = "+I2S(dmg))
            call Msg("haste = "+R2S(haste)) 
            call Msg("EndHeroname = "+GetUnitName(hero))      
            call Msg("nightmorphEnd")
        endif
    endif
    set hero = null
endfunction

function HeritageMorphWrapper takes nothing returns nothing
    call ExecuteFunc("HeritageMorph")
endfunction

function HeritageFall takes nothing returns nothing
    local group g = GetUnitsOfTypeIdAll(udg_herotypes[0])
    call Msg("heritagefall")
    call ForGroup(g, function HeritageMorphWrapper)
    call DestroyGroup(g)
    set g = null
endfunction

function HeritageRise takes nothing returns nothing
    local group g = GetUnitsOfTypeIdAll(udg_unittypes[2])
    call Msg("heritagerise")
    call ForGroup(g, function HeritageMorphWrapper)
    call DestroyGroup(g)
    set g = null
endfunction

//=====================================================================================================================
//Anger
function AngerEnd takes nothing returns nothing
    local timer endtimer = GetExpiredTimer()
    local timer moveupdatetimer = GetHandleTimer(endtimer,"moveupdatetimer")
    local timer explosiontimer = GetHandleTimer(endtimer,"explosiontimer")
    local unit hero = GetHandleUnit(moveupdatetimer,"hero")
    call PauseTimer(moveupdatetimer)
    call PauseTimer(explosiontimer)
    call DestroyTimer(endtimer)
    call DestroyTimer(moveupdatetimer)
    call DestroyTimer(explosiontimer)
    call UnitRemoveAbilityBJ('Avul',hero)
    call ResetUnitAnimation(hero)
    call GroupRemoveUnit(udg_busyunits,hero)
    set endtimer = null
    set moveupdatetimer = null
    set explosiontimer = null
    set hero = null
endfunction

function AngerExplosion takes nothing returns nothing
    local timer explosiontimer = GetExpiredTimer()
    local unit hero = GetHandleUnit(explosiontimer,"hero")
    local real x = GetWidgetX(hero)
    local real y = GetWidgetY(hero)
    local unit explosion = CreateUnit(Player(15), udg_dummyunittypes[1], x, y, 0)
    local real delay = 1.00
    local real radius = 100
    local real wait = 2
    local integer dmg = 30 * GetHeroAbilityLevel(hero, 4)
    local effect flameeffect = AddSpecialEffect("Doodads\\Cinematic\\FirePillarMedium\\FirePillarMedium.mdl",x,y)
    call DestroyEffectWait(flameeffect,delay)
    call SetUnitAnimationByIndex(explosion, 0)
    call UnitDamageArea(hero, x, y, radius, 17409, dmg, 2, 0, 0)
    call TriggerSleepAction(delay)
    call RemoveUnit(explosion)
    set flameeffect = null
    set explosion = null
    set hero = null
    set explosiontimer = null
endfunction

function AngerMoveUpdate takes nothing returns nothing
    local timer moveupdatetimer = GetExpiredTimer()
    local string moveupdatetimerstring = I2S(H2I(moveupdatetimer))
    local unit hero = I2Unit(GetStoredInteger(udg_gamecache,moveupdatetimerstring,"hero"))
    local real dx = GetStoredReal(udg_gamecache,moveupdatetimerstring,"dx")
    local real dy = GetStoredReal(udg_gamecache,moveupdatetimerstring,"dy")
    call MoveUnit(hero, dx, dy)
    set moveupdatetimer = null
    set hero = null
endfunction

function AngerCast takes nothing returns nothing
    local unit hero = GetTriggerUnit()
    local real herox = GetWidgetX(hero)
    local real heroy = GetWidgetY(hero)
    local location spellloc = GetSpellTargetLoc()
    local real spellx = GetLocationX(spellloc)
    local real spelly = GetLocationY(spellloc)
    local real velocity = 50
    local real dt = 0.02
    local real explosionT = 0.03
    local string temps
    local real facing = Angle(herox, heroy, spellx, spelly)
    local timer moveupdatetimer
    local timer explosiontimer
    local timer angerendtimer
    local real wait = 0.4
    call SetUnitFacing(hero, facing*bj_RADTODEG)
    call TriggerSleepAction(0)
    call SetUnitAnimationByIndex(hero, 8)
    if not IsUnitInGroup(hero,udg_busyunits) then
        call GroupAddUnit(udg_busyunits,hero) 
        call DisplayTextToPlayer(Player(0),0,0,"angercast")
        call TriggerSleepAction(wait)  
        set moveupdatetimer = CreateTimer()
        set explosiontimer = CreateTimer()
        set angerendtimer = CreateTimer()
        set temps = I2S(H2I(angerendtimer))
        call StoreInteger(udg_gamecache,temps,"moveupdatetimer",H2I(moveupdatetimer))
        call StoreInteger(udg_gamecache,temps,"explosiontimer",H2I(explosiontimer))
        set temps = I2S(H2I(moveupdatetimer))
        call StoreInteger(udg_gamecache,temps,"hero",H2I(hero))
        call SetHandleHandle(explosiontimer,"hero",hero)
        call StoreReal(udg_gamecache,temps,"dx",velocity*Cos(facing))
        call StoreReal(udg_gamecache,temps,"dy",velocity*Sin(facing))
        call UnitAddAbilityBJ('Avul',hero)    
        call TimerStart(moveupdatetimer, dt, true, function AngerMoveUpdate)
        call TimerStart(explosiontimer, explosionT, true, function AngerExplosion)
        call TimerStart(angerendtimer, Distance(herox, heroy, spellx, spelly) * dt / velocity, false, function AngerEnd)
        set moveupdatetimer = null
        set explosiontimer = null
        set angerendtimer = null
    endif
    set hero = null
endfunction

//Ignite
function IgniteDot takes nothing returns nothing
    local unit subject = udg_tempunit
    local unit target = udg_tempunit2
    local integer dmg = udg_tempint
    local real duration = udg_tempreal
    local real interval = udg_tempreal2
    local real r = 0
    loop
        exitwhen r > duration
        call SetHandleBoolean(subject,"igniteburns",true)
        call UnitDamageTargetBJ(subject,target,dmg,ATTACK_TYPE_CHAOS,DAMAGE_TYPE_UNIVERSAL)
        set r = r + interval
        call TriggerSleepAction(interval)
    endloop
    set subject = null
    set target = null
endfunction

function IgniteHits takes nothing returns nothing
    local unit target = GetTriggerUnit()
    local unit hero = GetEventDamageSource()
    local real haste = 50
    local real duration = 3
    local integer dmg = 20 * GetHeroAbilityLevel(hero, 5) / GetHeroLevel(hero)
    local real interval = 1
    local string targetstring = I2S(H2I(target))
    local integer burntime = GetStoredInteger(udg_gamecache,targetstring,"burntime")
    call UnitRemoveAbility(target, udg_buffs[4])
    if burntime == 0 then
        call Addbuff(target,6,-1)
    endif
    call StoreInteger(udg_gamecache,targetstring,"burntime",burntime+1)
    call Slow(target,-haste,duration)
    call DisplayTextToPlayer(Player(0),0,0,"ignitehit")
    call TriggerSleepAction(0)
    set udg_tempunit = hero
    set udg_tempunit2 = target
    set udg_tempint = dmg
    set udg_tempreal = duration
    set udg_tempreal2 = interval
    call ExecuteFunc("IgniteDot")   
    call TriggerSleepAction(duration)
    set burntime = GetStoredInteger(udg_gamecache,targetstring,"burntime")
    if burntime == 1 then
        call UnitRemoveAbility(target, udg_showbuffs[6])
    endif
    call StoreInteger(udg_gamecache,targetstring,"burntime",burntime-1)
    set target = null
    set hero = null
endfunction

//Concentrate
function ConcentrateEnd takes nothing returns nothing
    local real delay = 1.1
    local unit hero = udg_tempunit
    local string herostring = I2S(H2I(hero))
    local timer updatetimer = I2Timer(GetStoredInteger(udg_gamecache,herostring,"concentrateupdatetimer"))
    if updatetimer != null then
        call FlushStoredInteger(udg_gamecache,herostring,"concentrateupdatetimer")
        call PauseTimer(updatetimer)
        call DestroyTimer(updatetimer)
        call SetUnitTimeScalePercent(hero, 100.00)
        call DisplayTextToPlayer(Player(0),0,0,"concentrateEnd")
        call IssueImmediateOrder(hero,"stop")
    endif
    set updatetimer = null
    set hero = null
endfunction

function ConcentrateUpdate takes nothing returns nothing
    local timer updatetimer = GetExpiredTimer()
    local unit hero = GetHandleUnit(updatetimer,"hero")
    local string herostring = I2S(H2I(hero))
    local integer duration = 120
    local integer bonus
    local integer dmg = GetHeroAbilityLevel(hero,6)
    local integer concentratedamage = GetStoredInteger(udg_gamecache,herostring,"concentratedamage")
    local integer concentratedamagemax = 100*GetHeroAbilityLevel(hero,6)
    if concentratedamage >= concentratedamagemax then
        set udg_tempunit = hero
        call ExecuteFunc("ConcentrateEnd")
    else
        call StoreInteger(udg_gamecache,herostring,"concentratedamage",concentratedamage + dmg)
        call ChangeBonus(hero, dmg, 0, true)
    endif
    set updatetimer = null
    set hero = null
endfunction

function ConcentrateCast takes nothing returns nothing
    local unit hero = GetTriggerUnit()
    local timer updatetimer = CreateTimer()
    local real anispeed = 200
    local real speed = 0.01
    local real duration = 3
    local real delay = 1.6
    call SetHandleHandle(updatetimer,"hero",hero)
    call SetHandleHandle(hero,"concentrateupdatetimer",updatetimer)
    call SetUnitTimeScalePercent(hero, anispeed)
    call TriggerSleepAction(delay)
    call SetUnitTimeScalePercent(hero, 0.00)
    call TimerStart(updatetimer, speed, true, function ConcentrateUpdate)
    set updatetimer = null
    set hero = null
    call Msg("concentratecast")
endfunction

function ConcentrateHits takes nothing returns nothing
    local unit subject = GetTriggerUnit()
    local unit hero = GetEventDamageSource()
    local texttag tag
    local integer dmg = R2I(GetEventDamage())
    local real duration = 1
    local real concentratedamage = I2R(GetHandleInt(hero,"concentratedamage"))
    local real tagheight = 0
    local real tagsize = 10
    call Msg("concentratehits")
    set tag = CreateTextTag()
    call SetTextTagPosUnit(tag, hero, tagheight)
    call SetTextTagColor(tag,255,0,0,0)
    call Msg(I2S(dmg))
    call SetTextTagText(tag,I2S(dmg)+"!",TextTagSize2Height(tagsize))
    call SetHandleInt(hero,"concentratedamage",0)
    call ChangeBonus(hero, -concentratedamage, 0, true)
    call TriggerSleepAction(duration)
    call DestroyTextTag(tag)
    set tag = null
    set subject = null
    set hero = null
endfunction

//Burnout
function BurnoutHeroDeath takes nothing returns nothing
    local timer herodeathtimer = GetExpiredTimer()
    local unit hero = GetHandleUnit(herodeathtimer,"hero")
    call DisplayTextToPlayer(Player(0),0,0,"burnoutherodeath")
    call DestroyTimer(herodeathtimer)
    call PauseUnit(hero,false)
    call GroupRemoveUnit(udg_busyunits,hero)  
    call SetUnitTimeScalePercent(hero, 100.00)
    call KillUnit(hero)
    set herodeathtimer = null
    set hero = null
endfunction

function BurnoutPhase2 takes nothing returns nothing
    local timer phase2timer = GetExpiredTimer()
    local unit hero = GetHandleUnit(phase2timer,"hero")
    local timer herodeathtimer = phase2timer
    local integer i = 0
    local integer i2 = 1
    local real minradius = 70
    local real maxradius = 200
    local real radius
    local real anglespeed = 10
    local real x = GetWidgetX(hero)
    local real y = GetWidgetY(hero)
    local real delay = 0.1
    local real interval = 0
    local real wait = 0.1
    local real radiusspeed = 35
    local unit array explosion
    local integer dmg = 100 * GetHeroAbilityLevel(hero, 7)
    local real delay2 = 2
    local real x2
    local real y2
    local real delay3 = 1
    local effect array flameeffect
    call PauseUnit(hero,true)
    call SetUnitTimeScalePercent(hero, 0.00)
    call Msg("burnoutphase2")
    call TriggerSleepAction(wait)
    set radius = minradius
    call TimerStart(herodeathtimer,delay,false,function BurnoutHeroDeath)
    loop
        call UnitDamageArea(hero,x,y,radius,17408,dmg,2,0,0)
        loop
            set x2 = x + Cos(anglespeed * I2R(i)) * radius
            set y2 = y + radius * Sin(anglespeed * I2R(i))
            set explosion[i] = CreateUnit(Player(15), udg_dummyunittypes[1], x2, y2, 0)
            set flameeffect[i] = AddSpecialEffect("Doodads\\Cinematic\\FirePillarMedium\\FirePillarMedium.mdl",x2,y2)
            call SetUnitAnimationByIndex(explosion[i], 0)
            set i = i + 1
            exitwhen I2R(i) * anglespeed >= 360*i2
        endloop
        exitwhen radius >= maxradius
        set radius = radius + radiusspeed
        set i2 = i2+1
    endloop
    call TriggerSleepAction(delay2)
    set i = 0
    loop
        exitwhen explosion[i] == null
        call RemoveUnit(explosion[i])
        call DestroyEffectWait(flameeffect[i],delay3)
        set flameeffect[i] = null
        set explosion[i] = null
        set i = i + 1
    endloop
    call DisplayTextToPlayer(Player(0),0,0,"burnoutend")
    set hero = null
    set phase2timer = null
    set herodeathtimer = null
endfunction

function BurnoutPhase2Wrap takes nothing returns nothing
    call ExecuteFunc("BurnoutPhase2")
endfunction

function BurnoutCast takes nothing returns nothing
    local unit hero = GetTriggerUnit()
    local timer phase2timer = CreateTimer()
    local real delay = 0.4
    call TriggerSleepAction(0)
    call SetHandleHandle(phase2timer,"hero",hero)
    call SetUnitAnimationByIndex(hero,4)
    call DisplayTextToPlayer(Player(0),0,0,"burnoutcast")
    if not IsUnitInGroup(hero,udg_busyunits) then
        call GroupAddUnit(udg_busyunits,hero)     
        call TimerStart(phase2timer,delay,false,function BurnoutPhase2Wrap)
    endif
    set hero = null
    set phase2timer = null
endfunction

//====================================================================================================================
//HopAStrike
function HopastrikeEnd takes timer t, unit hero, unit target returns nothing
    local integer dmg = 100 * GetHeroAbilityLevel(hero, 8)
    local texttag tag = CreateTextTagUnitBJ(I2S(dmg) + "!", hero, 0, 10, 100, 0, 0, 0)
    local real delay = 1
    call SetUnitFlyHeight(hero, 0, 0)
    call FlushHandleLocals(t)
    call PauseTimer(t)
    call DestroyTimer(t)
    call UnitRemoveAbility(hero, 'Avul')
    call UnitDamageTargetNew(hero, target, dmg, 2, 0, 0)
    call GroupRemoveUnit(udg_busyunits,hero)
    call DisplayTextToPlayer(Player(0),0,0,"hopastrikeend")
    call TriggerSleepAction(delay)
    call DestroyTextTag(tag)
    set tag = null
endfunction

function HopastrikeUpdate takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local string timers = I2S(H2I(t))
    local unit hero = I2Unit(GetStoredInteger(udg_gamecache,timers,"hero"))
    local unit target = I2Unit(GetStoredInteger(udg_gamecache,timers,"flytarget"))
    local integer time = (GetStoredInteger(udg_gamecache,timers,"time"))+1
    local real startspeed = 3.0
    local real dt = 0.02
    local integer endtime = 32
    local real x = GetWidgetX(hero)
    local real y = GetWidgetY(hero)
    local real x2 = GetWidgetX(target)
    local real y2 = GetWidgetY(target)
    local real facing = Angle(x, y, x2, y2)
    local real distance = 100
    local real xv = (x2 - x - Cos(facing)*distance) / I2R(endtime-time)
    local real yv = (y2 - y - Sin(facing)*distance) / I2R(endtime-time)
    local real height = udg_pointspermeter * (startspeed * time*dt - 0.5*udg_gravity*time*dt*time*dt)
    call SetUnitCor(hero, x + xv, y + yv)
    call SetUnitFacing(hero, facing*bj_RADTODEG)
    //call Msg(I2S(time))
    if height <= 0 then
        call HopastrikeEnd(t,hero,target)
    else
        call SetUnitFlyHeightBJ(hero, height, 0)
        call StoreInteger(udg_gamecache,timers,"time",time)
    endif
    set t = null
    set hero = null
    set target = null
endfunction

function HopastrikeUpdateWrap takes nothing returns nothing
    call ExecuteFunc("HopastrikeUpdate")
endfunction

function Hopastrike2 takes nothing returns nothing
    local real updatedelay = 0.02
    call TimerStart(GetExpiredTimer(), updatedelay, true, function HopastrikeUpdateWrap)
endfunction

function HopastrikeCast takes nothing returns nothing
    local unit hero = GetTriggerUnit()
    local unit target = GetSpellTargetUnit()
    local timer phase2timer = CreateTimer()
    local real delay = 0.15
    local real duration = 0.6
    local string phase2timerstring = I2S(H2I(phase2timer))    
    if not IsUnitInGroup(hero,udg_busyunits) then
        call GroupAddUnit(udg_busyunits,hero)
        call UnitAddAbilityBJ('Avul',hero)
        call StoreInteger(udg_gamecache,phase2timerstring,"flytarget",H2I(target))
        call StoreInteger(udg_gamecache,phase2timerstring,"hero",H2I(hero))
        call DisplayTextToPlayer(Player(0),0,0,"hopacast")  
        call TimerStart(phase2timer, delay, true, function Hopastrike2)
    endif
    set phase2timer = null
    set hero = null
    set target = null
endfunction

function AirformEvasion takes unit hero returns nothing
    local real empowerment = 2
    local real evasion = 100- 100/(empowerment*GetUnitAbilityLevel(hero,udg_habils[9])/GetHeroLevel(hero)+1)
    local real minlevel = 1
    local real maxlevel = 11
    local integer level = R2I(minlevel+evasion/100*(maxlevel+1-minlevel))
    call Msg("calculated % evasion = "+R2S(evasion))
    call Msg("level of evasion abil given = "+I2S(level))
    call UnitAddAbility(hero,udg_uabils[14])
    call SetUnitAbilityLevel(hero,udg_uabils[14],level)
endfunction

function AirformCast takes nothing returns nothing
    local unit hero = GetTriggerUnit()
    local string herostring = I2S(H2I(hero))
    local real haste =  320 * GetHeroAbilityLevel(hero,9) / GetHeroLevel(hero)
    local real interval = 1
    call Msg("airformcast")
    call SetPlayerAbilityAvailable(GetTriggerPlayer(), udg_habils[10], false)
    call AirformEvasion(hero)
    call StoreReal(udg_gamecache,herostring,"airformhaste",haste)
    call Slow(hero,-haste,-1)
    call Msg("airformcast2")
    set hero = null
endfunction

function AirformOff takes unit hero returns nothing
    local string herostring = I2S(H2I(hero))
    local real haste = GetStoredReal(udg_gamecache,herostring,"airformhaste")
    call UnitRemoveAbility(hero,udg_uabils[14])
    call SetPlayerAbilityAvailable(GetTriggerPlayer(), udg_habils[10],true)
    call FlushStoredReal(udg_gamecache,herostring,"airformhaste")
    call Slow(hero,haste,-1)
    call Msg("airformend")
endfunction

function AirformNullmana takes nothing returns nothing
    local unit hero = GetTriggerUnit()
    call DisplayTextToPlayer(Player(0),0,0,"AirformNullmana")
    call AirformOff(hero)
    set hero = null
endfunction

function AirformLearned takes nothing returns nothing
    local trigger nullmanatrig = CreateTrigger()
    local unit hero = GetTriggerUnit()
    call SetPlayerAbilityAvailable(GetTriggerPlayer(), udg_uabils[14], false)
    call SetHandleHandle(hero,"nullmanatrig",nullmanatrig)
    call TriggerAddAction(nullmanatrig,function AirformNullmana)
    call TriggerRegisterUnitStateEvent(nullmanatrig,hero,UNIT_STATE_MANA,EQUAL,0)
    call DisplayTextToPlayer(Player(0),0,0,"airformlearned")
    set hero = null
    set nullmanatrig = null
endfunction

function WindswipeLevel2Chaos takes integer level returns integer
    local integer array indexes
    set indexes[0] = udg_uabils[47]
    set indexes[1] = udg_uabils[48]
    set indexes[2] = udg_uabils[49]
    set indexes[3] = udg_uabils[50]
    set indexes[4] = udg_uabils[51]
    set indexes[5] = udg_uabils[52]
    set indexes[6] = udg_uabils[53]
    set indexes[7] = udg_uabils[54]
    set indexes[8] = udg_uabils[55]
    set indexes[9] = udg_uabils[56]
    set indexes[10] = udg_uabils[57]
    return indexes[level-1]
endfunction

function WindswipeCast takes nothing returns nothing
    local unit hero = GetTriggerUnit()
    local real midlevel = 5
    local real duration = 15
    local real ias = 10 * GetUnitAbilityLevel(hero,udg_habils[48])
    local integer chaos
    local real delay = 0.5
    local real delay2 = 0.3
    local string herostring = I2S(H2I(hero))
    local integer windswipelevel = GetUnitAbilityLevel(hero,udg_habils[48])
    local integer rangelevel = R2I(1+midlevel * 4 * I2R(windswipelevel) / I2R(GetHeroLevel(hero)))
    local real movespeed = GetUnitMoveSpeed(hero)    
    local real haste = GetStoredReal(udg_gamecache,herostring,"airformhaste")
    call Msg("windswipecast")
    call Msg("range = 77 * "+I2S(rangelevel))
    call Msg("heromovespeed before transform = "+R2S(movespeed))
    call ChangeBonus(hero,-ias,1,true)
    call IssueImmediateOrder(hero,"stop")
    call SetPlayerAbilityAvailable(GetTriggerPlayer(), udg_uabils[23], true)
    call SetUnitAbilityLevel(hero,udg_uabils[23],rangelevel)
    call UnitAddAbility(hero,'Avul')
    call IssueImmediateOrder(hero,udg_orders[23])
    call SetPlayerAbilityAvailable(GetTriggerPlayer(), udg_habils[48], false)
    call SetPlayerAbilityAvailable(GetTriggerPlayer(), udg_habils[11], false)
    call TriggerSleepAction(delay2)
    call UnitRemoveAbility(hero,'Avul')
    call SetUnitMoveSpeed(hero,movespeed)
    call Msg("heromovespeed after transform = "+R2S(GetUnitMoveSpeed(hero)))
    if haste != 0 then
        call AirformEvasion(hero)
    endif
    call UnitAddAbilityBJ( 'Amrf', hero )
    call UnitRemoveAbilityBJ( 'Amrf', hero )
    call TriggerSleepAction(duration-delay)
    call UnitAddAbility(hero,'Avul')
    set movespeed = GetUnitMoveSpeed(hero)
    call TriggerSleepAction(delay+delay2)
    call SetUnitMoveSpeed(hero,movespeed)    
    set haste = GetStoredReal(udg_gamecache,herostring,"airformhaste")
    if haste != 0 then
        call AirformEvasion(hero)
    endif
    call UnitRemoveAbility(hero,'Avul')
    call Msg("windswipeend")
    call SetPlayerAbilityAvailable(GetTriggerPlayer(), udg_habils[48], true)
    call SetPlayerAbilityAvailable(GetTriggerPlayer(), udg_habils[11], true)
    call SetPlayerAbilityAvailable(GetTriggerPlayer(), udg_uabils[23], false)
    call ChangeBonus(hero,-ias,1,true)
    call Msg("you should now see heroname: "+GetUnitName(hero))
    set hero = null
endfunction

//Meditate
function MeditateUpdate takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local unit hero = GetHandleUnit(t,"hero")
    local integer ammount = 2*GetHeroAbilityLevel(hero, 10)
    call SetUnitManaBJ(hero, (GetUnitState(hero, UNIT_STATE_MANA) + ammount ))
    set hero = null
    set t = null
endfunction

function MeditateCast2 takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local timer t2 = CreateTimer()
    local unit hero = GetHandleUnit(t,"hero")
    local real wait = 0
    local real wait2 = 1
    local effect e = AddSpecialEffect("Abilities\\Spells\\NightElf\\Cyclone\\CycloneTarget.mdl", GetWidgetX(hero), GetWidgetY(hero))
    local real duration = 4
    local real interval = 0.01
    local real delay = 3.5
    local real delay2 = 2.2
    local real height = 400
    call SetHandleBoolean(hero,"meditatephase2",true)
    call SetHandleHandle(t2,"hero",hero)
    call PauseUnit(hero, true)
    call SetUnitTimeScalePercent(hero, 0.00)
    call DestroyTimer(t)
    call TriggerSleepAction(wait)
    call PauseUnit(hero, false)
    call SetUnitFlyHeightBJ(hero, height, 600.00)
    call PauseUnit(hero, true)
    call UnitAddAbilityBJ('Avul',hero)
    call TimerStart(t2, interval, true, function MeditateUpdate)
    call TriggerSleepAction(duration-delay)
    call DestroyEffect(e)
    call TriggerSleepAction(delay)
    call PauseTimer(t2)
    call DestroyTimer(t2)
    call PauseUnit(hero, false)
    call SetUnitFlyHeightBJ(hero, 0.00, 600.00)
    call PauseUnit(hero, true)
    call TriggerSleepAction(wait2)
    call UnitRemoveAbilityBJ('Avul',hero)
    call PauseUnit(hero, false)
    call SetUnitTimeScalePercent(hero, 100.00)
    call TriggerSleepAction(delay2)
    call FlushStoredBoolean(udg_gamecache,I2S(H2I(hero)),"meditatephase2")
    call GroupRemoveUnit(udg_busyunits,hero)
    call ResetUnitAnimation(hero)
    set t = null
    set t2 = null
    set e = null
    set hero = null
    call Msg("meditateEnd")
endfunction

function MeditateCast2Wrap takes nothing returns nothing
    call ExecuteFunc("MeditateCast2")
endfunction

function MeditateCast takes nothing returns nothing
    local timer phase2timer = CreateTimer()
    local unit hero = GetTriggerUnit()
    local real anispeed = 200
    local real delay = 3.4    
    //if not IsUnitInGroup(hero,udg_busyunits) then 
    //eigelijk moet de hero niet nu al in busyunits komen. maar moet 
    //phase1 van meditate gecanceled worden juist als de hero in busyunits komt.
        call GroupAddUnit(udg_busyunits,hero)
        call SetHandleHandle(phase2timer,"hero",hero)
        call SetHandleHandle(hero,"meditatetimer",phase2timer)
        call SetUnitTimeScalePercent(hero, anispeed)
        call TimerStart(phase2timer,100*delay/anispeed,false,function MeditateCast2Wrap)
        call Msg("meditateCast")
    //endif
    set hero = null
    set phase2timer = null
endfunction

function MeditateCancel takes nothing returns nothing
    local unit hero = GetTriggerUnit()
    local timer t
    local string heros = I2S(H2I(hero))
    if not GetStoredBoolean(udg_gamecache,heros,"meditatephase2") then
        call GroupRemoveUnit(udg_busyunits,hero)
        set t = I2Timer(GetStoredInteger(udg_gamecache,heros,"meditatetimer"))
        call PauseTimer(t)
        call DestroyTimer(t)
        call SetUnitTimeScalePercent(hero, 100.00)
        call Msg("meditateCancel")
    endif
endfunction

//Tornado
function TornadoUpdatePhase2 takes nothing returns nothing
    local timer updatetimer = GetExpiredTimer()
    local string updatetimerstring = I2S(H2I(updatetimer))
    local string temps
    local integer i = 1
    local unit hero = I2Unit(GetStoredInteger(udg_gamecache,updatetimerstring,"hero"))
    local real angle
    local real g = -10
    local real subjectx
    local real subjecty
    local integer i2 = 0
    local unit subject
    local real distance = 10
    local real dt = 0.02
    local integer guycount = GetStoredInteger(udg_gamecache,updatetimerstring,"guycount")
    local real height
    local integer tempint
    local integer ticks = GetStoredInteger(udg_gamecache,updatetimerstring,"ticks") + 1
    local real dmg = 100*GetHeroAbilityLevel(hero,11)
    call DisplayTextToPlayer(Player(0),0,0,"Tornadoupdate2")
    loop
        exitwhen i == guycount+1
        set temps = I2S(i)
        set tempint = GetStoredInteger(udg_gamecache,updatetimerstring,"tornadoguy"+temps)
        if tempint != 0 then
            set i2 = i2 + 1
            set subject = I2Unit(tempint)
            set height = GetStoredReal(udg_gamecache,updatetimerstring,"tornadoguyheight"+temps) + udg_pointspermeter*0.5*g*ticks*dt*ticks*dt
            if height <= 0 then
                set height = 0
                call UnitRemoveAbilityBJ('Avul',subject)
                call UnitDamageTargetBJ(hero,subject,dmg,ATTACK_TYPE_HERO,DAMAGE_TYPE_NORMAL)
                call PauseUnit(subject,false)
                call StoreInteger(udg_gamecache,updatetimerstring,"tornadoguy"+temps,0)
            else
                set subjectx = GetWidgetX(subject)
                set subjecty = GetWidgetY(subject)
                set angle = GetStoredReal(udg_gamecache,updatetimerstring,"tornadoguyangle"+temps)
                call SetUnitCor(subject, subjectx + distance * CosBJ(angle), subjecty + distance * SinBJ(angle))
            endif
            call SetUnitFlyHeightBJ(subject,height,0)
        endif
        set i = i + 1
    endloop
    if i2 == 0 then
        call DisplayTextToPlayer(Player(0),0,0,"tornadoEnd")
        call PauseTimer(updatetimer)
        call DestroyTimer(updatetimer)
        call FlushStoredMission(udg_gamecache,updatetimerstring)
    else
        call StoreInteger(udg_gamecache,updatetimerstring,"ticks",ticks)
    endif
    set hero = null
    set subject = null
    set updatetimer = null
endfunction

function TornadoPhase1End takes trigger trig returns nothing
    local string trigstring = I2S(H2I(trig))
    local timer updatetimer = I2Timer(GetStoredInteger(udg_gamecache,trigstring,"updatetimer"))
    local group g = I2Group(GetStoredInteger(udg_gamecache,trigstring,"group"))
    local string updatetimerstring = I2S(H2I(updatetimer))
    local unit hero = I2Unit(GetStoredInteger(udg_gamecache,updatetimerstring,"hero"))
    local unit tornado = I2Unit(GetStoredInteger(udg_gamecache,updatetimerstring,"tornado"))
    local integer guycount
    local integer i = 1
    local string temps
    local real dt = 0.02
    call DisplayTextToPlayer(Player(0),0,0,"tornadophase1end")
    call GroupRemoveUnit(udg_busyunits,hero)
    call DestroyTrigger(trig)
    call FlushStoredMission(udg_gamecache,trigstring)
    set guycount = GetStoredInteger(udg_gamecache,updatetimerstring,"guycount")
    if guycount == 0 then
        call PauseTimer(updatetimer)
        call DestroyTimer(updatetimer)
        call FlushStoredMission(udg_gamecache,updatetimerstring)
    else
        loop
            exitwhen i > guycount
            set temps = "tornadoguyangle"+I2S(i)
            call StoreReal(udg_gamecache,updatetimerstring,temps,ModuloReal(GetStoredReal(udg_gamecache,updatetimerstring,temps)+90,360))
            set i = i + 1
        endloop
        call TimerStart(updatetimer, dt, true, function TornadoUpdatePhase2)
    endif
    call KillUnit(tornado)
    call SetUnitPathing(hero, true)
    call TriggerSleepAction(1.00)
    call RemoveUnit(tornado)
    call DestroyGroup(g)
    set updatetimer = null
    set g = null
    set hero = null
    set tornado = null
endfunction

function TornadoPhase1EndByTimer takes nothing returns nothing
    local timer phase1endtimer = GetExpiredTimer()
    local trigger trig = GetHandleTrigger(phase1endtimer,"trig")
    call DisplayTextToPlayer(Player(0),0,0,"phase1endbytimer")
    if trig != null then
        call TornadoPhase1End(trig)
        set trig = null
    else
        call DisplayTextToPlayer(Player(0),0,0,"no trig found!!")
    endif
    call FlushHandleLocals(phase1endtimer)
    call DestroyTimer(phase1endtimer)
    set phase1endtimer = null
endfunction

function TornadoUpdatePhase1 takes nothing returns nothing
    local timer updatetimer = GetExpiredTimer()
    local string updatetimerstring = I2S(H2I(updatetimer))
    local unit hero = I2Unit(GetStoredInteger(udg_gamecache,updatetimerstring,"hero"))
    local unit subject
    local string integers
    local real distance
    local integer guycount = GetStoredInteger(udg_gamecache,updatetimerstring,"guycount")
    local real herox = GetWidgetX(hero)
    local real heroy = GetWidgetY(hero)
    local real angle
    local real anglespeed = 0.1
    local integer i = 1
    call SetUnitCor(I2Unit(GetStoredInteger(udg_gamecache,updatetimerstring,"tornado")), herox, heroy)
    loop
        exitwhen i > GetStoredInteger(udg_gamecache,updatetimerstring,"guycount")
        set integers = I2S(i)
        set subject = I2Unit(GetStoredInteger(udg_gamecache,updatetimerstring,"tornadoguy"+integers))
        set distance = GetStoredReal(udg_gamecache,updatetimerstring,"tornadoguydistance"+integers)
        set angle = ModuloReal(GetStoredReal(udg_gamecache,updatetimerstring,"tornadoguyangle"+integers)+anglespeed,2*bj_PI)
        call SetUnitCor(subject, herox + distance * Cos(angle), heroy + distance * Sin(angle))
        call StoreReal(udg_gamecache,updatetimerstring,"tornadoguyangle"+integers,angle)
        set i = i + 1
    endloop
    set subject = null
    set hero = null
    set updatetimer = null
endfunction

function TornadoInRange takes nothing returns nothing
    local trigger trig = GetTriggeringTrigger()
    local string trigstring = I2S(H2I(trig))
    local timer updatetimer
    local string updatetimerstring
    local unit hero
    local unit subject = GetTriggerUnit()
    local real herox
    local real heroy
    local real subjectx
    local real subjecty
    local integer i
    local integer i2
    local real height
    local string guycountstring
    local integer guycount
    local real distance
    local real mod
    local real size
    local real mindistance = 100
    local real maxdistance = 170
    local real minheight = 150
    local real maxheight = 350
    local group g = I2Group(GetStoredInteger(udg_gamecache,trigstring,"group"))
    if IsGameUnit(subject) and not IsUnitInGroup(subject,g) then
        call PauseUnit(subject,true)
        call DisplayTextToPlayer(Player(0),0,0,"unitinrange!") 
        set updatetimer =  I2Timer(GetStoredInteger(udg_gamecache,I2S(H2I(trig)),"updatetimer"))
        set updatetimerstring = I2S(H2I(updatetimer))
        set hero = I2Unit(GetStoredInteger(udg_gamecache,updatetimerstring,"hero"))
        set guycount = GetStoredInteger(udg_gamecache,updatetimerstring,"guycount") + 1
        set guycountstring = I2S(guycount)
        set herox = GetWidgetX(hero)
        set heroy = GetWidgetY(hero)
        set subjectx = GetWidgetX(subject)
        set subjecty = GetWidgetY(subject)
        call GroupAddUnit(g,subject)
        if guycount == 1 then
            set mod = 1
        else
            if guycount == 2 then
                set mod = 0
            else
                set i = 1
                set i2 = guycount - 2
                loop
                    set size = Pow(2,i)
                    if guycount < (size-1) then
                        set mod = 2 + (-1-2*guycount)/size
                        exitwhen true
                    endif
                    set i = i + 1
                endloop
            endif
        endif
        set height = minheight+(maxheight-minheight)* mod
        set distance = mindistance + (maxdistance-mindistance) * (height-minheight)/(maxheight-minheight)
        call StoreReal(udg_gamecache,updatetimerstring,"tornadoguyheight"+guycountstring,height)
        call StoreInteger(udg_gamecache,updatetimerstring,"tornadoguy"+guycountstring,H2I(subject))
        call StoreReal(udg_gamecache,updatetimerstring,"tornadoguydistance"+guycountstring,distance)
        call StoreReal(udg_gamecache,updatetimerstring,"tornadoguyangle"+guycountstring,Angle(herox,heroy,subjectx,subjecty))
        call UnitAddAbility(subject,'Avul')
        call SetUnitFlyHeight(subject, height, height*2)
        call StoreInteger(udg_gamecache,updatetimerstring,"guycount",guycount)
        set updatetimer = null
        set hero = null
    endif
    set g = null
    set trig = null
    set subject = null
endfunction

function TornadoInRangeCondition takes nothing returns boolean
    local unit subject = GetTriggerUnit()
    local trigger trig = GetTriggeringTrigger()
    local group g = GetHandleGroup(trig,"group")
    local boolean b
    if IsGameUnit(subject) and not IsUnitInGroup(subject,g) then
        set b = true
    endif
    set subject = null
    set trig = null
    set g = null
    return b
endfunction


function TornadoCast takes nothing returns nothing
    local unit hero = GetTriggerUnit()
    local player p = GetTriggerPlayer()
    local unit tornado = CreateUnit(p, udg_dummyunittypes[2], GetWidgetX(hero), GetWidgetY(hero), 0)
    local timer updatetimer = CreateTimer()
    local string updatetimerstring = I2S(H2I(updatetimer))
    local string temps
    local integer i = 1
    local trigger trig = CreateTrigger()
    local string trigstring = I2S(H2I(trig))
    local real range =  180
    local real dt = 0.02
    local real dmg = GetHeroAbilityLevel(hero, 10)
    local real duration = 19
    local group g = CreateGroup()
    local integer guycount
    local timer phase1endtimer = CreateTimer()
    call GroupAddUnit(udg_busyunits,hero)
    call SetUnitPathing(hero, false)
    call TriggerAddAction(trig, function TornadoInRange)
    call TriggerRegisterUnitInRange(trig, hero, range, null)
    call StoreInteger(udg_gamecache,trigstring,"group",H2I(g))
    call StoreInteger(udg_gamecache,updatetimerstring,"hero",H2I(hero))
    call StoreInteger(udg_gamecache,updatetimerstring,"tornado",H2I(tornado))
    call StoreInteger(udg_gamecache,trigstring,"updatetimer",H2I(updatetimer))
    call SetHandleHandle(phase1endtimer,"trig",trig)
    call SetHandleHandle(hero,"trig",trig)
    call TimerStart(updatetimer, dt, true, function TornadoUpdatePhase1)
    call DisplayTextToPlayer(Player(0),0,0,"tornadocast")
    call TimerStart(phase1endtimer,duration,false,function TornadoPhase1EndByTimer)
    set phase1endtimer = null
    set g = null
    set updatetimer = null
    set p = null
    set hero = null
    set tornado = null
    set trig = null
endfunction

//===================================================================================================================
//Shadowlurk
function ShadowlurkCast takes nothing returns nothing
    local unit hero = GetTriggerUnit()
    local real haste = 30*GetHeroLevel(hero)/GetHeroAbilityLevel(hero,12)
    local real speed = GetUnitMoveSpeed(hero)
    local integer dmg = 50 * GetHeroAbilityLevel(hero,12)
    local string herostring = I2S(H2I(hero))
    local real delay = 0.5
    call ChangeBonus(hero,dmg,0,true)
    call SetUnitMoveSpeed(hero, speed - haste)
    loop 
        call TriggerSleepAction(delay)
        exitwhen GetUnitAbilityLevel(hero,udg_buffs[16]) == 0     
    endloop
    set speed = GetUnitMoveSpeed(hero)
    call SetUnitMoveSpeed(hero, speed + haste)     
    call Msg("shadowlurkend")        
    call ChangeBonus(hero,-dmg,0,true)
    set hero = null
    call Msg("ShadowlurkCast")
endfunction

//Vira
function ViraHits takes nothing returns nothing
    local unit target = GetTriggerUnit()
    local unit hero = GetEventDamageSource()
    local real duration = 30
    local real interval = 1
    local real i = 0
    local integer dmg = GetHeroAbilityLevel(hero,13)
    call UnitRemoveBuffBJ(udg_buffs[5],target)
    call Addbuff(target,0,duration)
    call Dot(hero,target,dmg,duration,interval)
    call DisplayTextToPlayer(Player(0),0,0,"virahitsdmg = "+I2S(dmg))
    set target = null
    set hero = null
endfunction

//Bodyburn
function BodyburnCast takes nothing returns nothing
    local unit hero = GetTriggerUnit()
    local real haste = 20*GetHeroAbilityLevel(hero, 14)
    local real ias = 20*GetHeroAbilityLevel(hero, 14)
    local real interval = 0.5
    call SetUnitMoveSpeed(hero, GetUnitMoveSpeed(hero) + haste)
    call ChangeBonus(hero, ias, 1, true)
    call DisplayTextToPlayer(Player(0),0,0,"bodyburncast")
    loop
        call TriggerSleepAction(interval)
        if not UnitHasBuffBJ(hero, udg_buffs[6]) then
            exitwhen true
        endif
    endloop
    call SetUnitMoveSpeed(hero, GetUnitMoveSpeed(hero) - haste)
    call ChangeBonus(hero, -ias, 1, true)
    call DisplayTextToPlayer(Player(0),0,0,"bodyburnend")
    set hero = null
endfunction

function BackshotCast takes nothing returns nothing
    local unit hero = GetTriggerUnit()
    local unit target = GetSpellTargetUnit()
    local real herox = GetWidgetX(hero)
    local real heroy = GetWidgetY(hero)
    local real targetx = GetWidgetX(target)
    local real targety = GetWidgetY(target)
    local real facing = Angle(herox,heroy,targetx,targety)*bj_RADTODEG
    call SetHandleReal(hero,"backshotangle",facing)
    call DisplayTextToPlayer(Player(0),0,0,"backshotcast")
    set hero = null
endfunction

function BackshotHits takes nothing returns nothing
    local unit target = GetTriggerUnit()
    local unit hero = GetEventDamageSource()
    local string herostring = I2S(H2I(hero))
    local real angle1 = ModuloReal(GetStoredReal(udg_gamecache,herostring,"backshotangle")+360,360)
    local real angle2 = GetUnitFacing(target)
    local integer basedmg = 50*GetHeroAbilityLevel(hero, 15)
    local integer dmg = R2I((1+2*(RAbsBJ(RAbsBJ(angle1-angle2)-180)/180))*basedmg)
    local texttag tag
    local real delay = 1
    local real tagheight = 0
    local real tagsize = 10
    //debug
    call Msg(R2S(angle1))
    call Msg(R2S(angle2))
    call Msg(R2S(angle1-angle2))
    //debugend
    call UnitRemoveBuffBJ(udg_buffs[7],target)
    set tag = CreateTextTag()
    call SetTextTagPosUnit(tag, target, tagheight)
    call SetTextTagColor(tag,255,0,0,0)
    call SetTextTagText(tag,I2S(dmg)+"!",TextTagSize2Height(tagsize))
    call DisplayTextToPlayer(Player(0),0,0,"backshothits")
    call UnitDamageTargetNew(hero, target, dmg, 1,0,0)
    call TriggerSleepAction(delay)
    call DestroyTextTag(tag)
    set tag = null
    set target = null
    set hero = null
endfunction

//===================================================================================================================
//Rampage
function RampageEnd takes unit hero, timer updatetimer, string timerstring, unit collider, unit shockwave returns nothing
    call PauseUnit(hero,false)
    call PauseTimer(updatetimer)
    call DestroyTimer(updatetimer)
    call ResetUnitAnimation(hero)
    call GroupRemoveUnit(udg_busyunits,hero)
    call FlushStoredMission(udg_gamecache,timerstring)
    call RemoveUnit(collider)
    call RemoveUnit(shockwave)
    call DisplayTextToPlayer(Player(0),0,0,"chargeend")
    call PauseUnit(hero, false)
endfunction

function RampageEndByTimer takes nothing returns nothing
    local timer endtimer = GetExpiredTimer()
    local string endtimerstring = I2S(H2I(endtimer))
    local timer updatetimer = I2Timer(GetStoredInteger(udg_gamecache,endtimerstring,"updatetimer"))
    local string updatetimerstring
    local unit hero
    local unit shockwave
    local unit collider
    call FlushStoredMission(udg_gamecache, endtimerstring)
    if updatetimer != null then
        set updatetimerstring = I2S(H2I(updatetimer))
        set hero = I2Unit(GetStoredInteger(udg_gamecache,updatetimerstring,"hero"))
        set shockwave = I2Unit(GetStoredInteger(udg_gamecache,updatetimerstring,"shockwave"))
        set collider = I2Unit(GetStoredInteger(udg_gamecache,updatetimerstring,"collider"))
        call RampageEnd(hero,updatetimer,updatetimerstring,collider,shockwave)
        set hero = null
        set collider = null
        set shockwave = null
    endif
    set endtimer = null
    set updatetimer = null
endfunction

function RampagePhase2Collides takes nothing returns nothing
    local unit subject = GetEnumUnit()
    local unit hero = udg_tempunit
    local real x = GetWidgetX(subject)
    local real y = GetWidgetY(subject)
    local real duration = 1
    local real slow = 120*GetHeroAbilityLevel(hero,16)/GetHeroLevel(hero)
    local integer dmg = 50*GetHeroAbilityLevel(hero,16)
    call DisplayTextToPlayer(Player(0),0,0,"rampagecollision")
    call BJDebugMsg(GetUnitName(subject))
    call SetUnitPosition(subject, x, y)
    if GetWidgetX(subject) != x or GetWidgetY(subject) != y then
        call DestroyEffectWait(AddSpecialEffectTarget("Abilities\\Spells\\Orc\\StasisTrap\\StasisTotemTarget.mdl", subject, "overhead"), duration)
        call Slow(hero,slow,duration)
        call UnitDamageTargetNew(hero,subject,dmg, 2, 0, 0)
    endif
    set hero = null
    set subject = null
endfunction

function RampagePhase2Condition takes nothing returns boolean
    return TargetTypeCondition(GetFilterUnit(),udg_tempunit,udg_tempint)
endfunction

function RampageUpdatePhase2 takes nothing returns nothing
    local timer updatetimer = GetExpiredTimer()
    local string timerstring = I2S(H2I(updatetimer))
    local unit hero = I2Unit(GetStoredInteger(udg_gamecache,timerstring,"hero"))
    local unit shockwave = I2Unit(GetStoredInteger(udg_gamecache,timerstring,"shockwave"))
    local location loc =  GetUnitLoc(hero)
    local real dx = GetStoredReal(udg_gamecache,timerstring,"xvelocity")
    local real dy = GetStoredReal(udg_gamecache,timerstring,"yvelocity")
    local real x = GetWidgetX(hero) + dx
    local real y = GetWidgetY(hero) + dy
    local real collisionrange = 70
    local group g
    set udg_tempint = 49153
    set udg_tempunit = hero
    set g = GetUnitsInRangeOfLocMatching(collisionrange, loc, Condition(function RampagePhase2Condition))
    call DisplayTextToPlayer(Player(0),0,0,"rampageupdate2")
    call SetUnitCor(hero, x, y)
    call SetUnitCor(shockwave, GetWidgetX(shockwave) + dx, GetWidgetY(shockwave) + dy)
    call ForGroup(g, function RampagePhase2Collides)
    call RemoveLocation(loc)
    call DestroyGroup(g)
    set g = null
    set loc = null
    set hero = null
    set shockwave = null
    set updatetimer = null
endfunction

function RampageNextPhase takes nothing returns nothing
    local timer nextphasetimer = GetExpiredTimer()
    local string nextphasetimerstring = I2S(H2I(nextphasetimer))
    local timer updatetimer = I2Timer(GetStoredInteger(udg_gamecache,nextphasetimerstring,"updatetimer"))
    local string updatetimerstring = I2S(H2I(updatetimer))
    local real dx = GetStoredReal(udg_gamecache,updatetimerstring,"xvelocity")
    local real dy = GetStoredReal(udg_gamecache,updatetimerstring,"yvelocity")
    local unit collider = I2Unit(GetStoredInteger(udg_gamecache,updatetimerstring,"collider"))  
    local real dt = 0.02
    local unit hero = I2Unit(GetStoredInteger(udg_gamecache,updatetimerstring,"hero"))
    local real x = GetWidgetX(hero)
    local real y = GetWidgetY(hero)
    local real facing = Angle(0,0,dx,dy)
    local real shockahead = 60
    local unit shockwave = CreateUnit(Player(15), udg_dummyunittypes[3], x + shockahead*Cos(facing), y + shockahead*Sin(facing), facing*bj_RADTODEG)
    call RemoveUnit(collider)
    call StoreInteger(udg_gamecache,updatetimerstring,"shockwave",H2I(shockwave))
    if updatetimer != null then
        call TimerStart(updatetimer, dt, true, function RampageUpdatePhase2)
        set updatetimer = null
    endif
    call FlushStoredMission(udg_gamecache,nextphasetimerstring)
    call DestroyTimer(nextphasetimer)
    set collider = null
    set nextphasetimer = null
    set updatetimer = null
    set shockwave = null
endfunction

function RampageUpdatePhase1 takes nothing returns nothing
    local timer updatetimer = GetExpiredTimer()
    local string updatetimerstring = I2S(H2I(updatetimer))
    local unit hero = I2Unit(GetStoredInteger(udg_gamecache,updatetimerstring,"hero"))
    local unit collider = I2Unit(GetStoredInteger(udg_gamecache,updatetimerstring,"collider"))
    local real dx = GetStoredReal(udg_gamecache,updatetimerstring,"xvelocity")
    local real dy = GetStoredReal(udg_gamecache,updatetimerstring,"yvelocity")
    local real herox = GetWidgetX(hero)
    local real heroy = GetWidgetY(hero)
    local real x = herox + dx
    local real y = heroy + dy
    local real duration = 1
    local real slow = 50
    call DisplayTextToPlayer(Player(0),0,0,"chargeupdate")
    call ShowUnitHide(hero)
    call SetUnitPosition(collider, x, y)
    if SubString(R2S(GetWidgetX(collider)),0,3) != SubString(R2S(x),0,3) or SubString(R2S(GetWidgetY(collider)),0,3) != SubString(R2S(y),0,3) then
        call ShowUnitShow(hero)        
        call SetUnitCor(hero, herox, heroy)
        call RampageEnd(hero,updatetimer,updatetimerstring,collider,null)
        call DisplayTextToPlayer(Player(0),0,0,"chargecrash")
        call Slow(hero,slow,duration)
        call DestroyEffectWait(AddSpecialEffectTarget("Abilities\\Spells\\Orc\\StasisTrap\\StasisTotemTarget.mdl", hero, "overhead"), duration)
    else
        call ShowUnitShow(hero)
        call SetUnitCor(hero, x, y)
    endif
    set hero = null
    set collider = null
    set updatetimer = null
endfunction

function RampageSpellStarts takes nothing returns nothing
    local unit hero = GetTriggerUnit()
    local location loc = GetSpellTargetLoc()
    local player p = GetTriggerPlayer()
    local real x = GetWidgetX(hero)
    local real y = GetWidgetY(hero)
    local real x2 = GetLocationX(loc)
    local real y2 = GetLocationY(loc)
    local real velocity = 3
    local real dt = 0.02
    local real totaltime = Distance(x, y, x2, y2) / (udg_pointspermeter*velocity)
    local real switchwait = 400/(velocity*udg_pointspermeter)
    local real facing = Angle(x, y, x2, y2)
    local unit collider = CreateUnit(Player(15), udg_dummyunittypes[4], x, y, 0)
    local timer updatetimer = CreateTimer()
    local timer nextphasetimer
    local timer endtimer = CreateTimer()
    local string updatetimerstring = I2S(H2I(updatetimer))
    local real delay = 0
    call TriggerSleepAction(delay)
    if not IsUnitInGroup(hero,udg_busyunits) then
        call GroupAddUnit(udg_busyunits,hero)
        call SetUnitAnimationByIndex(hero,3)
        call PauseUnit(hero, true)
        call StoreInteger(udg_gamecache,updatetimerstring,"hero",H2I(hero))
        call StoreInteger(udg_gamecache,updatetimerstring,"collider",H2I(collider))
        call StoreReal(udg_gamecache,updatetimerstring,"yvelocity",udg_pointspermeter*velocity*Sin(facing)*dt)
        call StoreReal(udg_gamecache,updatetimerstring,"xvelocity",udg_pointspermeter*velocity*Cos(facing)*dt)
        call SetUnitFacing(hero,facing*bj_RADTODEG)
        call PlaySoundOnUnitBJ(gg_snd_Shockwave, 100, hero)
        call PauseUnit(hero,true)
        call TimerStart(updatetimer, dt, true, function RampageUpdatePhase1)
        if totaltime > switchwait then
            set nextphasetimer = CreateTimer()
            call SetHandleHandle(nextphasetimer,"updatetimer",updatetimer)
            call TimerStart(nextphasetimer, switchwait, false, function RampageNextPhase)
            set nextphasetimer = null
        endif
        call SetHandleHandle(endtimer,"updatetimer",updatetimer)
        call TimerStart(endtimer,totaltime,false,function RampageEndByTimer)
        call RemoveLocation(loc)
        call DisplayTextToPlayer(Player(0),0,0,"rampagecast")
    endif
    set hero = null
    set loc = null
    set p = null
    set collider = null
    set updatetimer = null
    set endtimer = null
endfunction


//Toss
function TossEnd takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local string tstring = I2S(H2I(t))
    local unit subject = I2Unit(GetStoredInteger(udg_gamecache,tstring,"subject"))
    local unit hero = I2Unit(GetStoredInteger(udg_gamecache,tstring,"hero"))
    local integer dmg = 50 * GetHeroAbilityLevel(hero, 17)
    local real delay = 1
    local effect effect1 = AddSpecialEffectTarget("Abilities\\Weapons\\Rifle\\RifleImpact.mdl",subject,"overhead")         
    call Msg("tossend")
    call UnitDamageTargetNew(hero, subject, dmg, 2,0,0)
    call DestroyEffectWait(effect1,delay)
    set t = null
    set hero = null
    set subject = null
endfunction


//function TossUpdate takes nothing returns nothing
//    local timer updatetimer = GetExpiredTimer()
//    local string updatetimerstring = I2S(H2I(updatetimer))
//    local unit hero = I2Unit(GetStoredInteger(udg_gamecache,updatetimerstring,"hero"))
//    local unit target = I2Unit(GetStoredInteger(udg_gamecache,updatetimerstring,"target"))
//    local real dt = 0.02
//    local real ticks = GetStoredReal(udg_gamecache,updatetimerstring,"ticks")+1
//    local integer totaltime = 30
//    local real zvelocity0 = 10
//    local integer dmg
//    local real height = udg_pointspermeter * (zvelocity0*ticks*dt - 0.5*udg_gravity*ticks*dt*ticks*dt)
//    call MoveUnit(target, GetStoredReal(udg_gamecache,updatetimerstring,"xvelocity"), GetStoredReal(udg_gamecache,updatetimerstring,"yvelocity"))
//    if height <= 0 then
//        set height = 0
//        call GroupRemoveUnit(udg_busyunits,target)
//        set dmg = 50 * GetHeroAbilityLevel(hero, 17)
//        call PauseTimer(updatetimer)
//        call DestroyTimer(updatetimer)
//        call UnitRemoveAbility(target, 'Avul')
//        call UnitDamageTargetNew(hero, target, dmg, 2,0,0)
//        call FlushStoredMission(udg_gamecache,updatetimerstring)
//    else    
//        call StoreReal(udg_gamecache,updatetimerstring,"ticks",ticks)
//    endif
//    call SetUnitFlyHeight(target, height, 0)
//endfunction

//function TossCast takes nothing returns nothing
//    local timer updatetimer = CreateTimer()
//    local string updatetimerstring = I2S(H2I(updatetimer))
//    local unit hero = GetTriggerUnit()
//    local unit target = GetSpellTargetUnit()
//    local real dt = 0.02
//    local real herox = GetWidgetX(hero)
//    local real heroy = GetWidgetY(hero)
//    local real targetx = GetWidgetX(target)
//    local real targety = GetWidgetY(target)
//    local real angle = Angle(herox,heroy,targetx,targety)
//    local real hvelocity = 10
//    local real delay = 0.5
//    call GroupAddUnit(udg_busyunits,target)
//    call TriggerSleepAction(delay)
//    call StoreReal(udg_gamecache,updatetimerstring,"xvelocity",hvelocity*Cos(angle))
//    call StoreReal(udg_gamecache,updatetimerstring,"yvelocity",hvelocity*Sin(angle))
//    call StoreInteger(udg_gamecache,updatetimerstring,"hero",H2I(hero))
//    call StoreInteger(udg_gamecache,updatetimerstring,"target",H2I(target))
//    call PauseUnit(target,true)
//    call UnitAddAbility(target,'Avul')
//    call TimerStart(updatetimer, dt, true, function TossUpdate)
//    set updatetimer = null
//    set hero = null
//    set target = null
//    call DisplayTextToPlayer(Player(0),0,0,"tosscast")
//endfunction

function TossCast takes nothing returns nothing
    local unit hero = GetTriggerUnit()
    local unit target = GetSpellTargetUnit()
    local real herox = GetWidgetX(hero)
    local real heroy = GetWidgetY(hero)
    local real targetx = GetWidgetX(target)
    local real targety = GetWidgetY(target)
    local real angle = Angle(herox,heroy,targetx,targety)
    local real mspeed = 500
    local real delay = 0.5
    local real zvelocity0 = 5
    local real h0 = 0
    local timer t
    call GroupAddUnit(udg_busyunits,target)
    call TriggerSleepAction(delay)
    set t = StartDumbFlight(target,angle,mspeed,zvelocity0,h0,"TossEnd")
    call SetHandleHandle(t,"hero",hero)
    call PauseUnit(target,true)
    call UnitAddAbility(target,'Avul')
    set hero = null
    set target = null
    set t = null
    call Msg("tosscast")
endfunction


//Quadrostomp
function QuadrostompEnd takes unit hero returns nothing
    local string herostring = I2S(H2I(hero))
    local timer updatetimer = I2Timer(GetStoredInteger(udg_gamecache,herostring,"quadrostompupdatetimer"))
    local string updatetimerstring = I2S(H2I(updatetimer))
    local timer endtimer = I2Timer(GetStoredInteger(udg_gamecache,updatetimerstring,"endtimer"))
    call FlushStoredMission(udg_gamecache,updatetimerstring)
    call FlushHandleLocals(endtimer)
    call FlushStoredInteger(udg_gamecache,herostring,"quadrostompupdatetimer")
    call DestroyTimer(endtimer)
    call PauseTimer(updatetimer)
    call DestroyTimer(updatetimer)
    set endtimer = null
    set updatetimer = null
    set hero = null
endfunction

function QuadrostompEndByTimer takes nothing returns nothing
    local timer endtimer = GetExpiredTimer()
    local unit hero = GetHandleUnit(endtimer,"hero")
    call QuadrostompEnd(hero)
    set endtimer = null
    set hero = null
endfunction

function QuadrostompUpdate takes nothing returns nothing
    local timer updatetimer = GetExpiredTimer()
    local string updatetimerstring = I2S(H2I(updatetimer))
    local integer ticks = GetStoredInteger(udg_gamecache,updatetimerstring,"ticks")
    local unit hero = I2Unit(GetStoredInteger(udg_gamecache,updatetimerstring,"hero"))
    local real array xs
    local real array ys
    local real herox = GetWidgetX(hero)
    local real heroy = GetWidgetY(hero)
    local integer i = ModuloInteger(ticks,2)   
    local integer i2 = 0
    local real radius = 250
    local effect effect1
    local real facing = GetUnitFacing(hero)
    local integer dmg = 10 * GetHeroAbilityLevel(hero, 18)
    call StoreInteger(udg_gamecache,updatetimerstring,"ticks",ModuloInteger(ticks+1,4))
    set xs[0] = herox + 70 * CosBJ(facing + 30)
    set xs[1] = herox + 60 * CosBJ(facing + 150)
    set xs[2] = herox + 70 * CosBJ(facing - 30)
    set xs[3] = herox + 60 * CosBJ(facing - 150)
    set ys[0] = heroy + 70 * SinBJ(facing + 30)
    set ys[1] = heroy + 60 * SinBJ(facing + 150)
    set ys[2] = heroy + 70 * SinBJ(facing - 30)
    set ys[3] = heroy + 60 * SinBJ(facing - 150)
    loop
        exitwhen i2 == 2
        call UnitDamageArea(hero, xs[i+2*i2], ys[i+2*i2], radius, 21505, dmg, 2, 0, 0)
        set effect1 = AddSpecialEffect("Abilities\\Spells\\Human\\ThunderClap\\ThunderClapCaster.mdl", xs[i+2*i2], ys[i+2*i2])
        call DestroyEffectWait(effect1,1)
        set i2 = i2 + 1
    endloop
    set effect1 = null
    set updatetimer = null
    set hero = null
endfunction

function QuadrostompCast takes nothing returns nothing
    local unit hero = GetTriggerUnit()
    local real duration = -1
    local real interval = 0.23
    local timer updatetimer = CreateTimer()
    local timer endtimer
    call Msg("quadrostompcast")
    call SetHandleHandle(updatetimer,"hero",hero)
    call SetHandleHandle(hero,"quadrostompupdatetimer",updatetimer)
    call TimerStart(updatetimer,interval,true,function QuadrostompUpdate)
    if duration != -1 then
        set endtimer = CreateTimer()
        call TimerStart(endtimer,duration,false,function QuadrostompUpdate)
        call SetHandleHandle(endtimer,"hero",hero)
        call SetHandleHandle(updatetimer,"endtimer",endtimer)
        set endtimer = null
    endif
    set hero = null
    set updatetimer = null
endfunction

function BlizzardCast takes nothing returns nothing
    local location loc = GetSpellTargetLoc()
    local real x = GetLocationX(loc)
    local real y = GetLocationY(loc)
    local unit hero = GetTriggerUnit()
    local unit blizcaster
    local unit cloudcaster
    local player p = GetTriggerPlayer()
    local real duration = 60 * GetHeroAbilityLevel(hero, 19) / GetHeroLevel(hero)
    call CastCorAbility(p,1,1,x,y,-1)
    set blizcaster = udg_caster
    call CastCorAbility(p,6,1,x,y,-1)
    set cloudcaster = udg_caster
    call DisplayTextToPlayer(Player(0),0,0,"blizcast")
    call TriggerSleepAction(duration)
    call DisplayTextToPlayer(Player(0),0,0,"blizzardend")
    call IssueImmediateOrder(blizcaster,"stop")
    call IssueImmediateOrder(cloudcaster,"stop")
    set udg_tempint = 1
    set udg_tempreal = 0
    set udg_caster = blizcaster
    call ExecuteFunc("RecycleCaster")
    set udg_tempint = 6
    set udg_caster = cloudcaster
    call ExecuteFunc("RecycleCaster")
endfunction

//===================================================================================================================
//Hell Fires
function HellFiresHitsArea takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local string timers = I2S(H2I(t))
    local unit hero = I2Unit(GetStoredInteger(udg_gamecache,timers,"hero"))
    local real targetx = GetStoredReal(udg_gamecache,timers,"targetx")
    local real targety = GetStoredReal(udg_gamecache,timers,"targety")
    local real radius = 400
    local integer dmg = 120 * GetHeroAbilityLevel(hero,20)
    call UnitDamageArea(hero, targetx, targety, radius, 17408, dmg, 2, 0, 0)
    call DestroyTimer(t)
    call FlushStoredMission(udg_gamecache,timers)
    set t = null
    set hero = null
endfunction

function HellFiresHitTarget takes nothing returns nothing
    local unit caster = GetEventDamageSource()
    local string casters = I2S(H2I(caster))
    local unit hero = I2Unit(GetStoredInteger(udg_gamecache,casters,"hero"))
    local real radius = 200
    local integer dmg = 120 * GetHeroAbilityLevel(hero,20)
    local unit target = GetTriggerUnit()
    local real x = GetWidgetX(target)
    local real y = GetWidgetX(target)
    call UnitDamageArea(hero, x, y, radius, 17408, dmg, 2, 0, 0)
    call FlushStoredMission(udg_gamecache,casters)
    set udg_caster = caster
    set udg_tempint = 16
    set udg_tempreal = 0
    call ExecuteFunc("RecycleCaster")
    set caster = null
    set target = null
    set hero = null
endfunction

function HellFiresHitsUnit takes nothing returns nothing
    local string ts = udg_tempstring
    local unit hero = I2Unit(GetStoredInteger(udg_gamecache,ts,"hero"))
    local real tx = GetWidgetX(udg_tempunit)
    local real ty = GetWidgetY(udg_tempunit)
    local real radius = 400
    local integer dmg = 120 * GetUnitAbilityLevel(hero,udg_habils[20])
    local effect effect1 = I2Effect(GetStoredInteger(udg_gamecache,ts,"effect"))
    call UnitDamageArea(hero,tx,ty,radius,17408,dmg,2,0,0)
    call KillUnit(udg_tempunit2)
    call DestroyEffect(effect1)
    set effect1 = null
    set hero = null
endfunction

function HellFiresCast takes nothing returns nothing
    local unit hero = GetTriggerUnit()
    local real herox = GetWidgetX(hero)
    local real heroy = GetWidgetY(hero)
    local timer t = CreateTimer()
    local real missilespeed = 700
    local real delay
    local real facing = GetUnitFacing(hero)*bj_DEGTORAD
    local unit target = GetHandleUnit(hero, "targettarget")
    local real targetdist = 500
    local real launcherdist = 50
    local real targetx
    local real targety
    local string timers
    local player p = GetTriggerPlayer()
    local effect array effects
    local real height = 100
    local unit array missiles
    local real hitheight = 60
    local real aoa = bj_PI/3
    local integer i
    local real steerspeed = bj_PI/40
    if target == null then
        call Msg("notarget")
        set t = CreateTimer()
        set targetx = herox + Cos(facing) * targetdist
        set targety = heroy + Sin(facing) * targetdist
        set delay = Distance(0,0,targetdist,launcherdist)/missilespeed
        set timers = I2S(H2I(t))
        call StoreInteger(udg_gamecache,timers,"hero",H2I(hero))
        call StoreReal(udg_gamecache,timers,"targetx",targetx)
        call StoreReal(udg_gamecache,timers,"targety",targety)
        set i = 0
        loop
            exitwhen i == 2
            call CastCorAbilityCor(p, 7, 1, targetx, targety, 0, herox + launcherdist * Cos(facing + (I2R(i)*2-1)*bj_PI), heroy + launcherdist * Sin(facing + (I2R(i)*2-1)*bj_PI), height)
            set i = i + 1
        endloop
        call TimerStart(t, delay, false, function HellFiresHitsArea)
        set t = null
    else
        call Msg("targetfound")  
        set i = 0
        loop
            exitwhen i == 1
            set missiles[i] = CreateUnit(p,udg_dummyunittypes[0],herox + launcherdist * Cos(facing + (I2R(i)*2-1)*bj_PI), heroy + launcherdist * Sin(facing + (I2R(i)*2-1)*bj_PI),0)
            set effects[i] = AddSpecialEffectTarget("Abilities\\Spells\\Other\\TinkerRocket\\TinkerRocketMissile.mdl",missiles[i],"origin")
            set t = StartRocket(missiles[i],target,hitheight,aoa,height,missilespeed,"HellFiresHitsUnit",steerspeed, facing)
            set timers = I2S(H2I(t))
            call StoreInteger(udg_gamecache,timers,"effect",H2I(effects[i]))
            call SetUnitUserData(missiles[i],i)
            call StoreInteger(udg_gamecache,timers,"hero",H2I(hero))
            set missiles[i] = null
            set effects[i] = null
            set i = i + 1
        endloop
    endif
    set hero = null
    set p = null
    call DisplayTextToPlayer(Player(0),0,0,"hellfirescast")
endfunction

function ChaosHero2Abil takes integer heronumber returns integer
    local integer array hero2abil
    set hero2abil[0] = udg_uabils[34]
    set hero2abil[1] = udg_uabils[35]
    set hero2abil[2] = udg_uabils[36]
    set hero2abil[3] = udg_uabils[37]
    set hero2abil[4] = udg_uabils[38]
    set hero2abil[5] = udg_uabils[39]
    set hero2abil[6] = udg_uabils[40]
    set hero2abil[7] = udg_uabils[41]
    set hero2abil[8] = udg_uabils[42]
    set hero2abil[9] = udg_uabils[43]
    set hero2abil[10] = udg_uabils[44]
    set hero2abil[11] = udg_uabils[45]
    return hero2abil[heronumber]
endfunction

//function PowSpellStarts takes nothing returns nothing
//    local unit hero = GetTriggerUnit()
//    local unit target = GetSpellTargetUnit()
//    local real duration = 30 * GetHeroAbilityLevel(hero,21) / GetHeroLevel(hero)
//    local integer heronumber = Hero2Number(GetUnitTypeId(target))
//    local integer abil = ChaosHero2Abil(heronumber)
//    local real delay = 1
//    call UnitAddAbility(target,udg_uabils[20])
//    call Msg("powcast")
//    call TriggerSleepAction(duration)
//    call UnitRemoveAbility(target,udg_uabils[20])
//    call UnitAddAbility(target,abil)
//    call TriggerSleepAction(delay)
//    call UnitRemoveAbility(target,abil)
//    call Msg("powend")
//    set hero = null
//    set target = null
//endfunction

function PowSpellStarts takes nothing returns nothing
    local unit hero = GetTriggerUnit()
    local unit target = GetSpellTargetUnit()
    local real duration = 30 * GetHeroAbilityLevel(hero,21) / GetHeroLevel(hero)
    call Stun(target,duration)
    call SetUnitScale(target,0.5,0.5,0.5)
    call UnitAddAbility(target,udg_uabils[61])
    call Msg("powcast")
    call TriggerSleepAction(duration)
    call UnitRemoveAbility(target,udg_uabils[61])
    call SetUnitScale(target,1,1,1)
    call Msg("powend")
endfunction

//Coolant Flush
function CoolantFlushCast takes nothing returns nothing
    local unit hero = GetTriggerUnit()
    local player p = GetTriggerPlayer()
    local unit caster
    local real facing = GetUnitFacing(hero)
    local real distance = 400
    local real missilespeed = 700
    local real delay = distance/missilespeed
    local real herox = GetWidgetX(hero)
    local real heroy = GetWidgetY(hero)
    local real spellx = herox + CosBJ(facing+180) * distance
    local real spelly = heroy + SinBJ(facing+180) * distance
    local real duration = 32 * GetHeroAbilityLevel(hero,22) / GetHeroLevel(hero)
    call CastCorAbilityCor(p, 17, 1, spellx, spelly, 0, herox, heroy, 0)
    call TriggerSleepAction(delay)
    call CastCorAbility(p, 8, 1, spellx, spelly, -1)
    set caster = udg_caster
    call DisplayTextToPlayer(Player(0),0,0,"CoolantFlushCast")
    call TriggerSleepAction(duration)
    call DisplayTextToPlayer(Player(0),0,0,"CoolantFlushEnd")
    set udg_caster = caster
    set udg_tempint = 8
    call ExecuteFunc("RecycleCaster")
    set p = null
    set hero = null
    set caster = null
endfunction

//Target
function TargetDeath takes unit target returns nothing
    local string targetstring = I2S(H2I(target))
    local effect targeteffect = I2Effect(GetStoredInteger(udg_gamecache,targetstring,"targeteffect"))
    call DestroyEffect(targeteffect)
    set targeteffect = null
endfunction

function TargetEnd takes nothing returns nothing
    local timer endtimer = GetExpiredTimer()
    local unit hero = GetHandleUnit(endtimer,"hero")
    local string herostring = I2S(H2I(hero))
    local unit target = I2Unit(GetStoredInteger(udg_gamecache,herostring,"targettarget"))
    local string targetstring = I2S(H2I(target))
    local effect targeteffect = I2Effect(GetStoredInteger(udg_gamecache,targetstring,"targeteffect"))
    call DestroyEffect(targeteffect)
    call Msg("targetend")
    call UnitRemoveAbility(target,udg_buffs[3])
    call FlushStoredInteger(udg_gamecache,herostring,"targettarget")
    call FlushStoredInteger(udg_gamecache,targetstring,"targeteffect")
    call FlushStoredInteger(udg_gamecache,targetstring,"targethero")
endfunction

function TargetCast takes nothing returns nothing
//1 is targetcast on fresh target with no target active on an oldtarget.
//2 is a targetcast on the unit that was already targeted by you.
//3 is a targetcast while you already had target on another unit. Targetstuff must then be removed from the old target
//4 is targetcast while the unit was already targeted by another hero.
//5 is when you already had another target and your new target was already targeted by another hero.
    local unit hero = GetTriggerUnit()
    local unit target = GetSpellTargetUnit()
    local string herostring = I2S(H2I(hero))
    local string targetstring = I2S(H2I(target))
    local real duration = 80 * GetHeroAbilityLevel(hero,23) / GetHeroLevel(hero)
    local effect targeteffect
    local timer endtimer
    local unit otherhero
    local string oldtargetstring
    local unit oldtarget = I2Unit(GetStoredInteger(udg_gamecache,herostring,"targettarget"))  
    if oldtarget == null then 
        set otherhero = I2Unit(GetStoredInteger(udg_gamecache,targetstring,"targethero"))
        call StoreInteger(udg_gamecache,targetstring,"targethero",H2I(hero))   
        if otherhero == null then //1
            call Msg("1")
            set endtimer = CreateTimer()
            call StoreInteger(udg_gamecache,targetstring,"targettimer",H2I(endtimer))   
            set targeteffect = AddSpecialEffectTarget("Abilities\\Spells\\Other\\Aneu\\AneuTarget.mdl",target, "overhead")
            call StoreInteger(udg_gamecache,targetstring,"targeteffect",H2I(targeteffect))       
        else //4
            call Msg("4")
            call SetHandleHandle(otherhero,"targettarget",null)
            set endtimer = I2Timer(GetStoredInteger(udg_gamecache,targetstring,"targettimer"))
        endif        
        call SetHandleHandle(endtimer,"hero",hero)
        call StoreInteger(udg_gamecache,herostring,"targettarget",H2I(target))
    else
        if oldtarget == target then // 2
            call Msg("2")
            set endtimer = I2Timer(GetStoredInteger(udg_gamecache,targetstring,"targettimer"))
        else  
            set otherhero = I2Unit(GetStoredInteger(udg_gamecache,targetstring,"targethero"))
            set oldtargetstring = I2S(H2I(oldtarget))
            set targeteffect = I2Effect(GetStoredInteger(udg_gamecache,oldtargetstring,"targeteffect"))
            call FlushStoredInteger(udg_gamecache,oldtargetstring,"targethero")
            call DestroyEffect(targeteffect)                            
            set endtimer = GetHandleTimer(oldtarget,"targettimer")   
            call StoreInteger(udg_gamecache,targetstring,"targethero",H2I(hero))                    
            if otherhero == null then //3     
                call Msg("3")                 
                call StoreInteger(udg_gamecache,targetstring,"targettimer",H2I(endtimer))   
                set targeteffect = AddSpecialEffectTarget("Abilities\\Spells\\Other\\Aneu\\AneuTarget.mdl",target, "overhead")       
                call StoreInteger(udg_gamecache,targetstring,"targeteffect",H2I(targeteffect))       
            else        //5    
                call Msg("5")                               
                call SetHandleHandle(otherhero,"targettarget",null)
                call PauseTimer(endtimer)
                call DestroyTimer(endtimer)
                set endtimer = I2Timer(GetStoredInteger(udg_gamecache,targetstring,"targettimer"))
            endif
            call StoreInteger(udg_gamecache,herostring,"targettarget",H2I(target))
        endif
    endif
    call TimerStart(endtimer,duration,false,function TargetEnd)
    
    call Msg("targetcast")
    set endtimer = null    
    set otherhero = null
    set targeteffect = null
    set hero = null
    set oldtarget = null
    set target = null
endfunction

//===================================================================================================================================================
//Venomancer

//Poison Nova
function PoisonnovaCast takes nothing returns nothing
    local integer i = 0
    local unit hero = GetTriggerUnit()
    local real x = GetWidgetX(hero)
    local real y = GetWidgetY(hero)
    local player p = GetTriggerPlayer()
    local real dist = 600
    local real angle
    loop
        exitwhen i == 8
        set angle = i * 45
        call CastCorAbilityCor(p, 15, 1, x + CosBJ(angle)*dist, y + SinBJ(angle)*dist,5,x,y,50)
        call SetHandleHandle(udg_caster,"hero",hero)
        set i = i + 1
    endloop
    call DisplayTextToPlayer(Player(0),0,0,"poisonnovacast")
    set hero = null
    set p = null
endfunction

function PoisonnovaHits takes nothing returns nothing
    local integer i = 1
    local unit subject = GetTriggerUnit()
    local unit caster = GetEventDamageSource()
    local string subjectstring = I2S(H2I(subject))
    local string casterstring = I2S(H2I(caster))
    local unit hero = I2Unit(GetStoredInteger(udg_gamecache,casterstring,"hero"))
    local integer dmg = 2 * GetHeroAbilityLevel(hero, 24)
    local boolean stacks = false
    local real duration = 10
    local real interval = 1
    local integer poisoncount = GetStoredInteger(udg_gamecache,subjectstring,"poisoncount")
    local integer poisonbuffcount = GetStoredInteger(udg_gamecache,subjectstring,"poisonbuffcount")
    call UnitRemoveBuffBJ(udg_buffs[9], subject)
    call DisplayTextToPlayer(Player(0),0,0,"PBC: "+I2S(poisonbuffcount))
    if poisonbuffcount == 0 then
        call Addbuff(subject,1,-1)
    endif
    call DisplayTextToPlayer(Player(0),0,0,"PC: "+I2S(poisoncount))
    if poisoncount == 0 or stacks then
        call DisplayTextToPlayer(Player(0),0,0,"poisonnovaHits")
        call Dot(hero,subject,dmg,duration,interval)
        call StoreInteger(udg_gamecache,subjectstring,"poisonbuffcount",poisonbuffcount+1)
        if not stacks then
            call StoreInteger(udg_gamecache,subjectstring,"poisoncount",poisoncount+1)  
        endif
        call TriggerSleepAction(duration)
        if stacks then
            set poisoncount = GetStoredInteger(udg_gamecache,subjectstring,"poisoncount")
        else
            set poisoncount = GetStoredInteger(udg_gamecache,subjectstring,"poisoncount") - 1
            call StoreInteger(udg_gamecache,subjectstring,"poisoncount",poisoncount)   
        endif
        set poisonbuffcount = GetStoredInteger(udg_gamecache,subjectstring,"poisonbuffcount") - 1
        call StoreInteger(udg_gamecache,subjectstring,"poisonbuffcount",poisonbuffcount)   
        if poisonbuffcount == 0 then
            call UnitRemoveAbility(subject,udg_showbuffs[1])
            call DisplayTextToPlayer(Player(0),0,0,"buffEnd")
        endif
        call DisplayTextToPlayer(Player(0),0,0,"poisonnovaEnd")
    endif
    set subject = null
    set caster = null
    set hero = null
endfunction

//Poison Skin
function PoisonskinCast takes nothing returns nothing
    call CastWidgetAbility(GetTriggerPlayer(),62,1,GetTriggerUnit(),0)
endfunction

function PoisonskinHit takes nothing returns nothing
    local integer i = 0
    local unit hero = GetTriggerUnit()
    local unit subject = GetEventDamageSource()
    local string subjectstring = I2S(H2I(subject))
    local integer poisoncount = GetStoredInteger(udg_gamecache,subjectstring,"poisoncount")
    local integer poisonbuffcount = GetStoredInteger(udg_gamecache,subjectstring,"poisonbuffcount")
    local integer dmg = 4 * GetHeroAbilityLevel(hero,25) / GetHeroLevel(hero)
    local real duration = 10
    local real interval = 1
    local boolean stacks = true
    call UnitRemoveAbility(subject,udg_buffs[12])
    if poisonbuffcount == 0 then
        call Addbuff(subject,1,-1)
    endif
    if stacks or poisoncount == 0 then
        call DisplayTextToPlayer(Player(0),0,0,"poisonskinHit")
        call Dot(hero,subject,dmg,duration,interval)
        call StoreInteger(udg_gamecache,subjectstring,"poisonbuffcount",poisonbuffcount+1)
        if not stacks then
            call StoreInteger(udg_gamecache,subjectstring,"poisoncount",poisoncount+1)  
        endif
        call TriggerSleepAction(duration)
        if stacks then
            set poisoncount = GetStoredInteger(udg_gamecache,subjectstring,"poisoncount")
        else
            set poisoncount = GetStoredInteger(udg_gamecache,subjectstring,"poisoncount") - 1
            call StoreInteger(udg_gamecache,subjectstring,"poisoncount",poisoncount)   
        endif
        set poisonbuffcount = GetStoredInteger(udg_gamecache,subjectstring,"poisonbuffcount") - 1
        call StoreInteger(udg_gamecache,subjectstring,"poisonbuffcount",poisonbuffcount)   
        if poisonbuffcount == 0 then
            call UnitRemoveAbility(subject,udg_showbuffs[1])
        endif
        call DisplayTextToPlayer(Player(0),0,0,"poisonskinEnd")
    endif
    set hero = null
    set subject = null
endfunction

//Crippling Poison
function CripplingPoisonHits takes nothing returns nothing
    local unit target = GetTriggerUnit()
    local unit hero = GetEventDamageSource()
    local integer slow = 80 * GetHeroAbilityLevel(hero,26) / GetHeroLevel(hero)
    local real duration = 10
    local real delay = 0.2
    local string targetstring = I2S(H2I(target))
    local integer cripplecount = GetStoredInteger(udg_gamecache,targetstring,"cripplecount")
    if not GetHandleBoolean(target,"cpdelay") then
        call SetHandleBoolean(target,"cpdelay",true)
        if cripplecount == 0 then
            call Addbuff(target,5,-1)
        endif
        call StoreInteger(udg_gamecache,targetstring,"cripplecount",cripplecount+1)
        call Slow(target,slow,duration)   
        call Msg("CripplingPoisonHits") 
        call TriggerSleepAction(delay)
        call SetHandleBoolean(target,"cpdelay",false)
        call TriggerSleepAction(duration-delay)
        set cripplecount = GetStoredInteger(udg_gamecache,targetstring,"cripplecount")-1
        if cripplecount == 0 then
            call UnitRemoveAbility(target, udg_showbuffs[5])
            call Msg("CripplingPoisonFullEnd")
        endif
        call StoreInteger(udg_gamecache,targetstring,"cripplecount",cripplecount)
        set target = null
        set hero = null
    endif 
endfunction

//====================================================================================================================================================
//Bodyless

//Soul Sap
function SoulSapEnd takes timer updatetimer, timer endtimer, string updatetimerstring, lightning l returns nothing
    local effect targeteffect = I2Effect(GetStoredInteger(udg_gamecache,updatetimerstring, "targeteffect"))
    local effect castereffect = I2Effect(GetStoredInteger(udg_gamecache,updatetimerstring, "castereffect"))
    call PauseTimer(updatetimer)
    call DestroyEffect(targeteffect)
    call DestroyEffect(castereffect)
    call FlushStoredMission(udg_gamecache,updatetimerstring)
    call DestroyLightning(l)
    call DestroyTimer(updatetimer)
    set targeteffect = null
    set castereffect = null
endfunction

function SoulSapEndByTimer takes nothing returns nothing
    local timer endtimer = GetExpiredTimer()
    local timer updatetimer = GetHandleTimer(endtimer,"updatetimer")
    local string updatetimerstring = I2S(H2I(updatetimer))
    local lightning l = I2Lightning(GetStoredInteger(udg_gamecache,updatetimerstring, "l"))
    call SoulSapEnd(updatetimer,endtimer,updatetimerstring,l)
    call DisplayTextToPlayer(Player(0),0,0,"soulsapendbytimer")
    set endtimer = null
    set updatetimer = null
    set l = null
endfunction

function SoulSapUpdate takes nothing returns nothing
    local timer updatetimer = GetExpiredTimer()
    local string updatetimerstring = I2S(H2I(updatetimer))
    local unit hero = I2Unit(GetStoredInteger(udg_gamecache,updatetimerstring,"hero"))
    local unit target = I2Unit(GetStoredInteger(udg_gamecache,updatetimerstring,"target"))
    local lightning l = I2Lightning(GetStoredInteger(udg_gamecache,updatetimerstring,"l"))
    local real life = GetUnitState(hero,UNIT_STATE_LIFE)
    local real steal = 0.1 * GetHeroAbilityLevel(hero,28)
    local real herox = GetWidgetX(hero)
    local real heroy = GetWidgetY(hero)
    local real targetx = GetWidgetX(target)
    local real targety = GetWidgetY(target)
    local real heroz = 70
    local real targetz = 70
    local real distancesquare = herox*herox+2*herox*-targetx+targetx*targetx+heroy*heroy+2*heroy*-targety+targety*targety
    local real maxdistancesquare = 640000
    //call Msg(R2S(distancesquare))
    //call Msg(R2S((herox-targetx)*(herox-targetx)+(heroy-targety)*(heroy-targety)))
    //call Msg(R2S(Pow(herox-targetx,2)+Pow(heroy-targety,2)))
    call MoveLightningEx(l,false,herox,heroy,heroz,targetx,targety,targetz)
    if steal < 1 then
        if GetRandomReal(0,1) > steal then
            set steal = 1
            call UnitDamageTargetNew(hero,target,R2I(steal),2,0,0)
            call SetUnitState(hero,UNIT_STATE_LIFE,life+steal)
        endif
    endif
    if distancesquare > maxdistancesquare or GetUnitState(target,UNIT_STATE_LIFE) == 0 then
        call DisplayTextToPlayer(Player(0),0,0,"soulsapendbycondition")
        call SoulSapEnd(updatetimer,I2Timer(GetStoredInteger(udg_gamecache,updatetimerstring,"endtimer")),updatetimerstring,l)
    endif
    set updatetimer = null
    set hero = null
    set target = null
    set l = null
endfunction

function SoulSapCast takes nothing returns nothing
    local unit hero = GetTriggerUnit()
    local timer updatetimer = CreateTimer()
    local timer endtimer = CreateTimer()
    local unit target = GetSpellTargetUnit()
    local real herox = GetWidgetX(hero)
    local real heroy = GetWidgetY(hero)
    local real targetx = GetWidgetX(target)
    local real targety = GetWidgetY(target)
    local real interval = 0.02
    local real heroz = 90
    local real targetz = 90
    local lightning l = AddLightningEx("DRAL",false,herox,heroy,heroz,targetx,targety,targetz)
    local string updatetimerstring = I2S(H2I(updatetimer))
    local effect targeteffect = AddSpecialEffectTarget("Abilities\\Spells\\Other\\Drain\\DrainCaster.mdl", target, "chest")
    local effect castereffect = AddSpecialEffectTarget("Abilities\\Spells\\Other\\Drain\\DrainTarget.mdl", hero, "chest")
    local real duration = 10
    call StoreInteger(udg_gamecache,updatetimerstring,"l",H2I(l))
    call StoreInteger(udg_gamecache,updatetimerstring,"hero",H2I(hero))
    call StoreInteger(udg_gamecache,updatetimerstring,"target",H2I(target))
    call StoreInteger(udg_gamecache,updatetimerstring,"targeteffect",H2I(targeteffect))
    call StoreInteger(udg_gamecache,updatetimerstring,"castereffect",H2I(castereffect))
    call StoreInteger(udg_gamecache,updatetimerstring,"endtimer",H2I(endtimer))
    call SetHandleHandle(endtimer,"updatetimer",updatetimer)
    call TimerStart(updatetimer,interval,true,function SoulSapUpdate)
    call TimerStart(endtimer,duration,false,function SoulSapEndByTimer)
    call DisplayTextToPlayer(Player(0),0,0,"soulsapcast")
    set targeteffect = null
    set endtimer = null
    set hero = null
    set l = null
    set target = null
    set updatetimer = null
endfunction

//SilencingSouls
function SilencingSoulsHits takes nothing returns nothing
    local unit subject = GetTriggerUnit()
    local unit hero = GetEventDamageSource()
    local string heros = I2S(H2I(hero))
    local group g = I2Group(GetStoredInteger(udg_gamecache,heros,"ssgroup"))
    local real duration = 12* GetHeroAbilityLevel(hero,29) / GetHeroLevel(hero)
    call UnitRemoveAbility(subject,udg_buffs[13])
    if not IsUnitInGroup(subject,g) then
        call GroupAddUnit(g,subject)
        call Msg("unitdmgedbyflood")
        call Msg("silencingsoulshits")
        call Addbuff(subject, 2,duration)  
    endif
    set g = null
    set hero = null
    set subject = null
endfunction

function SilencingSoulsCast takes nothing returns nothing
    local unit hero = GetTriggerUnit()
    local real hx = GetWidgetX(hero)
    local real hy = GetWidgetY(hero)
    //local real facing = GetUnitFacing(hero)*bj_DEGTORAD
    local location spelloc = GetSpellTargetLoc()
    local real spellx = GetLocationX(spelloc)
    local real spelly = GetLocationY(spelloc)
    local real facing = Atan2(spelly-hy, spellx-hx)
    local real areahalf = 150
    local real spellrange = 800
    local real tx
    local real ty
    local integer i
    local real delay = 0.1
    local real delay2 = 1
    local group g = CreateGroup()
    set i = 0
    call SetHandleHandle(hero,"ssgroup",g)
    call Msg("SSSPELLSTARTS")
    call TriggerSleepAction(delay)
    loop
        exitwhen i == 2
        set tx = hx + Cos(facing)*spellrange + Cos(facing+(1-i*2)*bj_PI/2)*areahalf
        set ty = hy + Sin(facing)*spellrange + Sin(facing+(1-i*2)*bj_PI/2)*areahalf
        call CastCorAbilityCor(Player(15),21,1,tx,ty,1,hx,hy,0)
        set i = i + 1
    endloop
    call TriggerSleepAction(delay2)
    call DestroyGroup(g)
    set g = null
    set hero = null
endfunction

//Ghost Aura
function AuraBodylessAttacked takes nothing returns nothing
    local unit attacker = GetAttacker()
    local unit hero = GetTriggerUnit()
    local integer evasion = R2I(100-100/(1+GetUnitAbilityLevel(hero,udg_habils[30])/GetHeroLevel(hero)*4*2))
    call Msg("aurabodylessattacked. evasiondata following...")
    call Msg(GetUnitName(hero))
    call Msg(R2S(GetUnitAbilityLevel(hero,udg_habils[30])/GetHeroLevel(hero)*4*2))
    call Msg(R2S((1+GetUnitAbilityLevel(hero,udg_habils[30])/GetHeroLevel(hero)*4*2)))
    call Msg(R2S(100/(1+GetUnitAbilityLevel(hero,udg_habils[30])/GetHeroLevel(hero)*4*2)))
    call Msg(R2S(100-100/(1+GetUnitAbilityLevel(hero,udg_habils[30])/GetHeroLevel(hero)*4*2)))
    if evasion > 0 then
        call CastWidgetAbility(Player(15),18,evasion,attacker,0)
    endif
    set attacker = null
    set hero = null
endfunction

function AuraUnitDied takes nothing returns nothing
    local unit subject = GetTriggerUnit()
    local string ss = I2S(H2I(subject))
    local group auragroup = I2Group(GetStoredInteger(udg_gamecache,ss,"decrepitauragroup"))
    call GroupRemoveUnit(auragroup,subject)
    set subject = null
    set auragroup = null
endfunction

function DecrepitAuraBuffCheck takes nothing returns nothing
    local unit subject = GetEnumUnit()
    local string ss
    local real range = 900
    //call Msg("decrepitauraBuffCheck")
    if not (GetUnitAbilityLevel(subject,udg_buffs[21]) == 1) then 
    //beetje riscy om alleen een buffcheck te doen
    //de unit kan misschien nog steeds in range zijn.
        //newcode
        if Distance(GetWidgetX(subject),GetWidgetY(subject),GetWidgetX(udg_tempunit),GetWidgetY(udg_tempunit)) > range then
        //
            call Msg("unithasnobuff")
            set ss = I2S(H2I(subject))
            call GroupRemoveUnit(udg_tempgroup,subject)
            call Slow(subject,-GetStoredReal(udg_gamecache,ss,"decrepitauraslow"),-1)
            //call DestroyEffect(sloweffect)
            call FlushStoredReal(udg_gamecache,ss,"decrepitauraslow")
        endif
    endif
    set subject = null
endfunction

function DecrepitAuraSlowRemove takes nothing returns nothing
    local unit subject = GetEnumUnit()
    local string ss = I2S(H2I(subject))
    call UnitRemoveAbility(GetEnumUnit(),udg_buffs[21])
    call Msg("unithasnobuff")
    call GroupRemoveUnit(udg_tempgroup,subject)
    call Slow(subject,-GetStoredReal(udg_gamecache,ss,"decrepitauraslow"),-1)
    //call DestroyEffect(sloweffect)
    call FlushStoredReal(udg_gamecache,ss,"decrepitauraslow")
endfunction

function DecrepitAuraUnlearn takes unit hero returns nothing
    local string hs = I2S(H2I(hero))
    local trigger trig = I2Trigger(GetStoredInteger(udg_gamecache,hs,"decrepitauratrigger"))
    local timer t = I2Timer(GetStoredInteger(udg_gamecache,hs,"decrepitauratimer"))
    local group auragroup = I2Group(GetStoredInteger(udg_gamecache,hs,"decrepitauragroup"))
    local real interval = 1
    call Msg("decrepitauraUnlearn")
    call FlushHandleLocals(trig)
    call FlushHandleLocals(t)
    call DestroyTrigger(trig) 
    call ForGroup(auragroup,function DecrepitAuraSlowRemove)
    call DestroyGroup(auragroup)
    call PauseTimer(t)
    call DestroyTimer(t)
    set trig = null
    set t = null
    set auragroup = null   
endfunction

function DecrepitAuraEnd takes unit hero returns nothing
    local string hs = I2S(H2I(hero))
    local timer t = I2Timer(GetStoredInteger(udg_gamecache,hs,"decrepitauratimer"))
    local trigger trig = I2Trigger(GetStoredInteger(udg_gamecache,hs,"decrepitauratrigger"))
    call Msg("decrepitauraDeactivate")
    call PauseTimer(t)
    call DisableTrigger(trig)
    set trig = null
    set t = null
endfunction

function DecrepitAuraUpdate takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local string timerstring = I2S(H2I(t))
    local group auragroup = I2Group(GetStoredInteger(udg_gamecache,timerstring,"decrepitauragroup"))
    local unit hero = I2Unit(GetStoredInteger(udg_gamecache,timerstring,"hero"))
    set udg_tempgroup = auragroup
    set udg_tempunit = hero
    call ForGroup(auragroup,function DecrepitAuraBuffCheck)
    set t = null
    set hero = null
    set auragroup = null
endfunction

function DecrepitAuraInRange takes nothing returns nothing
    local trigger trig = GetTriggeringTrigger()
    local string trigs = I2S(H2I(trig))
    local unit hero = I2Unit(GetStoredInteger(udg_gamecache,trigs,"hero"))
    local unit subject = GetTriggerUnit()
    local group auragroup = I2Group(GetStoredInteger(udg_gamecache,trigs,"decrepitauragroup")) 
    local real slow = 320*GetUnitAbilityLevel(hero,udg_habils[30])/GetHeroLevel(hero)
    local string ss = I2S(H2I(subject))
    if TargetTypeCondition(subject,hero,33796) and not IsUnitInGroup(subject,auragroup) then
        call Msg(R2S(slow))
        call GroupAddUnit(auragroup,subject)
        call Slow(subject,slow,-1)
        call StoreReal(udg_gamecache,ss,"decrepitauraslow",slow)
        call StoreInteger(udg_gamecache,ss,"decrepitauragroup",H2I(auragroup))
        set auragroup = null
        call Msg("auratargetfound")
    endif
    set hero = null
    set subject = null
    set trig = null
endfunction

function DecrepitAuraActivate takes unit hero returns nothing
    local string hs = I2S(H2I(hero))
    local timer t = I2Timer(GetStoredInteger(udg_gamecache,hs,"decrepitauratimer"))
    local trigger trig = I2Trigger(GetStoredInteger(udg_gamecache,hs,"decrepitauratrigger"))
    local real interval = 1
    call Msg("decrepitauraactivate")
    call TimerStart(t,interval,true,function DecrepitAuraUpdate)
    call EnableTrigger(trig)
    set trig = null
    set t = null
endfunction

function DecrepitAuraLearned takes unit hero returns nothing
    local string hs = I2S(H2I(hero))
    local trigger trig = CreateTrigger()
    local timer t = CreateTimer()
    local string timerstring = I2S(H2I(t))
    local group auragroup = CreateGroup()
    local string trigs = I2S(H2I(trig))
    local real range = 900
    call Msg("decrepitauralearned")
    call StoreInteger(udg_gamecache,timerstring,"decrepitauragroup",H2I(auragroup))
    //Newcode
    call StoreInteger(udg_gamecache,timerstring,"hero",H2I(hero))
    //
    call StoreInteger(udg_gamecache,hs,"decrepitauratrigger",H2I(trig))
    call StoreInteger(udg_gamecache,hs,"decrepitauratimer",H2I(t))
    call StoreInteger(udg_gamecache,hs,"decrepitauragroup",H2I(auragroup))
    call TriggerRegisterUnitInRange(trig,hero,range,null)
    call TriggerAddAction(trig,function DecrepitAuraInRange)
    call DisableTrigger(trig)
    call StoreInteger(udg_gamecache,trigs,"hero",H2I(hero))
    call StoreInteger(udg_gamecache,trigs,"decrepitauragroup",H2I(auragroup))
    call SetHandleHandle(auragroup,"decrepitauragroup",t)
    call DecrepitAuraActivate(hero)
    set trig = null
    set t = null
    set auragroup = null    
endfunction

//Possession
function PossessionPhase2End takes nothing returns nothing
    local timer phase2endtimer = GetExpiredTimer()
    local string phase2endtimerstring = I2S(H2I(phase2endtimer))
    local unit hero = I2Unit(GetStoredInteger(udg_gamecache,phase2endtimerstring,"hero"))
    local string herostring = I2S(H2I(hero))
    local player targetplayer = I2Player(GetStoredInteger(udg_gamecache,phase2endtimerstring,"targetplayer"))
    local unit target = I2Unit(GetStoredInteger(udg_gamecache,herostring,"possessiontarget"))
    local timer anitimer = I2Timer(GetStoredInteger(udg_gamecache,herostring,"possessionanitimer"))
    call FlushStoredMission(udg_gamecache,phase2endtimerstring)
    call PauseTimer(anitimer)
    call FlushHandleLocals(anitimer)
    call DestroyTimer(anitimer)
    call PauseUnit(hero, false)
    call UnitRemoveAbility(hero, 'Avul')
    call ResetUnitAnimation(hero)
    call SetUnitOwner(target,targetplayer,true)
    call DisplayTextToPlayer(Player(0),0,0,"possessionend")
    set targetplayer = null
    set hero = null
    set target = null
endfunction

function PossessionPhase2Start takes unit hero returns nothing
    local string herostring = I2S(H2I(hero))
    local unit target = I2Unit(GetStoredInteger(udg_gamecache,herostring,"possessiontarget"))
    local player heroplayer = GetOwningPlayer(hero)
    local timer phase2endtimer = CreateTimer()
    local player targetplayer = GetOwningPlayer(target)
    local real duration = 40 * GetHeroAbilityLevel(hero,31) / GetHeroLevel(hero)
    call UnitAddAbility(hero, 'Avul')
    call SetUnitOwner(target,heroplayer,true)
    call SetHandleHandle(phase2endtimer,"hero",hero)
    call SetHandleHandle(phase2endtimer,"targetplayer",targetplayer)
    call TimerStart(phase2endtimer,duration,false,function PossessionPhase2End)
    call DisplayTextToPlayer(Player(0),0,0,"possessionphase1end")
    set target = null
    set heroplayer = null
    set targetplayer = null
    set phase2endtimer = null
endfunction

function PossessionPhase1End takes unit hero returns nothing
    local string herostring = I2S(H2I(hero))
    local effect effect1 = I2Effect(GetStoredInteger(udg_gamecache,herostring,"possessiontargeteffect"))
    local effect effect2 = I2Effect(GetStoredInteger(udg_gamecache,herostring,"possessioncastereffect"))
    local unit target = I2Unit(GetStoredInteger(udg_gamecache,herostring,"possessiontarget"))
    if effect1 == null then
        call Msg("effect1 = null")
    endif
    call DestroyEffect(effect1)
    call DestroyEffect(effect2)
    call PauseUnit(target,false)
    call Msg("possessionphase1end")
    set effect1 = null
    set effect2 = null
    set target = null
endfunction

function PossessionPhase1EndByTimer takes nothing returns nothing
    local timer phase1endtimer = GetExpiredTimer()
    local string phase1endtimerstring = I2S(H2I(phase1endtimer))
    local unit hero = I2Unit(GetStoredInteger(udg_gamecache,phase1endtimerstring,"hero"))
    call FlushStoredMission(udg_gamecache,phase1endtimerstring)
    call PossessionPhase1End(hero)
    call PossessionPhase2Start(hero)
    //call PauseUnit(hero,false)
    call DestroyTimer(phase1endtimer)
    set hero = null
    set phase1endtimer = null
    call Msg("possessionphase1endbytimer")
endfunction

function PossessionInterrupt takes nothing returns nothing
    local unit hero = GetTriggerUnit()
    local string herostring = I2S(H2I(hero))
    local timer phase1endtimer = I2Timer(GetStoredInteger(udg_gamecache,herostring,"possessionphase1endtimer"))
    local timer anitimer = I2Timer(GetStoredInteger(udg_gamecache,herostring,"possessionanitimer"))
    call FlushStoredInteger(udg_gamecache,herostring,"possessionphase1endtimer")
    call FlushHandleLocals(phase1endtimer)
    call DestroyTimer(phase1endtimer)
    call PauseTimer(anitimer)
    call FlushHandleLocals(anitimer)
    call PauseUnit(hero,false)
    call DestroyTimer(anitimer)
    call PossessionPhase1End(hero)
    call Msg("possessioninterrupt")
    set anitimer = null
    set phase1endtimer = null
    set hero = null
endfunction

function AniPlay takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local unit hero = GetHandleUnit(t,"hero")
    call SetUnitAnimationByIndex(hero,3)
    set t = null
    set hero = null
endfunction

function PossessionSpellStarts takes nothing returns nothing
    local unit hero = GetTriggerUnit()
    local unit target = GetSpellTargetUnit()
    local real delay = 1
    local real castingtime = 12 * GetHeroAbilityLevel(hero,31) / GetHeroLevel(hero)
    local string herostring = I2S(H2I(hero))
    local timer phase1endtimer = CreateTimer()
    local effect effect1
    local effect effect2
    local real interval = 1.33
    local timer anitimer = CreateTimer()
    call SetHandleHandle(anitimer,"hero",hero)
    call TriggerSleepAction(0)
    call BJDebugMsg(GetUnitName(target))
    call PauseUnit(hero,true)
    call PauseUnit(target,true)
    set effect1 = AddSpecialEffectTarget("Abilities\\Spells\\Undead\\Possession\\PossessionTarget.mdl",target,"overhead")
    set effect2 = AddSpecialEffectTarget("Abilities\\Spells\\Undead\\Possession\\PossessionCaster.mdl",hero,"overhead")
    call StoreInteger(udg_gamecache,herostring,"possessiontargeteffect",H2I(effect1))
    call StoreInteger(udg_gamecache,herostring,"possessioncastereffect",H2I(effect2))
    call StoreInteger(udg_gamecache,herostring,"possessiontarget",H2I(target))
    call StoreInteger(udg_gamecache,herostring,"possessionanitimer",H2I(anitimer))
    call StoreInteger(udg_gamecache,herostring,"possessionphase1endtimer",H2I(phase1endtimer))
    call SetHandleHandle(phase1endtimer,"hero",hero)
    call TimerStart(phase1endtimer,castingtime,false,function PossessionPhase1EndByTimer)
    call DisplayTextToPlayer(Player(0),0,0,"possessioncast")
    call TimerStart(anitimer,interval,true,function AniPlay)
    set anitimer = null
    set effect2 = null
    set effect1 = null
    set hero = null
    set target = null
    set phase1endtimer = null
endfunction

//=====================================================================================================================================================
//High Inquisitor

//Ambush
function AmbushInRange takes nothing returns nothing
    local trigger trig = GetTriggeringTrigger()
    local string trigstring = I2S(H2I(trig))
    local unit ambusher = I2Unit(GetStoredInteger(udg_gamecache,trigstring,"ambusher"))
    local unit hero = I2Unit(GetStoredInteger(udg_gamecache,trigstring,"hero"))
    local unit subject = GetTriggerUnit()
    local real delay = 2
    local real wait = 1
    local real duration = 20 * GetHeroAbilityLevel(hero,32) / GetHeroLevel(hero)
    local real facing = bj_RADTODEG*Angle(GetWidgetX(ambusher),GetWidgetY(ambusher),GetWidgetX(subject),GetWidgetY(subject))
    local integer targetypeint = 4100
    if TargetTypeCondition(subject,ambusher,targetypeint) then
        call FlushStoredMission(udg_gamecache,trigstring)
        call DestroyTrigger(trig)
        call SetUnitFacingTimed(ambusher,facing,1)
        call TriggerSleepAction(wait)
        //call PauseUnit(ambusher,false)
        call IssueTargetOrder(ambusher,"ensnare",subject)
        call TriggerSleepAction(delay)
        call RemoveUnit(ambusher)
        call TriggerSleepAction(duration-delay)
        call UnitRemoveAbility(subject,udg_buffs[19])
        call UnitRemoveAbility(subject,udg_buffs[20])
    endif
    set ambusher = null
    set hero = null
    set subject = null
endfunction
        
function AmbushSpellStarts takes nothing returns nothing
    local unit hero = GetTriggerUnit()
    local location targetloc = GetSpellTargetLoc()
    local real targetx = GetLocationX(targetloc)
    local real targety = GetLocationY(targetloc)
    local player p = GetTriggerPlayer()
    local trigger ambushinrange = CreateTrigger()
    //local unit ambusher = CreateUnit(p,udg_unittypes[1],targetx,targety,270)
    local unit ambusher = CreateUnit(Player(udg_player2force[GetPlayerId(p)]),udg_unittypes[1],targetx,targety,270)
    local real duration = 120 * GetHeroAbilityLevel(hero,32) / GetHeroLevel(hero)
    local real range = 600
    local effect effect1
    local effect effect2
    local real delay = 1
    local real wait = 1
    call RemoveLocation(targetloc)
    call SetHandleHandle(ambushinrange,"ambusher",ambusher)
    call SetHandleHandle(ambushinrange,"hero",hero)
    call TriggerAddAction(ambushinrange, function AmbushInRange)
    //call PauseUnit(ambusher,true)
    set effect1 = AddSpecialEffectTarget("Abilities\\Spells\\Human\\MassTeleport\\MassTeleportTo.mdl",ambusher,"origin")
    set effect2 = AddSpecialEffectTarget("Abilities\\Spells\\Human\\MassTeleport\\MassTeleportTarget.mdl",ambusher,"origin")
    call DestroyEffectWait(effect1,delay)
    call DestroyEffectWait(effect2,delay)
    call DisplayTextToPlayer(Player(0),0,0,"ambushcast")
    call TriggerSleepAction(wait)
    call TriggerRegisterUnitInRange(ambushinrange, ambusher, range, null)
    call DisplayTextToPlayer(Player(0),0,0,"ambushactivate")
    call TriggerSleepAction(duration)
    call DisplayTextToPlayer(Player(0),0,0,"ambushend")
    call RemoveUnit(ambusher)
    set targetloc = null
    set ambusher = null
    set effect1 = null
    set effect2 = null
    set hero = null
    set p = null
endfunction

//Sentry
function SentryCastTreeFind takes nothing returns nothing
    local destructable tree = GetEnumDestructable()
    local real treex = GetWidgetX(tree)
    local real treey = GetWidgetY(tree)
    local real halfsizesqr = 10000
    local real distancesqr1 = DistanceSqr(treex,treey,udg_tempreals[1],udg_tempreals[2])
    if (distancesqr1 < udg_tempreals[0] or udg_tempdest == null) and distancesqr1 <= halfsizesqr then
        set udg_tempreals[0] = distancesqr1
        call DisplayTextToPlayer(Player(0),0,0,"treeselected")
        set udg_tempdest = tree
    endif
    set tree = null
endfunction

function TreeFilter takes nothing returns boolean
    local destructable dest = GetFilterDestructable()
    local boolean b
    call DisplayTextToPlayer(Player(0),0,0,"possibletreefound")
    if GetDestructableTypeId(dest) == udg_desttypes[0] then
        set b = true
    endif
    set dest = null
    return b
endfunction

function SentryCast takes nothing returns nothing
    local unit hero = GetTriggerUnit()
    local real herox = GetWidgetX(hero)
    local location targetloc = GetSpellTargetLoc()
    local real targetx = GetLocationX(targetloc)
    local real targety = GetLocationY(targetloc)
    local unit sentry
    local real halfsize = 100
    local player p = GetTriggerPlayer()
    local real duration = 120 * GetHeroAbilityLevel(hero,33) / GetHeroLevel(hero)
    local rect targetarea = Rect(targetx-halfsize,targety-halfsize,targetx+halfsize,targety+halfsize)
    local effect effect1
    local effect effect2
    local real delay = 1
    set udg_tempreals[1] = targetx
    set udg_tempreals[2] = targety
    set udg_tempdest = null
    call EnumDestructablesInRect(targetarea,Condition(function TreeFilter),function SentryCastTreeFind)
    if udg_tempdest == null then
        set sentry = CreateUnit(p,udg_unittypes[0],targetx,targety,270)
    else
        call DisplayTextToPlayer(Player(0),0,0,"finaltreesfound")
        set targetx = GetWidgetX(udg_tempdest) - 30
        set targety = GetWidgetY(udg_tempdest) - 40
        set sentry = CreateUnit(p,udg_dummyunittypes[15],targetx,targety,250)
    endif
    set effect1 = AddSpecialEffectTarget("Abilities\\Spells\\Human\\MassTeleport\\MassTeleportTo.mdl",sentry,"origin")
    set effect2 = AddSpecialEffectTarget("Abilities\\Spells\\Human\\MassTeleport\\MassTeleportTarget.mdl",sentry,"origin")
    call DestroyEffectWait(effect1,delay)
    call DestroyEffectWait(effect2,delay)
    call RemoveLocation(targetloc)
    call RemoveRect(targetarea)
    call DisplayTextToPlayer(Player(0),0,0,"sentrycast")
    call TriggerSleepAction(duration)
    call DisplayTextToPlayer(Player(0),0,0,"sentryend")
    call RemoveUnit(sentry)
    set targetloc = null
    set sentry = null
    set hero = null
    set effect1 = null
    set effect2 = null
    set targetarea = null
    set p = null
endfunction

//Cage
function CageCast takes nothing returns nothing
    local unit hero = GetTriggerUnit()
    local unit target = GetSpellTargetUnit()
    local unit cage
    local integer newcage = 10
    local integer level = GetHeroAbilityLevel(hero, 32)
    local real targetx = GetWidgetX(target)
    local real targety = GetWidgetY(target)
    local player p = GetOwningPlayer(hero)
    local real duration = 40 * level / GetHeroLevel(hero)
    local real life = duration * 20
    local effect effect1
    local effect effect2
    local real delay = 1
    local unit collider
    call ShowUnitHide(target)
    call PauseUnit(target,true)
    if duration > newcage then
        set cage = CreateUnit(p,udg_unittypes[7],targetx,targety,0)
    else
        set cage = CreateUnit(p,udg_unittypes[8],targetx,targety,0)
    endif
    call ShowUnitHide(cage)
    set collider = CreateUnit(p,udg_dummyunittypes[13],targetx+10,targety+10,0)
    call ShowUnitShow(cage)
    //not really nessecary I believe
    call SetUnitCor(collider,targetx+10,targety+10)
    call SetUnitX(cage,targetx)
    call SetUnitY(cage,targety)
    //
    set effect1 = AddSpecialEffect("Abilities\\Spells\\Human\\MassTeleport\\MassTeleportTo.mdl",targetx,targety)
    set effect2 = AddSpecialEffect("Abilities\\Spells\\Human\\MassTeleport\\MassTeleportTarget.mdl",targetx,targety)
    call DestroyEffectWait(effect1,delay)
    call DestroyEffectWait(effect2,delay)
    call SetUnitState(cage,UNIT_STATE_MAX_LIFE,life)
    call SetHandleHandle(cage,"prisoner",target)
    call SetHandleHandle(cage,"collider",collider)
    if duration != 0 then
        call UnitApplyTimedLife(cage, 'BTLF', duration)
    endif
    set hero = null
    set target = null
    set cage = null
    set p = null
    set effect1 = null
    set effect2 = null
    call DisplayTextToPlayer(Player(0),0,0,"cagecast")
endfunction

function Cagebreak takes nothing returns nothing
    local unit cage = GetDyingUnit()
    local string cagestring = I2S(H2I(cage))
    local real wait = 2
    local unit prisoner = I2Unit(GetStoredInteger(udg_gamecache,cagestring,"prisoner"))
    local unit collider = I2Unit(GetStoredInteger(udg_gamecache,cagestring,"collider"))
    call RemoveUnit(collider)
    call ShowUnitShow(prisoner)
    call PauseUnit(prisoner,false)
    call DisplayTextToPlayer(Player(0),0,0,"cagebreak")
    call TriggerSleepAction(wait)
    call FlushStoredMission(udg_gamecache,cagestring)
    call RemoveUnit(cage)
    set cage = null
endfunction

function GatherMobTeleportWait takes nothing returns nothing
    local unit subject = udg_tempunit
    local real delay = 0.5
    call TriggerSleepAction(delay)
    call FlushHandleLocals(subject)
    call RemoveUnit(subject)
    set subject = null
endfunction

function GatherMobOff takes unit hero returns nothing
    local string herostring = I2S(H2I(hero))
    local timer updatetimer = I2Timer(GetStoredInteger(udg_gamecache,herostring,"gathermobupdatetimer"))
    local string updatetimerstring = I2S(H2I(updatetimer))
    local group mobgroup = I2Group(GetStoredInteger(udg_gamecache,updatetimerstring,"mobgroup"))
    local unit subject
    local integer i = 0
    local real x
    local real y
    local real delay = 1
    local effect effect1
    local effect effect2
    call BJDebugMsg(GetUnitName(hero))
    call PauseTimer(updatetimer)
    call DestroyTimer(updatetimer)
    call FlushStoredInteger(udg_gamecache,herostring,"gathermobupdatetimer")
    loop
        set subject = FirstOfGroup(mobgroup)
        exitwhen subject == null
        set effect1 = AddSpecialEffectTarget("Abilities\\Spells\\Human\\MassTeleport\\MassTeleportTo.mdl",subject,"origin")
        set effect2 = AddSpecialEffectTarget("Abilities\\Spells\\Human\\MassTeleport\\MassTeleportTarget.mdl",subject,"origin")
        set udg_tempunit = subject
        call GroupRemoveUnit(mobgroup,subject)
        call PauseUnit(subject, true)
        call ExecuteFunc("GatherMobTeleportWait")
        call DestroyEffectWait(effect1,delay)
        call DestroyEffectWait(effect2,delay)
    endloop
    call DestroyGroup(mobgroup)
    call DisplayTextToPlayer(Player(0),0,0,"gathermoboff")
    call FlushStoredMission(udg_gamecache, updatetimerstring)
    set mobgroup = null
    set subject = null
    set updatetimer = null
endfunction

function FemaleMobHits takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local string tstring = I2S(H2I(t))
    local unit missile = I2Unit(GetStoredInteger(udg_gamecache,tstring,"missile"))
    local effect torcheffect = I2Effect(GetStoredInteger(udg_gamecache,tstring,"torcheffect"))
    call RemoveUnit(missile)
    call DestroyEffect(torcheffect)
    set torcheffect = null
    set t = null
    set missile = null
endfunction

function FemaleMobAttacks takes nothing returns nothing
    local real zvelocity0 = 2
    local unit subject = GetAttacker()
    local unit target = GetTriggerUnit()
    local real x = GetWidgetX(subject)
    local real y = GetWidgetY(subject)
    local unit missile = CreateUnit(Player(15),udg_dummyunittypes[0],x,y,0)
    local real x2 = GetWidgetX(target)
    local real y2 = GetWidgetY(target)
    local real angle = Angle(x,y,x2,y2)
    local real mhorispeed = 500
    local real h0 = 50
    local real hitheight = 30
    local real aoa = bj_PI*1/4
    local string endfunc = "FemaleMobHits"
    local effect torcheffect = AddSpecialEffectTarget("Doodads\\LordaeronSummer\\Props\\TorchHuman\\TorchHuman.mdl",missile,"origin")
    local timer t = StartSmartFlight(missile,target,hitheight,aoa, h0, mhorispeed, endfunc, true, null)
    local string ts = I2S(H2I(t))
    
    call StoreInteger(udg_gamecache,ts,"torcheffect",H2I(torcheffect))
    set torcheffect = null
    set subject = null
    set target = null
    set missile = null
endfunction

function GatherMobUpdate takes nothing returns nothing
    local timer updatetimer = GetExpiredTimer()
    local string updatetimerstring = I2S(H2I(updatetimer))
    local unit hero = I2Unit(GetStoredInteger(udg_gamecache,updatetimerstring,"hero"))
    local group mobgroup = I2Group(GetStoredInteger(udg_gamecache,updatetimerstring,"mobgroup"))
    local integer mobcount = CountUnitsInGroup(mobgroup)
    local player p = GetOwningPlayer(hero)
    local real herox = GetWidgetX(hero)
    local real heroy = GetWidgetY(hero)
    local real x
    local real y
    local real mindistance = 300
    local real maxdistance = 500
    local real distance = GetRandomReal(mindistance,maxdistance)
    local real angle
    local effect effect1
    local effect effect2
    local unit newmobster
    local integer maxmobs = 11
    local real delay = 1
    local integer mobsleft = GetStoredInteger(udg_gamecache,updatetimerstring,"mobsleft") - 1
    local real dmg = 5 * GetUnitAbilityLevel(hero,udg_habils[35])
    local real ias = 5 * GetUnitAbilityLevel(hero,udg_habils[35])
    local real lif = 20 * GetUnitAbilityLevel(hero,udg_habils[35])
    local real arm = 2 * GetUnitAbilityLevel(hero,udg_habils[35])
    set angle = GetRandomReal(0,2*bj_PI)
    set x = herox + Cos(angle) * distance
    set y = heroy + Sin(angle) * distance
    if GetRandomInt(0,2) < 3 then
        set newmobster = CreateUnit(p,udg_unittypes[3],x,y,240)
    else
        set newmobster = CreateUnit(p,udg_unittypes[4],x,y,240)
    endif
    call ChangeBonus(newmobster,dmg,0,true)
    call ChangeBonus(newmobster,ias,1,true)
    call ChangeBonus(newmobster,lif,2,true)
    call ChangeBonus(newmobster,arm,3,true)
    call SetHandleHandle(newmobster,"mobgroup",mobgroup)
    call GroupAddUnit(mobgroup,newmobster)
    set effect1 = AddSpecialEffectTarget("Abilities\\Spells\\Human\\MassTeleport\\MassTeleportTo.mdl",newmobster,"origin")
    set effect2 = AddSpecialEffectTarget("Abilities\\Spells\\Human\\MassTeleport\\MassTeleportTarget.mdl",newmobster,"origin")
    call DestroyEffectWait(effect1,delay)
    call DestroyEffectWait(effect2,delay)
    if mobsleft == 0 then
        call PauseTimer(updatetimer)
    else
        call StoreInteger(udg_gamecache,updatetimerstring,"mobsleft",mobsleft)
    endif
    set effect1 = null
    set effect2 = null
    set newmobster = null
    set mobgroup = null
    set p = null
    set hero = null
    set updatetimer = null
endfunction

function GatherMobCast takes nothing returns nothing
    local unit hero = GetTriggerUnit()
    local real interval = 3
    local timer updatetimer = CreateTimer()
    local string updatetimerstring = I2S(H2I(updatetimer))
    local group mobgroup = CreateGroup()
    local integer mobcount = 11
    call StoreInteger(udg_gamecache,updatetimerstring,"mobgroup",H2I(mobgroup))
    call StoreInteger(udg_gamecache,updatetimerstring,"hero",H2I(hero))
    call StoreInteger(udg_gamecache,updatetimerstring,"mobsleft",mobcount)
    call SetHandleHandle(hero,"gathermobupdatetimer",updatetimer)
    call TimerStart(updatetimer,interval,true,function GatherMobUpdate)
    call DisplayTextToPlayer(Player(0),0,0,"gathermobcast")
    set mobgroup = null
    set hero = null
    set updatetimer = null
endfunction

function GatherMobNullmana takes nothing returns nothing
    local unit hero = GetTriggerUnit()
    call DisplayTextToPlayer(Player(0),0,0,"gathermobnullmana")
    call GatherMobOff(hero)
    set hero = null
endfunction

function GatherMobLearned takes nothing returns nothing
    local trigger nullmanatrig = CreateTrigger()
    local unit hero = GetTriggerUnit()
    call SetHandleHandle(hero,"nullmanatrig",nullmanatrig)
    call TriggerAddAction(nullmanatrig,function GatherMobNullmana)
    call TriggerRegisterUnitStateEvent(nullmanatrig,hero,UNIT_STATE_MANA,EQUAL,0)
    set hero = null
    set nullmanatrig = null
endfunction

function MTMobDeath takes nothing returns nothing
    local unit subject = GetDyingUnit()
    local string subjectstring = I2S(H2I(subject))
    local group mobgroup = I2Group(GetStoredInteger(udg_gamecache,subjectstring,"mobgroup"))
    call DisplayTextToPlayer(Player(0),0,0,"gathermobdeath")
    if mobgroup != null then
        call GroupRemoveUnit(mobgroup,subject)
        call FlushStoredInteger(udg_gamecache,subjectstring,"mobgroup")
        set mobgroup = null
    endif
    set subject = null
endfunction

//==========================================================================================================
//GrandMarshal

//Killed Your Fathers
function KilledYourFathersOff takes unit hero returns nothing
    local string herostring = I2S(H2I(hero))
    local timer updatetimer = I2Timer(GetStoredInteger(udg_gamecache,herostring,"KYFupdatetimer"))
    call DisplayTextToPlayer(Player(0),0,0,"KYFend")
    call FlushStoredInteger(udg_gamecache,herostring,"KYFupdatetimer")
    call PauseTimer(updatetimer)
    call FlushHandleLocals(updatetimer)
    call DestroyTimer(updatetimer)
    set hero = null
    set updatetimer = null
endfunction

function KilledYourFathersCondition takes nothing returns boolean
    if TargetTypeCondition(GetFilterUnit(),udg_tempunit,33796) then
        call Msg("KYFtargetfound")
    endif
    return TargetTypeCondition(GetFilterUnit(),udg_tempunit,33796)
endfunction

function KilledYourFathersUpdate takes nothing returns nothing
    local timer updatetimer = GetExpiredTimer()
    local unit hero = GetHandleUnit(updatetimer,"hero")
    local player p = GetOwningPlayer(hero)
    local real range = 700
    local real herox = GetWidgetX(hero)
    local real heroy = GetWidgetY(hero)
    local real radius = 700
    local unit target
    local effect effect1
    local group g = CreateGroup()
    local real delay = 1
    call Msg("KYFupdate")
    set udg_tempunit = hero
    call GroupEnumUnitsInRange(g,herox,heroy,radius,Condition(function KilledYourFathersCondition))
    set target = GroupPickRandomUnit(g)
    if target != null then
        call IssueTargetOrder(target,"attack",hero)
        set effect1 = AddSpecialEffectTarget("Abilities\\Spells\\Other\\TalkToMe\\TalkToMe.mdl",hero,"overhead")
        call DestroyEffectWait(effect1,delay)
    endif
    call DestroyGroup(g)
    set effect1 = null
    set g = null
    set target = null
    set updatetimer = null
    set p = null
    set hero = null
endfunction

function KilledYourFathersCast takes nothing returns nothing
    local unit hero = GetTriggerUnit()
    local real interval = 0.1 * GetHeroLevel(hero) / GetHeroAbilityLevel(hero,36)
    local timer updatetimer = CreateTimer()
    call SetHandleHandle(hero,"KYFupdatetimer",updatetimer)
    call SetHandleHandle(updatetimer,"hero",hero)
    call TimerStart(updatetimer,interval,true,function KilledYourFathersUpdate)
    call DisplayTextToPlayer(Player(0),0,0,"KYFcast")
    set updatetimer = null
    set hero = null
endfunction

function KilledYourFathersNullmana takes nothing returns nothing
    local unit hero = GetTriggerUnit()
    call Msg("KYFnullmana")
    call KilledYourFathersOff(hero)
    set hero = null
endfunction

function KilledYourFathersLearned takes nothing returns nothing
    local trigger nullmanatrig = CreateTrigger()
    local unit hero = GetTriggerUnit()
    call SetHandleHandle(hero,"nullmanatrig",nullmanatrig)
    call TriggerAddAction(nullmanatrig,function KilledYourFathersNullmana)
    call TriggerRegisterUnitStateEvent(nullmanatrig,hero,UNIT_STATE_MANA,EQUAL,0)
    set hero = null
    set nullmanatrig = null
endfunction

function TrampleDeactivate takes unit hero returns nothing
    local string herostring = I2S(H2I(hero))
    local trigger trig = I2Trigger(GetStoredInteger(udg_gamecache,herostring,"trampletrig"))
    local effect effect1 = I2Effect(GetStoredInteger(udg_gamecache,herostring,"trampleffect1"))
    call FlushHandleLocals(trig)
    call DestroyEffect(effect1)
    call DestroyTrigger(trig)
    set trig = null
    set effect1 = null
endfunction

function TrampleInRange takes nothing returns nothing
    local trigger trig = GetTriggeringTrigger()
    local string trigstring = I2S(H2I(trig))
    local unit hero = I2Unit(GetStoredInteger(udg_gamecache,trigstring,"hero"))
    local integer dmg = 50 * GetHeroAbilityLevel(hero,37)
    local unit target = GetTriggerUnit()
    local effect effect1
    local real delay = 1
    local integer targettypeint = 21508
    if TargetTypeCondition(target,hero,targettypeint) then
        call DisplayTextToPlayer(Player(0),0,0,"trampleinrange")
        set effect1 = AddSpecialEffectTarget("Abilities\\Spells\\Other\\Stampede\\StampedeMissileDeath.mdl",target,"overhead")        
        call UnitDamageTargetNew(hero,target,dmg,2,0,0)
        call DestroyEffectWait(effect1,delay)
        set effect1 = null
    endif
    set hero = null
    set target = null
endfunction

function TrampleActivate takes unit hero returns nothing
    local trigger trig = CreateTrigger()
    local real range = 160
    local effect effect1
    call SetHandleHandle(hero,"trampletrig",trig)
    call TriggerAddAction(trig, function TrampleInRange)
    call SetHandleHandle(trig,"hero",hero)
    set effect1 = AddSpecialEffectTarget("Abilities\\Spells\\Human\\DevotionAura\\DevotionAura.mdl",hero,"origin")
    call SetHandleHandle(hero,"trampleeffect1",effect1)
    call TriggerRegisterUnitInRange(trig, hero, range, null)
    call DisplayTextToPlayer(Player(0),0,0,"trampleactivate")
    set effect1 = null
    set hero = null
    set trig = null
endfunction

function TrampleLearned takes nothing returns nothing
    local unit hero = GetTriggerUnit()
    call DisplayTextToPlayer(Player(0),0,0,"tramplelearned")
    call TrampleActivate(hero)
    set hero = null
endfunction

function TrampleEnd takes unit hero returns nothing
    local trigger trig = GetHandleTrigger(hero,"trampletrig")
    call FlushHandleLocals(trig)
    call DestroyTrigger(trig)
    set trig = null
endfunction

function FallBackSpellStarts takes nothing returns nothing
    local unit hero = GetTriggerUnit()
    local real haste = 400 * GetUnitAbilityLevel(hero,udg_habils[38]) / GetHeroLevel(hero)
    local real interval = 1
    local real herox = GetWidgetX(hero)
    local real heroy = GetWidgetY(hero)
    local location spelloc = GetSpellTargetLoc()
    local real targetx = GetLocationX(spelloc)
    local real targety = GetLocationY(spelloc)
    local real movespeed = GetUnitMoveSpeed(hero) + haste
    local real duration = Distance(herox,heroy,targetx,targety) / movespeed
    local integer heal = R2I(200 * GetUnitAbilityLevel(hero,udg_habils[38])/duration)
    local player p = GetTriggerPlayer()
    call Hot(hero,heal,interval,duration)
    call SetUnitOwner(hero,Player(15),false)
    call Addbuff(hero,8,duration)
    call Slow(hero,-haste,duration)
    call IssuePointOrder(hero,"move",targetx,targety)
    //call PauseUnit(hero,true)
    call DisplayTextToPlayer(Player(0),0,0,"fallbackcast")
    call TriggerSleepAction(duration)
    //call PauseUnit(hero,false)
    call SetUnitOwner(hero,p,false)
    call SelectUnitForPlayerSingle(hero,p)
    call IssueImmediateOrder(hero,"stop")
    call RemoveLocation(spelloc)
    set p = null
    set spelloc = null
    set hero = null
endfunction

function GrandChargeCast takes nothing returns nothing

endfunction

//==================================================================================================================
//Scarab King
//Disect
function DisectEnd takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local string ts = I2S(H2I(t))
    local unit hero = I2Unit(GetStoredInteger(udg_gamecache,ts,"hero"))
    local unit target = I2Unit(GetStoredInteger(udg_gamecache,ts,"subject")) 
    local integer dmg = 100 * GetHeroAbilityLevel(hero, 40)
    call PauseUnit(target,false)
    call UnitDamageTargetNew(hero, target, dmg, 2, 0, 0)
    set hero = null
    set t = null
    set target = null
endfunction

function DisectCast takes nothing returns nothing
    local unit hero = GetTriggerUnit()
    local unit target = GetSpellTargetUnit()
    local real zvelocity0 = 10
    local timer t = StartDumbFlight(target,0,0,zvelocity0,0,"DisectEnd")
    call SetHandleHandle(t,"hero",hero)
    call GroupAddUnit(udg_busyunits,target)
    call PauseUnit(target,true)
    set hero = null
    set target = null
endfunction

function BurrowFinish takes nothing returns nothing
    local unit hero = GetTriggerUnit()
    call SetUnitAnimationByIndex(hero,7)
    call PauseUnit(hero, true)    
    set hero = null
endfunction

function SandStormCast takes nothing returns nothing

endfunction

function FlyCast takes nothing returns nothing

endfunction

//===========================================================================================================
//Elven Prince

//Enchant Glaives
function EnchantGlaivesUpdate takes timer updatetimer returns nothing
    local string updatetimerstring = I2S(H2I(updatetimer))
    local unit hero = I2Unit(GetStoredInteger(udg_gamecache,updatetimerstring,"hero"))
    local real i = 1
    local real glaivenumber = 6
    local real x
    local real y
    local real herox = GetWidgetX(hero)
    local real heroy = GetWidgetY(hero)
    local unit subject
    local integer ticks = GetStoredInteger(udg_gamecache,updatetimerstring,"ticks")
    local real distance = 100
    local real gradiantanglespeed = 1
    local real dt = 0.02
    local real interval = 0.51
    //er moet gelden (360*dt=7.2)/interval=een geheel getal; dus interval = 7.2 / geheel getal.
    local real radius = 250
    local integer dmg
    loop                
        exitwhen i > glaivenumber
        set subject = I2Unit(GetStoredInteger(udg_gamecache,updatetimerstring,"glaive#"+I2S(R2I(i))))
        if ModuloReal(i,2) == 0 then
            set x = herox + Cos((i*2/glaivenumber+ticks*gradiantanglespeed*dt)*bj_PI)*distance
            set y = heroy + Sin((i*2/glaivenumber+ticks*gradiantanglespeed*dt)*bj_PI)*distance
        else
            set x = herox + Cos((i*2/glaivenumber-ticks*gradiantanglespeed*dt)*bj_PI)*distance
            set y = heroy + Sin((i*2/glaivenumber-ticks*gradiantanglespeed*dt)*bj_PI)*distance
        endif
        call SetUnitX(subject,x)
        call SetUnitY(subject,y)
        set i = i + 1
    endloop
    set subject = null
    call StoreInteger(udg_gamecache,updatetimerstring,"ticks",ModuloInteger(ticks+1,R2I(360/gradiantanglespeed)))
    if ModuloReal(ticks*dt,interval) == 0 then
        set dmg = 15 * GetHeroAbilityLevel(hero,44)
        call UnitDamageArea(hero,herox,heroy,radius,16388,dmg,2,0,0)
    endif
    set hero = null
endfunction

function EnchantGlaivesUpdateByTimer takes nothing returns nothing
    local timer updatetimer = GetExpiredTimer()
    call EnchantGlaivesUpdate(updatetimer)
    set updatetimer = null
endfunction

function EnchantGlaivesActivate takes unit hero returns nothing
    local unit array glaives
    local integer i = 1
    local integer glaivenumber = 6
    local effect array effects
    local timer updatetimer = CreateTimer()
    local player p = GetOwningPlayer(hero)
    local real dt = 0.02
    local real height = 50
    local string updatetimerstring = I2S(H2I(updatetimer))
    loop
        exitwhen i > glaivenumber
        set glaives[i] = GetaCaster(p,0,0,0,0,height)
        call SetUnitScale(glaives[i],0.40,0.40,0.40)
        call StoreInteger(udg_gamecache,updatetimerstring,"glaive#"+I2S(i),H2I(glaives[i]))
        set i = i + 1
    endloop
    call StoreInteger(udg_gamecache,updatetimerstring,"hero",H2I(hero))
    call SetHandleHandle(hero,"enchantglaivesupdatetimer",updatetimer)
    call EnchantGlaivesUpdate(updatetimer)
    call TimerStart(updatetimer,dt,true,function EnchantGlaivesUpdateByTimer)
    set i = 1
    loop
        exitwhen i > glaivenumber
        set effects[i] = AddSpecialEffectTarget("Abilities\\Weapons\\GlaiveMissile\\GlaiveMissile.mdl",glaives[i],"origin")
        call StoreInteger(udg_gamecache,updatetimerstring,"effect#"+I2S(i),H2I(effects[i]))
        set glaives[i] = null
        set effects[i] = null
        set i = i + 1
    endloop
    call DisplayTextToPlayer(Player(0),0,0,"EnchantGlaivescp3")
    call DisplayTextToPlayer(Player(0),0,0,"EnchantGlaivesActivate")
    set p = null
    set updatetimer = null
endfunction

function EnchantGlaivesLearned takes nothing returns nothing
    local unit hero = GetTriggerUnit()
    call DisplayTextToPlayer(Player(0),0,0,"EnchantglaivesLearned")
    call EnchantGlaivesActivate(hero)
    set hero = null
endfunction

function EnchantGlaivesEnd takes unit hero returns nothing
    local string herostring = I2S(H2I(hero))
    local timer updatetimer = I2Timer(GetStoredInteger(udg_gamecache,herostring,"enchantglaivesupdatetimer"))
    local string updatetimerstring = I2S(H2I(updatetimer))
    local integer i = 0
    local integer glaivenumber = 6
    local unit subject
    local effect tempeffect
    loop
        exitwhen i == glaivenumber
        set subject = I2Unit(GetStoredInteger(udg_gamecache,updatetimerstring,"glaive#"+I2S(i)))
        set tempeffect = I2Effect(GetStoredInteger(udg_gamecache,updatetimerstring,"effect#"+I2S(i)))
        call RemoveUnit(subject)
        call DestroyEffect(tempeffect)
        set i = i + 1
    endloop
    call FlushStoredMission(udg_gamecache,updatetimerstring)
    call FlushStoredInteger(udg_gamecache,herostring,"enchantglaivesupdatetimer")
    set updatetimer = null
    set subject = null
    set tempeffect = null
endfunction

function LureDragonOff takes unit hero returns nothing
    local string herostring = I2S(H2I(hero))
    local timer updatetimer = I2Timer(GetStoredInteger(udg_gamecache,herostring,"luredragonupdatetimer"))
    local string updatetimerstring = I2S(H2I(updatetimer))
    local unit dragon = I2Unit(GetStoredInteger(udg_gamecache,updatetimerstring,"dragon"))
    call PauseTimer(updatetimer)
    call DestroyTimer(updatetimer)
    call FlushStoredMission(udg_gamecache,updatetimerstring)
    call FlushStoredInteger(udg_gamecache,herostring,"luredragonupdatetimer")
    call RemoveUnit(dragon)
    call Msg("luredragonend")
    set dragon = null
    set updatetimer = null
endfunction

function LureDragonCondition takes nothing returns boolean
    if GetUnitAbilityLevel(GetFilterUnit(),udg_buffs[18]) == 0 and TargetTypeCondition(GetFilterUnit(),udg_tempunit,33796) then
        call Msg("LureDragonFiretargetfound..casting soon")
    endif
    return GetUnitAbilityLevel(GetFilterUnit(),udg_buffs[18]) == 0 and TargetTypeCondition(GetFilterUnit(),udg_tempunit,33796)
endfunction

function LureDragonUpdate takes nothing returns nothing
    local timer updatetimer = GetExpiredTimer()
    local string updatetimerstring = I2S(H2I(updatetimer))
    local unit hero = I2Unit(GetStoredInteger(udg_gamecache,updatetimerstring,"hero"))
    local unit dragon = I2Unit(GetStoredInteger(udg_gamecache,updatetimerstring,"dragon"))
    local real herox = GetWidgetX(hero)
    local real heroy = GetWidgetY(hero)
    local group g = CreateGroup()
    local unit subject
    local real range = 1000
    set udg_tempunit = hero
    call GroupEnumUnitsInRange(g,herox,heroy,range,Condition(function LureDragonCondition))
    call Msg("luredragonupdate")
    set subject = GroupPickRandomUnit(g)
    if subject != null then
        call IssueTargetOrder(dragon,"faeriefire",subject)
        set subject = null
    else
        call Msg("no faerietarget found")
    endif
    call DestroyGroup(g)
    set g = null
    set hero = null
    set dragon = null
endfunction

function LureDragonCast takes nothing returns nothing
    local unit hero = GetTriggerUnit()
    local real herox = GetWidgetX(hero)
    local real heroy = GetWidgetY(hero)
    local group g = CreateGroup()
    local player p = GetTriggerPlayer()
    local unit dragon = CreateUnit(p,udg_unittypes[5],herox,heroy,0)
    local real interval = 5
    local timer updatetimer = CreateTimer()
    local string updatetimerstring = I2S(H2I(updatetimer))
    call SetHandleHandle(hero,"luredragonupdatetimer",updatetimer)
    call SetHandleHandle(dragon,"hero",hero)
    call StoreInteger(udg_gamecache,updatetimerstring,"hero",H2I(hero))
    call StoreInteger(udg_gamecache,updatetimerstring,"dragon",H2I(dragon))
    call DisplayTextToPlayer(Player(0),0,0,"LureDragoncast")
    call IssueTargetOrder(dragon,"move",hero)
    call TimerStart(updatetimer,interval,true,function LureDragonUpdate)
    set p = null
    set dragon = null
    set hero = null
endfunction

function LureDragonNullmana takes nothing returns nothing
    local unit hero = GetTriggerUnit()
    call Msg("LureDragonnullmana")
    call LureDragonOff(hero)
    set hero = null
endfunction

function LureDragonLearned takes nothing returns nothing
    local trigger nullmanatrig = CreateTrigger()
    local unit hero = GetTriggerUnit()
    call SetHandleHandle(hero,"nullmanatrig",nullmanatrig)
    call TriggerAddAction(nullmanatrig,function LureDragonNullmana)
    call TriggerRegisterUnitStateEvent(nullmanatrig,hero,UNIT_STATE_MANA,LESS_THAN_OR_EQUAL,7)
    set hero = null
    set nullmanatrig = null
endfunction

function DragonFaerieFireSpellStarts takes nothing returns nothing
    local unit target = GetSpellTargetUnit()
    local unit caster = GetTriggerUnit()
    local unit hero = GetHandleUnit(caster,"hero")
    local real slow = 80 * GetHeroAbilityLevel(hero,42) / GetHeroLevel(hero)
    local real duration = 10
    call Slow(target,slow,duration)
    call TriggerSleepAction(1)
    call IssueTargetOrder(caster,"move",hero)
    call Msg("dragonfaeriefirecast") 
    set target = null
    set caster = null
    set hero = null
endfunction

function ManaGrabHits takes nothing returns nothing
    local unit target = GetTriggerUnit()
    local unit hero = GetEventDamageSource()
    local real attackdmg = GetEventDamage()
    local real dmgmod = 0.8 * GetUnitAbilityLevel(hero,udg_habils[46]) / GetHeroLevel(hero)
    local real manasteal = attackdmg*dmgmod
    local real targetmana = GetUnitState(target,UNIT_STATE_MANA)
    if targetmana < manasteal then
        set manasteal = targetmana
    endif
    call DisplayTextToPlayer(Player(0),0,0,"managrabhits")
    call SetUnitState(target,UNIT_STATE_MANA,targetmana-manasteal)
    call SetUnitState(hero,UNIT_STATE_MANA,GetUnitState(hero,UNIT_STATE_MANA)+manasteal)
    set hero = null
    set target = null
endfunction

function ShieldMagicOn takes nothing returns nothing
    local unit hero = GetOrderedUnit()
    local real slow = 40  * GetHeroLevel(hero) / GetUnitAbilityLevel(hero,udg_habils[47])
    call DisplayTextToPlayer(Player(0),0,0,"shieldmagicon")
    call SetHandleReal(hero,"shieldmagicslow",slow)
    call SetUnitMoveSpeed(hero,GetUnitMoveSpeed(hero)-slow)
    set hero = null
endfunction

function ShieldMagicOff takes nothing returns nothing
    local unit hero = GetOrderedUnit()
    local string herostring = I2S(H2I(hero))
    local real slow = GetStoredReal(udg_gamecache,herostring,"shieldmagicslow")
    call DisplayTextToPlayer(Player(0),0,0,"shieldmagicoff")
    call SetUnitMoveSpeed(hero,GetUnitMoveSpeed(hero)+slow)
    call FlushStoredReal(udg_gamecache,herostring,"shieldmagicslow")
    set hero = null
endfunction

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

//XPGOLDADD
function AddGold takes nothing returns nothing
    local player p = GetEnumPlayer()
    local integer goldadd = 1
    call SetPlayerState(p,PLAYER_STATE_RESOURCE_GOLD,GetPlayerState(p,PLAYER_STATE_RESOURCE_GOLD)+goldadd)
    set p = null
endfunction

function AddXp takes nothing returns nothing
    local unit hero = GetEnumUnit()
    local integer xpadd = 1
    call SetHeroXP(hero, GetHeroXP(hero)+xpadd, true)
    set hero = null
endfunction

function AddXpGoldByTimer takes nothing returns nothing
    call ForGroup(udg_heroesgroup,function AddXp)
    call ForForce(udg_forces[4], function AddGold)
endfunction

//===============================================================================================================
//Create Hero
function AllianceBack2Neutral takes player p, player p2 returns nothing
    call SetPlayerAlliance(p, p2, ALLIANCE_HELP_REQUEST,  false)
    call SetPlayerAlliance(p, p2, ALLIANCE_HELP_RESPONSE, false)
    call SetPlayerAlliance(p, p2, ALLIANCE_SHARED_SPELLS, false)
    call SetPlayerAlliance(p, p2, ALLIANCE_SHARED_VISION, false)
    call SetPlayerAlliance(p2, p, ALLIANCE_HELP_REQUEST,  false)
    call SetPlayerAlliance(p2, p, ALLIANCE_HELP_RESPONSE, false)
    call SetPlayerAlliance(p2, p, ALLIANCE_SHARED_SPELLS, false)
    call SetPlayerAlliance(p2, p, ALLIANCE_SHARED_VISION, false)
endfunction

function Hero2Boatindex takes integer heroindex returns integer
    local integer boatindex
    if heroindex == 0 then
        set boatindex = 3
    elseif heroindex == 1 then
        set boatindex = 4
    elseif heroindex == 2 then //windlord
        set boatindex = 1
    elseif heroindex == 3 then //whisper
        set boatindex = 5
    elseif heroindex == 4 then //mamak
        set boatindex = 1
    elseif heroindex == 5 then //terminator
        set boatindex = 2
    elseif heroindex == 6 then
        set boatindex = 4
    elseif heroindex == 7 then //bodyless
        set boatindex = 3
    elseif heroindex == 8 then //high inqui
        set boatindex = 0
    elseif heroindex == 9 then //grand marshal
        set boatindex = 0
    elseif heroindex == 10 then
        set boatindex = 5
    elseif heroindex == 11 then //prince
        set boatindex = 2
    elseif true then
    
    endif
    return boatindex
endfunction

function CreateHero takes nothing returns nothing
    local timer createherotimer = GetExpiredTimer()
    local string createherotimerstring = I2S(H2I(createherotimer))
    local integer heroindex = GetStoredInteger(udg_gamecache,createherotimerstring,"heroindex")
    local integer boatindex = Hero2Boatindex(heroindex)
    local integer pindex = GetStoredInteger(udg_gamecache,createherotimerstring,"playerindex")
    local location spawnloc = I2Location(GetStoredInteger(udg_gamecache,createherotimerstring,"spawnloc"))
    local player p = Player(pindex)
    local unit hero = CreateUnit(p, udg_herotypes[heroindex], GetLocationX(spawnloc), GetLocationY(spawnloc), GetRandomReal(1,360))
    local string herostring = I2S(H2I(hero))
    local unit god
    call RemoveLocation(spawnloc)
    call GroupAddUnit(udg_heroesgroup, hero)
    call GroupAddUnit(udg_heroteamgroups[udg_player2force[pindex]], hero)
    if heroindex == 2 then
        call SetPlayerAbilityAvailable(p, 'A01E', false)
    endif
    call StoreReal(udg_gamecache,herostring,"agi",GetHeroAgi(hero,false))
    call StoreReal(udg_gamecache,herostring,"int",GetHeroInt(hero,false))
    call StoreReal(udg_gamecache,herostring,"str",GetHeroStr(hero,false))
    if udg_chooseattributes then
        set god = CreateUnit(p, udg_dummyunittypes[11], 0,0,0)
        set god = null
    endif   
    call FlushStoredMission(udg_gamecache,createherotimerstring)
    call DestroyTimer(createherotimer)
    set createherotimer = null
    set hero = null
    set spawnloc = null
    set p = null
endfunction

function GetRandomPlaygroundLoc takes nothing returns location
    local location loc
    loop
        set loc = Location(GetRandomReal(GetRectMinX(udg_roughplayground), GetRectMaxX(udg_roughplayground)), GetRandomReal(GetRectMinY(udg_roughplayground), GetRectMaxY(udg_roughplayground)))
        if IsLocationInRegion(udg_playground,loc) then
            exitwhen true
        else
            call RemoveLocation(loc)
        endif
    endloop
    return loc
endfunction

function CreateHeroDummyEnter takes integer heroindex returns nothing
    local unit dummy = GetTriggerUnit()
    local integer boatindex = Hero2Boatindex(heroindex)
    local real wait
    local timer createherotimer = CreateTimer()
    local string createherotimerstring = I2S(H2I(createherotimer))
    local player p = GetOwningPlayer(dummy)
    local real fireheight = 50
    local integer pindex = GetPlayerId(p)
    local real missilespeedsqr = 490000
    local location targetloc
    local real targetx
    local real targety
    local integer i
    local real boatx = GetWidgetX(udg_boats[boatindex])
    local real boaty = GetWidgetY(udg_boats[boatindex])
    call RemoveUnit(dummy)
    call StoreInteger(udg_gamecache,createherotimerstring,"playerindex",pindex)
    call StoreInteger(udg_gamecache,createherotimerstring,"heroindex",heroindex)
    //Set targetloc
    if udg_gamemode == 0 or udg_gamemode == 1 then
            set targetloc = udg_boatfirelocs[boatindex]
    else
        if udg_gamemode == 2 or udg_gamemode == 3 then
            set targetloc = GetRandomPlaygroundLoc()
        else
            //nothing- no gamemode 4 yet.
        endif
    endif
    //ChangeHeroShopAllianceBack2Neutral
    if udg_gamemode == 0 or udg_gamemode == 1 then
        if udg_allpick then
            set i = 0
            loop
                exitwhen i == udg_mapmaxteams
                call AllianceBack2Neutral(p,Player(i+12))
                set i = i+1
            endloop
        else
            call AllianceBack2Neutral(p,Player(12+udg_player2force[pindex]))
        endif
    elseif udg_gamemode == 2 or udg_gamemode == 3 then
        set i = 0
        loop
            exitwhen i == udg_mapmaxteams
            set udg_tempint = i+12
            call AllianceBack2Neutral(p,Player(i+12))
            set i = i + 1
        endloop
    elseif true then
        //nothing- no gamemode 4 yet.
    endif
    
    call StoreInteger(udg_gamecache,createherotimerstring,"spawnloc",H2I(targetloc))
    set targetx = GetLocationX(targetloc)
    set targety = GetLocationY(targetloc)
    set wait = DistanceSqr(boatx,boaty,targetx,targety)/missilespeedsqr
    call CastLocAbilityCor(Player(15), 9, 1, targetloc, wait, GetWidgetX(udg_boats[boatindex]), GetWidgetY(udg_boats[boatindex]), fireheight)
    call TimerStart(createherotimer, wait, false, function CreateHero)
    set createherotimer = null
    set targetloc = null
endfunction

//===================================================================================================================
//RefreshScore

//bestplayer in gamemode0 stands for the team with highest score, goes from 1 to 4.
//bestplayer in gamemode1 stands for the team with highest kills, goes from 12-15.
//bestplayer in gamemode2 stands for the player with the most kills, goes from 0 to 11.

function ShrineControlCondition takes nothing returns boolean
    return TargetTypeCondition(GetFilterUnit(),udg_tempunit,udg_tempint)
endfunction

function ShrineEnter takes nothing returns nothing
    local group g
    local integer groupcount
    local unit subject = GetTriggerUnit()
    local trigger trig = GetTriggeringTrigger()
    local string trigstring = I2S(H2I(trig))
    local unit shrine = I2Unit(GetStoredInteger(udg_gamecache,trigstring,"shrine"))
    local integer shrineindex = GetStoredInteger(udg_gamecache,trigstring,"shrineindex")
    local real x = GetWidgetX(shrine)
    local real y = GetWidgetY(shrine)
    local real radius = 700
    local integer pindex = GetPlayerId(GetOwningPlayer(subject))
    if not (udg_shrine2controller[shrineindex] == udg_player2force[pindex]) then
        set g = CreateGroup()
        set udg_tempunit = subject
        set udg_tempint = 4
        call GroupEnumUnitsInRange(g,x,y,radius,Condition(function ShrineControlCondition))
        set bj_wantDestroyGroup = true
        set groupcount = CountUnitsInGroup(g)
        if groupcount == 0 then
            set udg_shrine2controller[shrineindex] = udg_player2force[pindex]
            call SetUnitColor(udg_shrines[shrineindex],GetPlayerColor(Player(udg_player2force[pindex])))
        endif
        call DestroyGroup(g)
        set g = null
    endif
    set subject = null
    set trig = null
endfunction

function DeclareWin takes nothing returns nothing
    call CustomVictoryBJ(GetEnumPlayer(),true,true)
endfunction

function DeclareDefeat takes nothing returns nothing
    call CustomDefeatBJ(GetEnumPlayer(),"You lost.")
endfunction

function TeamWin takes nothing returns nothing
    local force f = CreateForce()
    call ForceEnumAllies(f,Player(udg_bestplayer),null)
    call ForForce(f,function DeclareWin)
    call ForceClear(f)
    call ForceEnumEnemies(f,Player(udg_bestplayer),null)
    call ForForce(f,function DeclareDefeat)
endfunction

function PlayerWin takes nothing returns nothing
    call ForceRemovePlayer(udg_forces[2],Player(udg_bestplayer))
    call ForForce(udg_forces[2],function DeclareDefeat)
    call CustomVictoryBJ(Player(udg_bestplayer),true,true)
endfunction

function LMSRoundEnd takes nothing returns nothing

    //return
endfunction

//HERO DEATH AND REVIVE
function HeroDiedScoreUpdate takes unit deceased, unit killer returns nothing
    local player deceasedp = GetOwningPlayer(deceased)
    local player killerp = GetOwningPlayer(killer)
    local integer deceasedpindex = GetPlayerId(deceasedp)
    local integer killerpindex = GetPlayerId(killerp)
    local multiboarditem deceaseditem = MultiboardGetItem(udg_multiboard,udg_player2boardrow[deceasedpindex],2)
    local multiboarditem killeritem = MultiboardGetItem(udg_multiboard,udg_player2boardrow[killerpindex],1)
    local multiboarditem tempitem
    local integer deceasedteam
    local integer killerteam
    local integer leaderboardindex
    //NonGameScoreUpdate
    set udg_deaths[deceasedpindex] = udg_deaths[deceasedpindex] + 1
    set udg_kills[killerpindex] = udg_kills[killerpindex] + 1
    //MultiboardPlayerScoreUpdate
    call MultiboardSetItemValue(deceaseditem,I2S(udg_deaths[deceasedpindex]))
    call MultiboardSetItemValue(killeritem,I2S(udg_kills[killerpindex]))
    //MultiboardTeamScoreUpdate
    if udg_gamemode == 0 or udg_gamemode == 1 then
        set deceasedteam = udg_player2force[deceasedpindex]+12
        set udg_deaths[deceasedteam] = udg_deaths[deceasedteam] + 1
        set tempitem = MultiboardGetItem(udg_multiboard,udg_player2boardrow[deceasedteam],2) 
        call MultiboardSetItemValue(tempitem,I2S(udg_deaths[deceasedteam]))
        set killerteam = udg_player2force[killerpindex]+12
        set udg_kills[killerteam] = udg_kills[killerteam] + 1
        set tempitem = MultiboardGetItem(udg_multiboard,udg_player2boardrow[killerteam],1) 
        call MultiboardSetItemValue(tempitem,I2S(udg_kills[killerteam]))
        set tempitem = null
    endif
    //LeaderboardUpdate
    if udg_gamemode == 1 then //bestplayer now stands for the best forceplayer
        set leaderboardindex = udg_player2force[killerpindex]
        set killerteam = leaderboardindex + 12
        if udg_gamemode2 == 0 then
            call LeaderboardSetItemValue(udg_leaderboard,leaderboardindex,udg_victorytarget-udg_kills[killerteam])
        else
            if killerteam != udg_bestplayer then
                //if killerteam != udg_secondbestplayer then
                    if udg_kills[killerteam] >= udg_kills[udg_secondbestplayer] then
                        set udg_secondbestplayer = killerteam
                    endif
                //endif
                if udg_kills[killerteam] >= udg_kills[udg_bestplayer] then
                    set udg_secondbestplayer = udg_bestplayer
                    set udg_bestplayer = killerteam
                    call LeaderboardSetItemValue(udg_leaderboard,leaderboardindex,udg_victorytarget-udg_kills[udg_bestplayer]+udg_kills[udg_secondbestplayer])  
                endif
            else
                call LeaderboardSetItemValue(udg_leaderboard,leaderboardindex,udg_victorytarget-udg_kills[udg_bestplayer]+udg_kills[udg_secondbestplayer])                 
            endif
        endif
    else
        if udg_gamemode == 2 then
            if killerpindex != udg_bestplayer then
                //if killerpindex != udg_secondbestplayer then
                    if udg_kills[killerpindex] >= udg_kills[udg_secondbestplayer] then
                        set udg_secondbestplayer = killerpindex
                    endif
                //endif
                if udg_kills[killerpindex] >= udg_kills[udg_bestplayer] then
                    set udg_secondbestplayer = udg_bestplayer
                    set udg_bestplayer = killerpindex                
                    if udg_gamemode2 == 0 then
                        call LeaderboardSetItemValue(udg_leaderboard,0,udg_victorytarget-udg_kills[udg_bestplayer])
                    else
                        call LeaderboardSetItemValue(udg_leaderboard,0,udg_victorytarget-udg_kills[udg_bestplayer]+udg_kills[udg_secondbestplayer])    
                    endif     
                endif
            else                
                if udg_gamemode2 == 0 then
                    call LeaderboardSetItemValue(udg_leaderboard,0,udg_victorytarget-udg_kills[udg_bestplayer])
                else
                    call LeaderboardSetItemValue(udg_leaderboard,0,udg_victorytarget-udg_kills[udg_bestplayer]+udg_kills[udg_secondbestplayer])    
                endif 
            endif
        else
            if udg_gamemode == 3 then
                set udg_playersleft = udg_playersleft - 1
                call LeaderboardSetItemValue(udg_leaderboard,0,udg_playersleft)
            else
                //nothing- no gamemode 4 yet.
            endif      
        endif
    endif
    if udg_gamemode == 1 then
        if udg_kills[udg_bestplayer] == udg_victorytarget then
            call TeamWin()
        endif
    else
        if udg_gamemode == 2 then
            if udg_kills[udg_bestplayer] == udg_victorytarget then
                call PlayerWin()
            endif
        else
            if udg_gamemode == 3 then
                if udg_playersleft == 1 then
                    call LMSRoundEnd()
                endif
            else
                //nothing- no gamemode 4 yet.
            endif
        endif
    endif
    set deceasedp = null
    set killerp = null
    set deceaseditem = null
    set killeritem = null
endfunction

function HeroRevive takes unit hero returns nothing
    local real x
    local real y
    local location loc
    local integer pindex = GetPlayerId(GetOwningPlayer(hero))
    if udg_gamemode == 0 or udg_gamemode == 1 then
        set loc = GetRandomLocInRect(udg_startrects[udg_player2force[pindex]])
    else
        if udg_gamemode == 2 or udg_gamemode == 3 then
            set loc = GetRandomPlaygroundLoc()
        else
            //nothing- no gamemode 4 yet.
        endif
    endif
    set x = GetLocationX(loc)
    set y = GetLocationY(loc)
    call RemoveLocation(loc)
    call ReviveHero(hero,x,y,true)
    set loc = null
endfunction

function HeroDied takes nothing returns nothing
    local unit deceased = GetDyingUnit()
    local unit killer = GetKillingUnit()
    local real duration = 10
    local string dname = GetPlayerName(GetOwningPlayer(deceased))
    local string kname = GetPlayerName(GetOwningPlayer(killer))
    local string message
    local integer did = GetUnitTypeId(deceased)
    local integer randomi = GetRandomInt(0,8)
    if randomi == 1 then
        set message = dname+" has been 00NT by "+kname+"'s 13370|2 skIlz"
    elseif randomi == 2 then
        set message = dname+"got it IN DA FACE!! from "+kname
    elseif randomi == 3 then
        set message = kname+" brought some big TT's to "+dname
    elseif randomi == 4 then
        set message = dname+" Got Served By "+kname
    elseif randomi == 5 then
        set message = dname+" Was Ruthlessly Slain By "+kname
    elseif randomi == 6 then
        set message = dname+" Was Ruthlessly Slain By "+kname
    elseif randomi == 7 then
        set message = dname+" Was Ruthlessly Slain By "+kname
    elseif randomi == 8 and GetUnitTypeId(killer) == udg_herotypes[4] then
        set message = kname+" Disposed Of "+dname+" Silently"
    elseif randomi == 9 then
        set message = dname+" Was No Match For "+kname
    endif
    call HeroRevive(deceased)
    call HeroDiedScoreUpdate(deceased,killer)
    if did == udg_herotypes[11] then
        call EnchantGlaivesEnd(deceased)
    elseif did == udg_herotypes[9] then
        call TrampleEnd(deceased)
    elseif did == udg_herotypes[7] then
        call DecrepitAuraEnd(deceased)
    endif
    call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, duration, message)
    set deceased = null
    set killer = null
endfunction

//SHRINETICK
function ShrineTickBoardUpdateAll takes nothing returns nothing
    local integer i
    set i = 0
    loop
        exitwhen i == udg_teamcount
        call LeaderboardSetItemValue(udg_leaderboard,i,udg_scores[i])
        set i = i + 1
    endloop
endfunction

function ShrineTickBoardUpdateSingle takes nothing returns nothing
    call LeaderboardSetItemValue(udg_leaderboard,0,udg_scores[udg_bestplayer])
endfunction

function ShrineTick takes nothing returns nothing
    local integer i = 0
    local integer shrinecount = 2
    local integer pindex
    local boolean b
    loop
        exitwhen i == shrinecount
        if udg_shrine2controller[i] != 4 then
            set pindex = udg_shrine2controller[i]
            set udg_scores[pindex] = udg_scores[pindex]+ 1
            if pindex != udg_secondbestplayer then
                if udg_scores[pindex] >= udg_scores[udg_secondbestplayer] then
                    set udg_secondbestplayer = pindex
                endif
            else
                if udg_scores[pindex] >= udg_scores[udg_bestplayer] then
                    set udg_bestplayer = pindex
                    set b = true
                endif
            endif
        endif
        set i = i + 1
    endloop
    if udg_gamemode2 == 0 then
        if udg_scores[udg_bestplayer] >= udg_victorytarget then
            call DisplayTextToPlayer(Player(0),0,0,"scoreRacewin")
            call TeamWin()
        endif
    else
        if udg_gamemode2 == 1 then
            if udg_scores[udg_bestplayer] >= udg_scores[udg_secondbestplayer] + udg_victorytarget then
                call DisplayTextToPlayer(Player(0),0,0,"scoreOutrunwin")
                call TeamWin()
            endif
        endif
    endif
    if udg_gamemode2 == 0 or udg_gamemode2 == 2 then
        call ShrineTickBoardUpdateAll()
    else
        if b then
            call ShrineTickBoardUpdateSingle()
        endif    
    endif
endfunction

//==================================================================================================================
//UnitBeginsCasting
function UnitBeginsCasting takes nothing returns nothing
    local integer id = GetSpellAbilityId()
    if id == udg_habils[0] then
        call FloodCast()
    elseif id == udg_habils[2] then
        call ScizofreniaCast()
    elseif id == udg_habils[4] then
        call AngerCast()
    elseif id == udg_habils[6] then
        call ConcentrateCast()
    elseif id == udg_habils[7] then
        call BurnoutCast()
    elseif id == udg_habils[8] then
        call HopastrikeCast()
    elseif id == udg_habils[9] then
        call AirformCast()
    elseif id == udg_habils[10] then
        call MeditateCast()
    elseif id == udg_habils[11] then
        call TornadoCast()
    elseif id == udg_habils[12] then
        call ShadowlurkCast()
    elseif id == udg_habils[14] then
        call BodyburnCast()
    elseif id == udg_habils[15] then
        call BackshotCast()
    elseif id == udg_habils[17] then
        call TossCast()
    elseif id == udg_habils[18] then
        call QuadrostompCast()
    elseif id == udg_habils[19] then
        call BlizzardCast()
    elseif id == udg_habils[20] then
        call HellFiresCast()
    elseif id == udg_habils[22] then
        call CoolantFlushCast()
    elseif id == udg_habils[23] then
        call TargetCast()
    elseif id == udg_habils[24] then
        call PoisonnovaCast()
    elseif id == udg_habils[25] then
        call PoisonskinCast()
    elseif id == udg_habils[28] then
        call SoulSapCast()
    elseif id == udg_habils[29] then
        call SilencingSoulsCast()      
    elseif id == udg_habils[33] then
        call SentryCast()
    elseif id == udg_habils[34] then
        call CageCast()
    elseif id == udg_habils[35] then
        call GatherMobCast()
    elseif id == udg_habils[36] then
        call KilledYourFathersCast()
    //elseif id == udg_habils[38] then
    //    call FallBackCast()
    elseif id == udg_habils[39] then
        call GrandChargeCast()
    elseif id == udg_habils[40] then
        call DisectCast()
    elseif id == udg_habils[42] then
        call SandStormCast()
    elseif id == udg_habils[43] then
        call FlyCast()
    elseif id == udg_habils[45] then
        call LureDragonCast()
    elseif id == udg_habils[48] then
        call WindswipeCast()         
    elseif id == udg_habils[49] then
        call MoonCraveCast()                                                                                                          
    endif      
endfunction

//UnitStopsCasting
function UnitStopsCasting takes nothing returns nothing
    local unit subject = GetTriggerUnit()
    if GetSpellAbilityId() == udg_habils[6] then
        call DisplayTextToPlayer(Player(0),0,0,"concentratecancel")
        set udg_tempunit = subject
        call ExecuteFunc("ConcentrateEnd")
    elseif GetSpellAbilityId() == udg_habils[10] then
        call MeditateCancel()
    elseif GetSpellAbilityId() == udg_habils[18] then
        call QuadrostompEnd(subject)
    else
    endif
endfunction

function UnitSpellFinish takes nothing returns nothing
    local unit subject = GetTriggerUnit()
    local integer id = GetSpellAbilityId()
    if id == udg_habils[41] then
        call BurrowFinish()          
    endif   
endfunction

function UnitSpellStartsEffect takes nothing returns nothing
    local integer id = GetSpellAbilityId()
    if id == udg_habils[16] then
        call RampageSpellStarts()
    elseif id == udg_habils[32] then
        call AmbushSpellStarts()
    elseif id == udg_uabils[19] then
        call DragonFaerieFireSpellStarts()    
    elseif id == udg_habils[31] then
        call PossessionSpellStarts() 
    elseif id == udg_habils[21] then
        call PowSpellStarts()  
    elseif id == udg_habils[38] then
        call FallBackSpellStarts()                                                                                         
    endif
endfunction

//UnitAttacked
function UnitAttacked takes nothing returns nothing
    local unit attacker = GetAttacker()
    local unit target = GetTriggerUnit()
    local integer attackertypeid = GetUnitTypeId(attacker)
    local integer targettypeid = GetUnitTypeId(target)
    //if GetUnitAbilityLevel(attacker,udg_buffs[16]) != 0 then
    //    call ExecuteFunc("ShadowlurkAttacks")
    //endif
    if targettypeid == udg_herotypes[7] and GetUnitAbilityLevel(target,udg_habils[30]) != 0 then
        call ExecuteFunc("AuraBodylessAttacked")
    endif
    if attackertypeid == udg_unittypes[4] then
        call Msg("FemaleMobAttacks")
        call ExecuteFunc("FemaleMobAttacks")
    endif
endfunction

//UnitDamaged
function UnitDamaged takes nothing returns nothing
    local unit subject = GetTriggerUnit()
    local unit source = GetEventDamageSource()
    local integer subject_typeid = GetUnitTypeId(subject)
    local integer source_typeid = GetUnitTypeId(source)
    local string sourcestring = I2S(H2I(source))
    local boolean bool
    if source_typeid == udg_herotypes[1] then
        set bool = GetStoredBoolean(udg_gamecache,sourcestring,"igniteburns")
        if bool then
            call FlushStoredBoolean(udg_gamecache,sourcestring,"igniteburns")
        else        
            if GetStoredInteger(udg_gamecache,sourcestring,"concentratedamage") != 0 and GetEventDamage() > 0 then         
                call ExecuteFunc("ConcentrateHits")
            endif            
        endif   
    endif    
    if UnitHasBuffBJ(subject, udg_buffs[1]) then
        call ExecuteFunc("FloodHits")
        //call DisplayTextToPlayer(Player(0),0,0,"FloodHits")
    endif
    if source_typeid == udg_herotypes[0] or source_typeid == udg_unittypes[2] then
        call ExecuteFunc("CannibalizeHits")
        //call DisplayTextToPlayer(Player(0),0,0,"CannibalizeHits")
    endif
    if UnitHasBuffBJ(subject, udg_buffs[4]) then
        call ExecuteFunc("IgniteHits")
        //call DisplayTextToPlayer(Player(0),0,0,"IgniteHits")
    endif
    if UnitHasBuffBJ(subject, udg_buffs[5]) then
        call ExecuteFunc("ViraHits")
        //call DisplayTextToPlayer(Player(0),0,0,"ViraHits")
    endif
    if UnitHasBuffBJ(subject, udg_buffs[7]) then
        call ExecuteFunc("BackshotHits")
        //call DisplayTextToPlayer(Player(0),0,0,"BackshotHits")
    endif
    if UnitHasBuffBJ(subject, udg_buffs[9]) then
        call ExecuteFunc("PoisonnovaHits")
        //call DisplayTextToPlayer(Player(0),0,0,"PoisonnovaHits")
    endif
    if subject_typeid == udg_herotypes[6] and GetUnitAbilityLevel(source,udg_buffs[12]) != 0 then
        call ExecuteFunc("PoisonskinHit")
        //call DisplayTextToPlayer(Player(0),0,0,"PoisonskinHit")
    endif
    if UnitHasBuffBJ(subject, udg_buffs[10]) then   
        call UnitRemoveAbility(subject,udg_buffs[10])
        call ExecuteFunc("CripplingPoisonHits")
        call Msg("CripplingPoisonHits")
    endif
    if UnitHasBuffBJ(subject, udg_buffs[13]) then
        call ExecuteFunc("SilencingSoulsHits")
        //call DisplayTextToPlayer(Player(0),0,0,"SilencingSoulsHits")
    endif
    if GetStoredInteger(udg_gamecache,I2S(H2I(subject)),"possessionphase1endtimer") != null then
        call ExecuteFunc("PossessionInterrupt")
        //call DisplayTextToPlayer(Player(0),0,0,"PossessionInterrupt")
    endif    
    if GetUnitAbilityLevel(source,udg_habils[46]) != 0 and not IsUnitType(subject, UNIT_TYPE_MAGIC_IMMUNE) then
        call ExecuteFunc("ManaGrabHits")
        //call DisplayTextToPlayer(Player(0),0,0,"ManaGrabHits")
    endif
    //if id == udg_unittypes[15] then
    //    call ExecuteFunc("WindswipeDamage")
    //endif
endfunction

//UnitSelected
function UnitSelected takes nothing returns nothing
    local unit u = GetTriggerUnit()
    local integer id = GetUnitTypeId(u)
    call Msg("unitselected")
    if id == udg_unittypes[2] or id == udg_herotypes[0] then
        call ExecuteFunc("ScizofreniaSelect")
    else
        
    endif
endfunction

//SkillLearned
function SkillLearned takes nothing returns nothing
    local unit subject = GetTriggerUnit()
    local integer subjectid = GetUnitTypeId(subject)
    local integer skillid = GetLearnedSkill() 
    local integer level = GetLearnedSkillLevel()
    if subjectid == udg_unittypes[2] or subjectid == udg_herotypes[0] then
        call ScizofreniaSkillLearned()
    elseif skillid == udg_habils[9] and level == 1 then
        call AirformLearned()
    elseif skillid == udg_habils[37] and level == 1 then
        call TrampleLearned()
    elseif skillid == udg_habils[44] and level == 1 then
        call EnchantGlaivesLearned()
    elseif skillid == udg_habils[35] and level == 1 then
        call GatherMobLearned()
    elseif skillid == udg_habils[36] and level == 1 then
        call KilledYourFathersLearned()
    elseif skillid == udg_habils[45] and level == 1 then
        call LureDragonLearned()
    elseif skillid == udg_habils[30] and level == 1 then
        call DecrepitAuraLearned(subject)
    endif
endfunction

//Targetorder
function TargetOrder takes nothing returns nothing
    local unit u = GetOrderedUnit()
    local integer id = GetUnitTypeId(u)
    if id == udg_herotypes[2] then
        //call WindswipeTargets()
    else
        
    endif
endfunction

//PointOrder
function PointOrder takes nothing returns nothing
    local unit u = GetOrderedUnit()
    local integer id = GetUnitTypeId(u)
    if id == udg_herotypes[2] then
        //call WindswipeNoTarget()
    else
        
    endif
endfunction

//ImmediateOrder
function ImmediateOrder takes nothing returns nothing
    local unit subject = GetOrderedUnit()
    local integer subjectid = GetUnitTypeId(subject)
    local integer orderid = GetIssuedOrderId()
    local string subjectstring = I2S(H2I(subject))
    local boolean bool
    if subjectid == udg_herotypes[2] then
        //call WindswipeNoTarget()
    endif
    if orderid == 852478 and subjectid == udg_herotypes[11] then
        call DisplayTextToPlayer(Player(0),0,0,"shieldmagicOnCall")
        call ShieldMagicOn()
    endif
    if orderid == 852178 and subjectid == udg_herotypes[9] then
        call DisplayTextToPlayer(Player(0),0,0,"KYFoffcall")
        call KilledYourFathersOff(subject)
    endif
    if orderid == 852479 and subjectid == udg_herotypes[11] then
        call ShieldMagicOff()
    endif
    if orderid == 852178 and subjectid == udg_herotypes[11] then
        call LureDragonOff(subject)
    endif
    if orderid == 852178 and subjectid == udg_herotypes[8] then
        call DisplayTextToPlayer(Player(0),0,0,"GatherMobOffcall")
        call GatherMobOff(subject)
    endif
    if GetUnitName(subject) == "Windlord" then
        //set bool = GetStoredBoolean(udg_gamecache,subjectstring,"meditatephase2")
        //if bool == false then
        if orderid == 852178 then
            call Msg("AirformOffcall")
            call AirformOff(subject)
        endif        
        //endif
    endif
endfunction

//Level GAIN!!!
function LevelGain takes nothing returns nothing
    local unit hero = GetTriggerUnit()
    local integer heronumber = Hero2Number(GetUnitTypeId(hero))
    local real statt
    local string herostring
    if udg_chooseattributes then
        call DisplayTextToPlayer(Player(0),0,0,"choosestatts")
    
    else
        call DisplayTextToPlayer(Player(0),0,0,"autostattadd")
        set herostring = I2S(H2I(hero))
        set statt = GetStoredReal(udg_gamecache,herostring,"agi") + AgiAdd(heronumber)
        call SetHeroAgi(hero,R2I(statt),true)
        call StoreReal(udg_gamecache,herostring,"agi",statt)
        set statt = GetStoredReal(udg_gamecache,herostring,"int") + IntAdd(heronumber)
        call SetHeroInt(hero,R2I(statt),true)
        call StoreReal(udg_gamecache,herostring,"int",statt)
        set statt = GetStoredReal(udg_gamecache,herostring,"str") + StrAdd(heronumber)
        call SetHeroStr(hero,R2I(statt),true)
        call StoreReal(udg_gamecache,herostring,"str",statt)
    endif
endfunction

//MapEnter
function MapEnter takes nothing returns nothing
    local unit subject = GetTriggerUnit()
    local integer id = GetUnitTypeId(subject)
    if id == udg_herotypes[0] or id == udg_unittypes[2] then
        call ScizofreniaArrive()
    elseif id == udg_dummyunittypes[5] then
        call CreateHeroDummyEnter(0)
    elseif id == udg_dummyunittypes[6] then
        call CreateHeroDummyEnter(1)
    elseif id == udg_dummyunittypes[7] then
        call CreateHeroDummyEnter(2)
    elseif id == udg_dummyunittypes[8] then
        call CreateHeroDummyEnter(3)
    elseif id == udg_dummyunittypes[9] then
        call CreateHeroDummyEnter(4)
    elseif id == udg_dummyunittypes[10] then
        call CreateHeroDummyEnter(5)                        
    elseif id == udg_dummyunittypes[17] then
        call CreateHeroDummyEnter(6)                        
    elseif id == udg_dummyunittypes[18] then
        call CreateHeroDummyEnter(7)                        
    elseif id == udg_dummyunittypes[19] then
        call CreateHeroDummyEnter(8)                        
    elseif id == udg_dummyunittypes[20] then
        call CreateHeroDummyEnter(9)                        
    elseif id == udg_dummyunittypes[21] then
        call CreateHeroDummyEnter(10)                        
    elseif id == udg_dummyunittypes[22] then
        call CreateHeroDummyEnter(11)                        
    else
    endif
endfunction

//NEEDS TO ACTIVATE TRAMPLEEND AND ECHANTGLAIVES END, AND GHOST AURA END
function UnitDies takes nothing returns nothing
    local unit subject = GetDyingUnit()
    local integer id = GetUnitTypeId(subject)
    local string ss = I2S(H2I(subject))
    if GetStoredReal(udg_gamecache,ss,"decrepitauraslow") != 0 then
        call ExecuteFunc("AuraUnitDied")
    endif
    if id == udg_herotypes[7] then
        call ExecuteFunc("BodylessDied")
    endif
    if IsUnitInGroup(subject, udg_heroesgroup) then
        call ExecuteFunc("HeroDied")
    endif
    if id == udg_unittypes[7] or id == udg_unittypes[8] then
        call ExecuteFunc("Cagebreak")
    endif
    if id == udg_unittypes[10] then
        call ExecuteFunc("PowEndCaller2")
    endif
    if id == udg_unittypes[3] or id == udg_unittypes[4] then
        call ExecuteFunc("MTMobDeath")
    endif
endfunction

function Sunfall takes nothing returns nothing
    if udg_day then
        set udg_day = false
        call ExecuteFunc("HeritageFall")
    endif
endfunction

function Sunrise takes nothing returns nothing
    local real time = GetTimeOfDay()
    if time >= 6 and time < 18.000 then
        set udg_day = true
        call ExecuteFunc("HeritageRise")
    endif
endfunction

function PlayerLeaves takes nothing returns nothing
    local player p = GetTriggerPlayer()
    local string pname = GetPlayerName(p)
    local real duration = 10
    local string message
    local integer randomi = GetRandomInt(0,5)
    local multiboarditem mbi
    local integer pindex = GetPlayerId(p)
    set udg_playercount = udg_playercount - 1
    set mbi = MultiboardGetItem(udg_multiboard,udg_player2boardrow[pindex],0)
    call MultiboardReleaseItem(mbi)
    set mbi = MultiboardGetItem(udg_multiboard,udg_player2boardrow[pindex],1)
    call MultiboardReleaseItem(mbi)
    set mbi = MultiboardGetItem(udg_multiboard,udg_player2boardrow[pindex],2)
    call MultiboardReleaseItem(mbi)
    if randomi == 0 then
        set message = pname+" Went for a wank, and left the game."
    elseif randomi == 1 then
        set message = pname+" Heard his mother calling, and left the game."
    elseif randomi == 2 then
        set message = pname+" Smashed his keyboard in a rage, pressing alt+f4 by accident."
    elseif randomi == 3 then
        set message = pname+" Fell, and fell asleep on the ground."
    elseif randomi == 4 then
        set message = pname+" did not have Cola- and could not game on."
    elseif randomi == 5 then
        set message = pname+" drank himself drunk, and broke his computer."
    elseif randomi == 6 then
        set message = pname+" Got Scared And Left."
    elseif randomi == 6 then
        set message = pname+" was underaged to play. We have informed the authorities, just before he fled the game."
    endif
    call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,duration,message)
    set p = null
endfunction

//================================================================================================================
//Start

//SETUP BOARDS
function SetPlayerBoardRow takes nothing returns nothing
    local integer pindex = GetPlayerId(GetEnumPlayer())
    set udg_tempint = udg_tempint+1
    set udg_player2boardrow[pindex] = udg_tempint
endfunction

function SetupBoards takes nothing returns nothing
    local integer i
    local integer i2
    local integer teamsize
    local multiboarditem tempitem
    local real width = 0.07
    local real width2 = 0.04
    //LEADERBOARD
    call LeaderboardSetStyle(udg_leaderboard,true,true,true,false)
    if udg_gamemode == 0 then
        if udg_gamemode2 == 0 then
        // 17 spaces after team
            call LeaderboardSetLabel(udg_leaderboard,"Team                     Score")
            set i = 0
            loop 
                exitwhen i == udg_teamcount
                call LeaderboardAddItem(udg_leaderboard,"Team "+I2S(i+1),0,Player(i))
                set i = i + 1
            endloop
        else
            call LeaderboardSetLabel(udg_leaderboard,"Best Team                Score")
            call LeaderboardAddItem(udg_leaderboard,"Nobody",0,Player(0))
        endif
    else
        if udg_gamemode == 1 then
            if udg_gamemode2 == 0 then
                call LeaderboardSetLabel(udg_leaderboard,"Team                     Score")
                loop 
                    call LeaderboardAddItem(udg_leaderboard,"Team "+I2S(i+1),0,Player(i-1))
                    exitwhen i == udg_teamcount
                    set i = i + 1
                endloop
            else
                call LeaderboardSetLabel(udg_leaderboard,"Best Team                Score")
                call LeaderboardAddItem(udg_leaderboard,"Nobody",0,Player(0))
            endif
        else
            if udg_gamemode == 2 then
                call LeaderboardSetLabel(udg_leaderboard,"Best Player              Score")
                call LeaderboardAddItem(udg_leaderboard,"Nobody",0,Player(0))
            else
                if udg_gamemode == 3 then
                    call LeaderboardSetLabel(udg_leaderboard,"Last Man Standing")
                    call LeaderboardAddItem(udg_leaderboard,"Playersleft",udg_playersleft,Player(0))
                else
                    //nothing- no gamemode 4 yet.
                endif
            endif
        endif
    endif
    call LeaderboardSetSizeByItemCount(udg_leaderboard,LeaderboardGetItemCount(udg_leaderboard))
    call LeaderboardDisplay(udg_leaderboard,true)
    //MULTIBOARD
    set udg_multiboard = CreateMultiboard()
    call MultiboardSetTitleText(udg_multiboard,"Scoreboard")
    if udg_gamemode == 0 or udg_gamemode == 1 then    
        call MultiboardSetRowCount(udg_multiboard,udg_teamcount+udg_playercount+1)
        set i = 0
        set udg_tempint = 1
        loop
            exitwhen i == udg_teamcount
            set udg_player2boardrow[i+12] = udg_tempint
            call ForForce(udg_forces[i],function SetPlayerBoardRow)
            set udg_tempint = udg_tempint + 1
            set i = i + 1
        endloop
    else
        if udg_gamemode == 2 or udg_gamemode == 3 then
            call MultiboardSetRowCount(udg_multiboard,udg_playercount+1)
            set i = 0
            loop
                exitwhen i == udg_playercount
                set udg_player2boardrow[i] = i+1
                set i = i + 1
            endloop
        else
            //nothing- no gamemode 4 yet.
        endif
    endif
    call MultiboardSetColumnCount(udg_multiboard,3)
    set tempitem = MultiboardGetItem(udg_multiboard,0,0)
    call MultiboardSetItemValue(tempitem,"Player")
    call MultiboardSetItemStyle(tempitem,true,false)
    call MultiboardSetItemWidth(tempitem,width)
    set tempitem = MultiboardGetItem(udg_multiboard,0,1)
    call MultiboardSetItemValue(tempitem,"Kills")
    call MultiboardSetItemStyle(tempitem,true,false)
    call MultiboardSetItemWidth(tempitem,width2)
    set tempitem = MultiboardGetItem(udg_multiboard,0,2)
    call MultiboardSetItemValue(tempitem,"Deaths")
    call MultiboardSetItemStyle(tempitem,true,false)
    call MultiboardSetItemWidth(tempitem,width2)
    set i = 0
    loop
        exitwhen i == 12+udg_teamcount
        if udg_player2boardrow[i] != 0 then
            set tempitem = MultiboardGetItem(udg_multiboard,udg_player2boardrow[i],0)
            call MultiboardSetItemValue(tempitem,GetPlayerName(Player(i)))
            call MultiboardSetItemValueColor(tempitem,udg_player2colorcode[i],udg_player2colorcode[12+i],udg_player2colorcode[24+i],0)
            call MultiboardSetItemStyle(tempitem,true,false)
            call MultiboardSetItemWidth(tempitem,width)        
            set tempitem = MultiboardGetItem(udg_multiboard,udg_player2boardrow[i],1)     
            call MultiboardSetItemValue(tempitem,I2S(udg_kills[i]))
            call MultiboardSetItemStyle(tempitem,true,false)
            call MultiboardSetItemWidth(tempitem,width2)
            set tempitem = MultiboardGetItem(udg_multiboard,udg_player2boardrow[i],2) 
            call MultiboardSetItemValue(tempitem,I2S(udg_deaths[i]))
            call MultiboardSetItemStyle(tempitem,true,false)
            call MultiboardSetItemWidth(tempitem,width2)  
        endif
        set i = i + 1
    endloop
    call MultiboardDisplay(udg_multiboard,true)
endfunction

function AllyWithTempInt takes nothing returns nothing
    local player p = GetEnumPlayer()
    call SetPlayerAlliance(p, Player(udg_tempint), ALLIANCE_PASSIVE,       true)
    call SetPlayerAlliance(p, Player(udg_tempint), ALLIANCE_HELP_REQUEST,  true)
    call SetPlayerAlliance(p, Player(udg_tempint), ALLIANCE_HELP_RESPONSE, true)
    call SetPlayerAlliance(p, Player(udg_tempint), ALLIANCE_SHARED_XP,     true)
    call SetPlayerAlliance(p, Player(udg_tempint), ALLIANCE_SHARED_SPELLS, true)
    call SetPlayerAlliance(p, Player(udg_tempint), ALLIANCE_SHARED_VISION, true)
    call SetPlayerAlliance(Player(udg_tempint), p, ALLIANCE_PASSIVE,       true)
    call SetPlayerAlliance(Player(udg_tempint), p, ALLIANCE_HELP_REQUEST,  true)
    call SetPlayerAlliance(Player(udg_tempint), p, ALLIANCE_HELP_RESPONSE, true)
    call SetPlayerAlliance(Player(udg_tempint), p, ALLIANCE_SHARED_XP,     true)
    call SetPlayerAlliance(Player(udg_tempint), p, ALLIANCE_SHARED_SPELLS, true)
    call SetPlayerAlliance(Player(udg_tempint), p, ALLIANCE_SHARED_VISION, true)
    set p = null
endfunction

function AllyWithTempForce takes nothing returns nothing
    set udg_tempint = GetPlayerId(GetEnumPlayer())
    call ForForce(udg_tempforce,function AllyWithTempInt)
endfunction

function SetupAlliances takes nothing returns nothing
    local integer i
    local integer i2
    if udg_gamemode == 0 or udg_gamemode == 1 then
        set i = 0
        loop
            exitwhen i == udg_teamcount
            if udg_allpick then
                set i2 = 0
                loop
                    exitwhen i2 == udg_mapmaxteams
                    set udg_tempint = i2+12
                    call ForForce(udg_forces[i],function AllyWithTempInt)
                    set i2 = i2+1
                endloop
            else
                set udg_tempint = i+12
                call ForForce(udg_forces[i],function AllyWithTempInt)
            endif
            set i = i + 1
        endloop
    else
        if udg_gamemode == 2 or udg_gamemode == 3 then
            set i = 0
            loop
                exitwhen i == udg_mapmaxteams
                set udg_tempint = i+12
                call ForForce(udg_forces[4],function AllyWithTempInt)
                set i = i + 1
            endloop
        else
            //nothing- no gamemode 4 yet.
        endif
    endif
    loop
        exitwhen i == udg_teamcount
        set udg_tempforce = udg_forces[i]
        call ForForce(udg_forces[i], function AllyWithTempForce)
        set i = i + 1
    endloop
    call DisplayTextToPlayer(Player(0),0,0,"setupalliances")
endfunction

function ShrineEnterCondition takes nothing returns boolean
    return TargetTypeCondition(GetFilterUnit(),null,0)
endfunction

function InitShrines takes nothing returns nothing
    local trigger array shrinetrigs
    local trigger shrineticktrig = CreateTrigger()
    local string shrinetrigstring
    local integer shrinecount = 2
    local real tickinterval = 1
    local integer i
    local real range = 700
    set i = 0
    loop
        exitwhen i == shrinecount
        set shrinetrigs[i] = CreateTrigger()
        set shrinetrigstring = I2S(H2I(shrinetrigs[i]))
        call TriggerRegisterUnitInRange(shrinetrigs[i],udg_shrines[i],range,Condition(function ShrineEnterCondition))
        call StoreInteger(udg_gamecache,shrinetrigstring,"shrine",H2I(udg_shrines[i]))
        call StoreInteger(udg_gamecache,shrinetrigstring,"shrineindex",i)
        set udg_shrine2controller[i] = 4
        call TriggerAddAction(shrinetrigs[i],function ShrineEnter)
        set i = i + 1
    endloop
    call TriggerRegisterTimerEvent(shrineticktrig,tickinterval,true)
    call TriggerAddAction(shrineticktrig,function ShrineTick)
endfunction

function SetupForces takes nothing returns nothing
    local integer i
    local integer i2
    local integer i3
    local integer teamsize
    set i = 0
    set i2 = 0
    set i3 = 0
    loop
        exitwhen i == udg_teamcount //or i == 3
        set udg_forces[i] = CreateForce()
        call SetPlayerName(Player(12+i),"Team "+I2S(i+1))
        set teamsize = (udg_playercount-i3) / (udg_teamcount-i)
        loop
            exitwhen i3 == teamsize*(1+i) //or i2 == 7
            if IsPlayerInForce(Player(i2),udg_forces[4]) then
                set i3 = i3 + 1
                call ForceAddPlayer(udg_forces[i],Player(i2))
                set udg_player2force[i2] = i
                call DisplayTextToPlayer(Player(0),0,0,"adding player "+I2S(i2)+" to force "+I2S(i))
            endif
            set i2 = i2 + 1
        endloop
        set i = i + 1
    endloop
endfunction

function GameStart takes nothing returns nothing
    local timer addxpgoldtimer
    local real xpandgoldadddinterval = 1
    local integer i
    
    //Remove Cinematicmode
    call DisplayCineFilter(false)
    call ShowInterface(true, 0.1)
    call EnableUserUI(true)
    
    call SetupForces()
    call SetupAlliances()
    call SetupBoards()
    if udg_gamemode == 0 then
        call InitShrines()
    endif
    if not udg_killxpgold then
        set addxpgoldtimer = CreateTimer()
        call TimerStart(addxpgoldtimer,xpandgoldadddinterval,true,function AddXpGoldByTimer)
        set addxpgoldtimer = null
        set i = 0
        loop
            exitwhen i == 12
            call SetPlayerHandicapXP(Player(i), 0.00)
            set i = i + 1
        endloop
    else
        loop
            exitwhen i == 12    
            call SetPlayerState(Player(i), PLAYER_STATE_GIVES_BOUNTY, 1)
            set i = i + 1
        endloop
    endif
    call DisplayTextToPlayer(Player(0),0,0,"gamestart")
endfunction

//===================================================================================================================
//DIALOGCLICKS

function SetupGameoptionsdialog takes nothing returns nothing
    //HOTKEYS NOT OKAY
    call DialogClear(udg_dialog)
    set udg_dialogbuttons[0] = DialogAddButton(udg_dialog, "|cffffffffS|r|cffffcc00tart the Game!|r", 83)
    if udg_allpick then
        set udg_dialogbuttons[1] = DialogAddButton(udg_dialog, "|cffffffffA|r|cffffcc00llpick: on|r", 65)
    else
        set udg_dialogbuttons[1] = DialogAddButton(udg_dialog, "|cffffffffA|r|cffffcc00llpick: off|r", 65)    
    endif
    if udg_noherotypelimit then
        set udg_dialogbuttons[2] = DialogAddButton(udg_dialog, "|cffffffffN|r|cffffcc00o Herotype Limit: on|r", 78)  
    else
        set udg_dialogbuttons[2] = DialogAddButton(udg_dialog, "|cffffffffN|r|cffffcc00o Herotype Limit: off|r", 78)      
    endif
    if udg_killxpgold then
        set udg_dialogbuttons[3] = DialogAddButton(udg_dialog, "|cffffffffK|r|cffffcc00ill XP&Gold: on|r", 75)    
    else
        set udg_dialogbuttons[3] = DialogAddButton(udg_dialog, "|cffffffffK|r|cffffcc00ill XP&Gold: off|r", 75)        
    endif
    if udg_chooseattributes then
        set udg_dialogbuttons[4] = DialogAddButton(udg_dialog, "|cffffffffC|r|cffffcc00hoose Attributes: on|r", 67)    
    else
        set udg_dialogbuttons[4] = DialogAddButton(udg_dialog, "|cffffffffC|r|cffffcc00hoose Attributes: off|r", 67)        
    endif
    if udg_level4start then
        set udg_dialogbuttons[5] = DialogAddButton(udg_dialog, "|cffffffffL|r|cffffcc00evel 4 Start: on|r", 76)    
    else
        set udg_dialogbuttons[5] = DialogAddButton(udg_dialog, "|cffffffffL|r|cffffcc00evel 4 Start: off|r", 76)    
    endif
    if udg_mirrormatch then
        set udg_dialogbuttons[6] = DialogAddButton(udg_dialog, "|cffffffffM|r|cffffcc00irror Match: on|r", 77)    
    else
        set udg_dialogbuttons[6] = DialogAddButton(udg_dialog, "|cffffffffM|r|cffffcc00irror Match: off|r", 77)    
    endif
    if udg_oneherotype then
        set udg_dialogbuttons[7] = DialogAddButton(udg_dialog, "|cffffffff1|r|cffffcc00 Herotype: on|r", 49)    
    else
        set udg_dialogbuttons[7] = DialogAddButton(udg_dialog, "|cffffffff1|r|cffffcc00 Herotype: off|r", 49)    
    endif
    set udg_dialogstep = 4
    call DialogDisplay(udg_host,udg_dialog,true)
endfunction

function GameoptionsdialogClick takes nothing returns nothing
    local button button1 = GetClickedButton()
    if button1 == udg_dialogbuttons[0] then
        call GameStart()
    else
        if button1 == udg_dialogbuttons[1] then
            if udg_allpick then
                set udg_allpick = false
            else
                set udg_allpick = true
            endif
        else
            if button1 == udg_dialogbuttons[2] then
                if udg_noherotypelimit then
                    set udg_noherotypelimit = false
                else
                    set udg_noherotypelimit = true
                endif
            else
                if button1 == udg_dialogbuttons[3] then
                    if udg_killxpgold then
                        set udg_killxpgold = false
                    else
                        set udg_killxpgold = true
                    endif
                else
                    if button1 == udg_dialogbuttons[4] then
                        if udg_chooseattributes then
                            set udg_chooseattributes = false
                        else
                            set udg_chooseattributes = true
                        endif
                    else
                        if button1 == udg_dialogbuttons[5] then
                            if udg_level4start then
                                set udg_level4start = false
                            else
                                set udg_level4start = true
                            endif
                        else
                            if button1 == udg_dialogbuttons[6] then
                                if udg_mirrormatch then
                                    set udg_mirrormatch = false
                                else
                                    set udg_mirrormatch = true
                                endif
                            else
                                if button1 == udg_dialogbuttons[7] then
                                    if udg_oneherotype then
                                        set udg_oneherotype = false
                                    else
                                        set udg_oneherotype = true
                                    endif
                                else
                                    //nothing- only 8(7) gameoptions yet.
                                endif
                            endif
                        endif
                    endif
                endif
            endif
        endif
        call SetupGameoptionsdialog()
    endif
endfunction

function SetVictoryTarget takes integer gamelength returns nothing
    set gamelength = gamelength + 1
    if udg_gamemode == 0 then
        if udg_gamemode2 == 0 then
            set udg_victorytarget = gamelength*300
        elseif udg_gamemode2 == 1 then
            set udg_victorytarget = gamelength*400
        endif
    elseif udg_gamemode == 1 then
        if udg_gamemode2 == 0 then
            set udg_victorytarget = gamelength*10*R2I(udg_playercount/udg_teamcount)
        elseif udg_gamemode2 == 1 then
            set udg_victorytarget = gamelength*4*R2I(udg_playercount/udg_teamcount)
        endif
    elseif udg_gamemode == 2 then
        if udg_gamemode2 == 0 then
            set udg_victorytarget = gamelength*10
        elseif udg_gamemode2 == 1 then
            set udg_victorytarget = gamelength*4
        endif
    elseif true then
            
    endif  
endfunction

function GamelengthdialogClick takes nothing returns nothing
    local button button1 = GetClickedButton()
    if button1 == udg_dialogbuttons[0] then
        set udg_gamelength = 0
    else
        if button1 == udg_dialogbuttons[1] then
            set udg_gamelength = 1
        else
            if button1 == udg_dialogbuttons[2] then
                set udg_gamelength = 2
            else
                if button1 == udg_dialogbuttons[3] then
                    set udg_gamelength = 3
                else
                    //nothing- only 4different gamelengths now.
                endif
            endif
        endif
    endif      
    call SetVictoryTarget(udg_gamelength)  
    call SetupGameoptionsdialog()
endfunction

function SetupGamelengthdialog takes nothing returns nothing
    //HOTKEYS NOT OKAY
    call DialogClear(udg_dialog)
    set udg_dialogbuttons[0] = DialogAddButton(udg_dialog, "|cffffffffC|r|cffffcc00lose2Diner|r", 67)
    set udg_dialogbuttons[1] = DialogAddButton(udg_dialog, "|cffffffffR|r|cffffcc00ecommended|r", 82)
    set udg_dialogbuttons[2] = DialogAddButton(udg_dialog, "|cffffffffX|r|cffffcc00tra|r", 88)
    set udg_dialogbuttons[2] = DialogAddButton(udg_dialog, "|cffffffffU|r|cffffcc00ber|r", 85)
    set udg_dialogstep = 3
    call DialogDisplay(udg_host,udg_dialog,true)
endfunction

function TeamcountdialogClick takes nothing returns nothing
    local button button1 = GetClickedButton()
    if button1 == udg_dialogbuttons[0] then
        set udg_teamcount = 2
    else
        if button1 == udg_dialogbuttons[1] then
            set udg_teamcount = 3
        else
            if button1 == udg_dialogbuttons[2] then
                set udg_teamcount = 4
            else
                //nothing- only 3different teamammounts now.
            endif
        endif
    endif
    call SetupGamelengthdialog()
endfunction

function SetupTeamcountdialog takes nothing returns nothing
    if udg_mapmaxteams > 2 then
        call DialogClear(udg_dialog)
        set udg_dialogstep = 2
        set udg_dialogbuttons[0] = DialogAddButton(udg_dialog, "|cffffcc00Tw|r|cffffffffo|r|cffffcc00 teams|r", 79)
        set udg_dialogbuttons[1] = DialogAddButton(udg_dialog, "|cffffcc00Thre|r|cffffffffe|r|cffffcc00 teams|r", 68)
        if udg_mapmaxteams == 4 then
            set udg_dialogbuttons[2] = DialogAddButton(udg_dialog, "|cffffcc00Fou|r|cffffffffr|r|cffffcc00 teams|r", 82)
        endif
        call DialogDisplay(udg_host,udg_dialog,true)
    else
        set udg_teamcount = 2
        set udg_dialogstep = 3
        call SetupGamelengthdialog()
    endif
endfunction

function Gamemode2dialogClick takes nothing returns nothing
    local button button1 = GetClickedButton()
    if button1 == udg_dialogbuttons[0] then
        set udg_gamemode2 = 0
    else
        if button1 == udg_dialogbuttons[1] then
            set udg_gamemode2 = 1
        else
            //nothing- no gamemode2 3 yet.
        endif
    endif
    //Set up new dialog
    if udg_gamemode != 2 then
        call SetupTeamcountdialog()
    else
        call SetupGamelengthdialog()
    endif
endfunction

function SetupGamemode2dialog takes nothing returns nothing
    call DisplayTextToPlayer(Player(0),0,0,"setupgamemode2dialog")
    //HOTKEYS NOT OKAY
    call DialogClear(udg_dialog)
    set udg_dialogbuttons[0] = DialogAddButton(udg_dialog, "|cffffffffR|r|cffffcc00ace|r", 82)
    set udg_dialogbuttons[1] = DialogAddButton(udg_dialog, "|cffffffffO|r|cffffcc00utrun|r", 79)
    set udg_dialogbuttons[2] = DialogAddButton(udg_dialog, "|cffffffffT|r|cffffcc00imed|r", 84)
    set udg_dialogstep = 1
    call DialogDisplay(udg_host,udg_dialog,true)
endfunction

function InitLastManStanding takes nothing returns nothing
    set udg_gamemode2 = 2
    set udg_playersleft = udg_playercount
endfunction

function GamemodedialogClick takes nothing returns nothing
    local button button1 = GetClickedButton()
    call DisplayTextToPlayer(Player(0),0,0,"gamemodedialogclick")
    if button1 == udg_dialogbuttons[0] then
        set udg_gamemode = 0
    else
        if button1 == udg_dialogbuttons[1] then
            set udg_gamemode = 1
        else
            if button1 == udg_dialogbuttons[2] then
                set udg_gamemode = 2
            else
                if button1 == udg_dialogbuttons[3] then                
                    set udg_gamemode = 3
                    call InitLastManStanding()
                else
                    //nothing- no gamemode 4 yet.
                endif
            endif
        endif
    endif
    //Set up new dialog
    if udg_gamemode != 3 then
        call SetupGamemode2dialog()
    else
        call SetupGamelengthdialog()
    endif
endfunction

function SetupGamemodedialog takes nothing returns nothing
    call DisplayTextToPlayer(Player(0),0,0,"setupgamemodedialog")
    //HOTKEYS NOT OKAY
    call DialogClear(udg_dialog)
    set udg_dialogbuttons[0] = DialogAddButton(udg_dialog, "|cffffffffD|r|cffffcc00omination|r", 68)
    set udg_dialogbuttons[1] = DialogAddButton(udg_dialog, "|cffffffffT|r|cffffcc00eam Deathmatch|r", 84)
    set udg_dialogbuttons[2] = DialogAddButton(udg_dialog, "|cffffcc00Death|r|cffffffffm|r|cffffcc00atch|r", 77)
    set udg_dialogbuttons[3] = DialogAddButton(udg_dialog, "|cffffffffL|r|cffffcc00ast Man Standing|r", 76)
    set udg_dialogstep = 0
    call DialogDisplay(udg_host,udg_dialog,true)
endfunction

function DialogClick takes nothing returns nothing
    call DisplayTextToPlayer(Player(0),0,0,"dialogclick")
    if udg_dialogstep == 0 then
        call GamemodedialogClick()
    else
        if udg_dialogstep == 1 then
            call Gamemode2dialogClick()
        else
            if udg_dialogstep == 2 then
                call TeamcountdialogClick()
            else
                if udg_dialogstep == 3 then
                    call GamelengthdialogClick()
                else
                    if udg_dialogstep == 4 then
                        call GameoptionsdialogClick()
                    else
                    endif
                endif
            endif
        endif
    endif
endfunction

//==================================================================================================================
//Initialization
function GeneratePlaygroundHelp takes nothing returns nothing
    local real tilesize = 128
    local integer tileslong = R2I(RAbsBJ(GetRectMinY(udg_roughplayground)/tilesize)+(GetRectMaxY(udg_roughplayground)/tilesize))
    local integer i2
    local real x = udg_tempreal
    local real y
    set i2 = 0
    loop
        exitwhen i2 == tileslong
        set y = (i2+0.5-0.5*tileslong)*tilesize
        if IsTerrainPathable(x,y,PATHING_TYPE_WALKABILITY) then
            call RegionAddCell(udg_playground,x,y)
        endif
        set i2 = i2 + 1
    endloop
endfunction

function GeneratePlayground takes nothing returns nothing
    local real tilesize = 128
    local integer tileswide = R2I(RAbsBJ(GetRectMinX(udg_roughplayground)/tilesize)+(GetRectMaxX(udg_roughplayground)/tilesize))
    local integer i
    set i = 0
    loop
        exitwhen i == tileswide
        set udg_tempreal = (i+0.5-0.5*tileswide)*tilesize
        call ExecuteFunc("GeneratePlaygroundHelp")
        set i = i + 1
    endloop
endfunction

function doplayeractions takes nothing returns nothing
    local player p = GetEnumPlayer()
    call BJDebugMsg(GetPlayerName(GetEnumPlayer()))
    call ForceAddPlayer(udg_forces[4],p)
    call PlayerSetLeaderboard(p, udg_leaderboard)
    set udg_playercount = udg_playercount + 1
    call TriggerRegisterPlayerUnitEvent(udg_unitselected, p, EVENT_PLAYER_UNIT_SELECTED, null)
    call TriggerRegisterPlayerEvent(udg_temptrig, p, EVENT_PLAYER_LEAVE)
endfunction

function isplaying takes nothing returns boolean
    return GetPlayerSlotState(GetFilterPlayer()) == PLAYER_SLOT_STATE_PLAYING
endfunction

function InitRest takes nothing returns nothing
    local integer i 
    local trigger playerleavestrig = CreateTrigger()
    local real array tagxs
    local real array tagys
    local real tagsize = 10
    local integer boattagcount = 2
    
    //SET MAPSPECIFIC SHIT
    set udg_roughplayground = GetPlayableMapRect()
    set tagxs[0] = GetWidgetX(udg_boats[1])
    set tagys[0] = GetWidgetY(udg_boats[1])
    set tagxs[1] = GetWidgetX(udg_boats[3])
    set tagys[1] = GetWidgetY(udg_boats[3])
    set udg_mapmaxteams = 2
    //END OF MAPSPECIFIC SHIT
    
    call GeneratePlayground()
    
    //CREATE BOATTAGS
    set i = 0
    loop
        exitwhen i == boattagcount
        set udg_boattags[i] = CreateTextTag()
        call SetTextTagText(udg_boattags[i],"|cffffcc00Click on a boat|r",TextTagSize2Height(tagsize))
        call SetTextTagPos(udg_boattags[i],tagxs[i],tagys[i],0)
        call SetTextTagColor(udg_boattags[i],143,255,0,0)
        set i = i + 1
    endloop
    
    //SET PLAYER2COLORCODE
    set udg_player2colorcode[0] = 255
    set udg_player2colorcode[1] = 0
    set udg_player2colorcode[2] = 28
    set udg_player2colorcode[3] = 84
    set udg_player2colorcode[4] = 255
    set udg_player2colorcode[5] = 254
    set udg_player2colorcode[6] = 32
    set udg_player2colorcode[7] = 229
    set udg_player2colorcode[8] = 149
    set udg_player2colorcode[9] = 126
    set udg_player2colorcode[10] = 16
    set udg_player2colorcode[11] = 78
    set udg_player2colorcode[12] = 3
    set udg_player2colorcode[13] = 66
    set udg_player2colorcode[14] = 230
    set udg_player2colorcode[15] = 0
    set udg_player2colorcode[16] = 252
    set udg_player2colorcode[17] = 186
    set udg_player2colorcode[18] = 192
    set udg_player2colorcode[19] = 91
    set udg_player2colorcode[20] = 150
    set udg_player2colorcode[21] = 191
    set udg_player2colorcode[22] = 98
    set udg_player2colorcode[23] = 42
    set udg_player2colorcode[24] = 3
    set udg_player2colorcode[25] = 255
    set udg_player2colorcode[26] = 185
    set udg_player2colorcode[27] = 129
    set udg_player2colorcode[28] = 1
    set udg_player2colorcode[29] = 14
    set udg_player2colorcode[30] = 0
    set udg_player2colorcode[31] = 176
    set udg_player2colorcode[32] = 151
    set udg_player2colorcode[33] = 241
    set udg_player2colorcode[34] = 70
    set udg_player2colorcode[35] = 4
    
    //set udg_host = GetHost()
    set udg_host = Player(0)
    
    //setshipowners
    set i = 0
    loop
        call SetUnitOwner(udg_boats[i], Player(12), true)
        exitwhen i == 3
        set i = i + 1
    endloop
    loop
        call SetUnitOwner(udg_boats[i], Player(13), true)
        exitwhen  i == 5
        set i = i + 1
    endloop
    
    set udg_leaderboard = CreateLeaderboard()
    //PLAYER ACTIONS
    set udg_forces[4] = CreateForce()
    set udg_temptrig = playerleavestrig
    call ForForce(GetPlayersMatching(Condition(function isplaying)), function doplayeractions)
    
    call BJDebugMsg(I2S(udg_playercount))
    call TriggerAddAction(playerleavestrig,function PlayerLeaves)
    
    //START DIALOGS
    call TriggerSleepAction(0)
    
    call ShowInterface(false, 0.1)
    //call EnableUserControl(false)
    //call EnableOcclusion(false)
    
    call EnableUserUI(false)
    call SetCineFilterTexture("ReplaceableTextures\\CameraMasks\\Black_mask.blp")
    call SetCineFilterBlendMode(BLEND_MODE_BLEND)
    call SetCineFilterTexMapFlags(TEXMAP_FLAG_NONE)
    call SetCineFilterStartUV(0, 0, 1, 1)
    call SetCineFilterEndUV(0, 0, 1, 1)
    call SetCineFilterStartColor(0, 0, 0, 255)
    call SetCineFilterEndColor(0, 0, 0, 255)
    call SetCineFilterDuration(0)
    call DisplayCineFilter(true)
    call SetupGamemodedialog()
endfunction

//INIT HEROES==============================================================================
function InitHeroes takes nothing returns nothing
    //createtriggers
    local trigger dialogclick = CreateTrigger()
    local trigger unitbeginscasting = CreateTrigger()
    local trigger unitstopscasting = CreateTrigger()
    local trigger unitattacked = CreateTrigger()
    local trigger sunfall = CreateTrigger()
    local trigger sunrise = CreateTrigger()
    local trigger mapenter = CreateTrigger()
    local trigger skilllearned = CreateTrigger()
    local trigger targetorder = CreateTrigger()
    local trigger pointorder = CreateTrigger()
    local trigger immediateorder = CreateTrigger()
    local trigger levelgain = CreateTrigger(  )
    local trigger unitdies = CreateTrigger(  )
    local trigger unitspellfinish = CreateTrigger()
    local trigger unitspellstartseffect = CreateTrigger()
    
    //createtriggers
    set udg_unitdamaged = CreateTrigger()
    set udg_unitselected = CreateTrigger()
    
    //create dialog
    set udg_dialog = DialogCreate()
    
    //ini gamecache
    set udg_gamecache = InitGameCache("bestmap.w3v")
    
    //register trigger events and add actions
    call TriggerRegisterAnyUnitEventBJ( unitdies, EVENT_PLAYER_UNIT_DEATH )
    call TriggerAddAction( unitdies, function UnitDies )
    call TriggerRegisterAnyUnitEventBJ( levelgain, EVENT_PLAYER_HERO_LEVEL )
    call TriggerAddAction( levelgain, function LevelGain )
    call TriggerRegisterDialogEvent(dialogclick, udg_dialog)
    call TriggerAddAction(dialogclick, function DialogClick)
    call TriggerRegisterAnyUnitEventBJ(targetorder, EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER)
    call TriggerAddAction(targetorder, function TargetOrder)
    call TriggerRegisterAnyUnitEventBJ(pointorder, EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER)
    call TriggerAddAction(pointorder, function PointOrder)
    call TriggerRegisterAnyUnitEventBJ(immediateorder, EVENT_PLAYER_UNIT_ISSUED_ORDER)
    call TriggerAddAction(immediateorder, function ImmediateOrder)
    call TriggerRegisterAnyUnitEventBJ(unitbeginscasting, EVENT_PLAYER_UNIT_SPELL_CAST)
    call TriggerAddAction(unitbeginscasting, function UnitBeginsCasting)
    call TriggerRegisterAnyUnitEventBJ(unitstopscasting, EVENT_PLAYER_UNIT_SPELL_ENDCAST)
    call TriggerAddAction(unitstopscasting, function UnitStopsCasting)
    call TriggerRegisterAnyUnitEventBJ(unitspellfinish, EVENT_PLAYER_UNIT_SPELL_FINISH )
    call TriggerAddAction(unitspellfinish, function UnitSpellFinish)
    call TriggerRegisterAnyUnitEventBJ(unitspellstartseffect, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddAction(unitspellstartseffect, function UnitSpellStartsEffect)
    call TriggerRegisterAnyUnitEventBJ(unitattacked, EVENT_PLAYER_UNIT_ATTACKED)
    call TriggerAddAction(unitattacked, function UnitAttacked )
    call TriggerRegisterGameStateEventTimeOfDay(sunfall, GREATER_THAN_OR_EQUAL, 18.00)
    call TriggerRegisterGameStateEventTimeOfDay(sunfall, LESS_THAN, 6.01 )
    call TriggerAddAction(sunfall, function Sunfall)
    call TriggerRegisterGameStateEventTimeOfDay(sunrise, GREATER_THAN_OR_EQUAL, 6.01)
    call TriggerAddAction(sunrise, function Sunrise)
    call TriggerRegisterEnterRectSimple(mapenter, GetPlayableMapRect())
    call TriggerAddAction(mapenter, function MapEnter)
    call TriggerAddAction(udg_unitdamaged, function UnitDamaged)
    call TriggerAddAction(udg_unitselected, function UnitSelected)
    call TriggerRegisterAnyUnitEventBJ(skilllearned, EVENT_PLAYER_HERO_SKILL )
    call TriggerAddAction(skilllearned, function SkillLearned)
    
    //udg_buffs table
    
    set udg_buffs[0] = 'B003'  //Mindless (scizofrenia)
    set udg_buffs[1] = 'B004'  //Flood (dummy)
    set udg_buffs[2] = 'B006'  //Windswipe (dummy)
    set udg_buffs[3] = 'B00O'  //Target
    set udg_buffs[4] = 'B00A'  //Ignite (dummy)
    set udg_buffs[5] = 'B007'  //Vira (dummy)
    set udg_buffs[6] = 'B005'  //Bodyburn
    set udg_buffs[7] = 'B00C'  //Backshot (dummy)
    set udg_buffs[8] = 'B002'  //Airform
    set udg_buffs[9] = 'B00E'  //Poison Nova (dummy)
    set udg_buffs[10] = 'B00F' //Crippling Poison (dummy)
    set udg_buffs[11] = 'B00P' //P-O-W
    set udg_buffs[12] = 'B00I' //Poison Skin (dummy)
    set udg_buffs[13] = 'B00K' //Silencing Souls (dummy)
    set udg_buffs[14] = 'B00R' //Gather Mob
    set udg_buffs[15] = 'B00U' //Lure Dragon
    set udg_buffs[16] = 'B009' //Shadowlurk
    set udg_buffs[17] = 'B00M' //Possession (custom)
    set udg_buffs[18] = 'B00X' //Faerie Fire (lure dragon)
    set udg_buffs[19] = 'B00Y' //Ensnare (ambush ground)
    set udg_buffs[20] = 'B00Z' //Ensnare (ambush air)
    set udg_buffs[21] = 'B00M' //Ensnare (ambush air)
    
    //udg_showbuffs with matching buffabils table
    
    set udg_showbuffs[0] = 'B008'  //Vira
    set udg_showbuffs[1] = 'B00H'  //Poison (Poison Nova, Skin)
    set udg_showbuffs[2] = 'B00B'  //Silence
    set udg_showbuffs[3] = 'B00M'  //Hunted (public hunt)
    set udg_showbuffs[4] = 'B000'  //Soaked (flood)
    set udg_showbuffs[5] = 'B00G'  //Crippled (crippling poison)
    set udg_showbuffs[6] = 'B001'  //Burning (ignite)
    set udg_showbuffs[7] = 'B00N'  //Stunned (stun)
    set udg_showbuffs[8] = 'B010'  //Fall Back
    
    set udg_bufforders[0] = "cripple"
    set udg_bufforders[1] = "cripple"
    set udg_bufforders[2] = "soulburn"
    set udg_bufforders[3] = "faeriefire"
    set udg_bufforders[4] = "cripple"
    set udg_bufforders[5] = "cripple"
    set udg_bufforders[6] = "cripple"
    set udg_bufforders[7] = "thunderbolt"
    set udg_bufforders[8] = "cripple"
    
    //udg_buffuabils table
    set udg_buffabils[0] = 'A018'  //Cripple (vira)
    set udg_buffabils[1] = 'A02O'  //Cripple (Poison Nova,Skin)
    set udg_buffabils[2] = 'A02Q'  //Soul Burn (silence)
    set udg_buffabils[3] = 'A02R'  //Faerie Fire (public hunt)
    set udg_buffabils[4] = 'A00M'  //Cripple (flood)
    set udg_buffabils[5] = 'A02P'  //Cripple (Crippling Poison)
    set udg_buffabils[6] = 'A00G'  //Cripple (ignite)
    set udg_buffabils[7] = 'A008'  //Storm Bolt (stun)
    set udg_buffabils[8] = 'A03U'  //Cripple (Fall back)
    
    //udg_herotypes table
    
    set udg_herotypes[0] = 'O001'  //Lunatic
    set udg_herotypes[1] = 'N002'  //Flamelord
    set udg_herotypes[2] = 'O003'  //Windlord
    set udg_herotypes[3] = 'N000'  //Whisper
    set udg_herotypes[4] = 'O000'  //Mamak
    set udg_herotypes[5] = 'N001'  //Terminator
    set udg_herotypes[6] = 'O008'  //Venomancer
    set udg_herotypes[7] = 'U000'  //Bodyless
    set udg_herotypes[8] = 'H002'  //High Inquisitor
    set udg_herotypes[9] = 'H00J'  //Grand Marshal
    set udg_herotypes[10] = 'U001'  //Scarab King
    set udg_herotypes[11] = 'E000'  //Elven Prince 
    
    //udg_unittypes table
    
    set udg_unittypes[0] = 'n006'  //Plain Boy (sentry1)
    set udg_unittypes[1] = 'n008'  //Ambusher
    set udg_unittypes[2] = 'O002'  //Lunatic (wolf form)
    set udg_unittypes[3] = 'n00A'  //Man (MT)
    set udg_unittypes[4] = 'n009'  //Woman (MT)
    set udg_unittypes[5] = 'e001'  //Faerie Dragon (lure dragon)
    set udg_unittypes[6] = 'nvl2'  //Villager (windswipe)
    set udg_unittypes[7] = 'n005'  //Strong Cage
    set udg_unittypes[8] = 'n00B'  //Weak Cage
    //set udg_unittypes[9] =
    set udg_unittypes[10] = 'u003' //Burrowed Unit
    
    set udg_dummyunittypes[0] = 'h000'  //Caster
    set udg_dummyunittypes[1] = 'h001'  //Mine
    set udg_dummyunittypes[2] = 'h004'  //Tornado
    set udg_dummyunittypes[3] = 'h005'  //Shockwave
    set udg_dummyunittypes[4] = 'h009'  //MamakCollider
    set udg_dummyunittypes[5] = 'h00F'  //Peasant (lunatic)
    set udg_dummyunittypes[6] = 'h00B'  //Peasant (flamelord)
    set udg_dummyunittypes[7] = 'h00D'  //Peasant (windlord)
    set udg_dummyunittypes[8] = 'h00G'  //Peasant (whisper)
    set udg_dummyunittypes[9] = 'h00E'  //Peasant (mamak)
    set udg_dummyunittypes[10] = 'h00C' //Peasant (terminator)
    set udg_dummyunittypes[11] = 'H00H' //God
    set udg_dummyunittypes[12] = 'h00I' //Windlorddummytarget
    set udg_dummyunittypes[13] = 'h00V' //Collider
    //set udg_dummyunittypes[14] = 'h00M' //Weak Cage
    set udg_dummyunittypes[15] = 'n007' //Boy (sentry2)
    set udg_dummyunittypes[16] = 'h00K' //MobCollider
    set udg_dummyunittypes[17] = 'h00S' //Peasant (venomancer)
    set udg_dummyunittypes[18] = 'h00R' //Peasant (bodyless)
    set udg_dummyunittypes[19] = 'h00O' //Peasant (high inquisitor)
    set udg_dummyunittypes[20] = 'h00N' //Peasant (grand marshal)
    set udg_dummyunittypes[21] = 'h00P' //Peasant (scarab king)
    set udg_dummyunittypes[22] = 'h00Q' //Peasant (elven prince)
    set udg_dummyunittypes[23] = 'h00T' //Flood dummy
    set udg_dummyunittypes[24] = 'h00L' //Torch (mass teleport)
    
    // udg_destypes
    
    set udg_desttypes[0] = 'LTlt'  
    
    // udg_habils
    
    set udg_habils[0] = 'A00U'  //Flood
    set udg_habils[1] = 'A00D'  //Cannibalize
    set udg_habils[2] = 'A00C'  //Scizofrenia
    set udg_habils[3] = 'A006'  //Heritage
    set udg_habils[4] = 'A01A'  //Anger
    set udg_habils[5] = 'A00F'  //Ignite
    set udg_habils[6] = 'A00P'  //Concentrate
    set udg_habils[7] = 'A01B'  //Burnout
    set udg_habils[8] = 'A00I'  //Hop-A-Strike
    set udg_habils[9] = 'A02U' //Airform
    set udg_habils[10] = 'A00H'  //Meditate
    set udg_habils[11] = 'A00J' //Tornado
    set udg_habils[12] = 'A004' //Shadowlurk
    set udg_habils[13] = 'A01J' //Vira
    set udg_habils[14] = 'A002' //Bodyburn
    set udg_habils[15] = 'A007' //Backshot
    set udg_habils[16] = 'A009' //Charge
    set udg_habils[17] = 'A019' //Tusk Toss
    set udg_habils[18] = 'A00V' //Quadro Stomp
    set udg_habils[19] = 'A02H' //Blizzard (custom)
    set udg_habils[20] = 'A00E' //Hell Fires
    set udg_habils[21] = 'A02Z' //P-O-W
    set udg_habils[22] = 'A01O' //Coolant Flush
    set udg_habils[23] = 'A003' //Target
    set udg_habils[24] = 'A02J' //Poison Nova
    set udg_habils[25] = 'A03T' //Poison Skin
    set udg_habils[26] = 'A02K' //Crippling Poison
    set udg_habils[27] = 'A02M' //Underskin Eggs
    set udg_habils[28] = 'A01G' //Soul Sap
    set udg_habils[29] = 'A01H' //Silencing Souls
    set udg_habils[30] = 'A01F' //Decrepit Aura
    set udg_habils[31] = 'A01I' //Possession
    set udg_habils[32] = 'A036' //Ambush
    set udg_habils[33] = 'A031' //Sentry
    set udg_habils[34] = 'A01D' //Cage
    set udg_habils[35] = 'A035' //Gather Mob
    set udg_habils[36] = 'A02T' //Killed Your Fathers
    set udg_habils[37] = 'A034' //Trample
    set udg_habils[38] = 'A037' //Fall Back
    set udg_habils[39] = 'A02S' //Grand Charge
    set udg_habils[40] = 'A01V' //Disect
    set udg_habils[41] = 'A01W' //Burrow
    set udg_habils[42] = 'A03F' //Sand Storm
    set udg_habils[43] = 'A03E' //Fly
    set udg_habils[44] = 'A038' //Enchant Glaives
    set udg_habils[45] = 'A03A' //Lure Dragon
    set udg_habils[46] = 'A03C' //Mana Grab
    set udg_habils[47] = 'A03D' //Shield Magic
    set udg_habils[48] = 'A00L' //Windswipe
    set udg_habils[49] = 'A000' //Moon Crave
    
    //udg_uabils with matching udg_orders
    
    set udg_uabils[0] = 'A00T'  //Crushing Wave (flood)
    set udg_uabils[1] = 'A02V'  //Blizzard (blizzard)
    set udg_uabils[2] = 'A00Q'  //Spirit Link (scizofrenia)
    set udg_uabils[3] = 'A01K'  //Silence (scizofrenia)
    set udg_uabils[4] = 'A00B'  //Humanoid Form (heritage)
    set udg_uabils[5] = 'A00A'  //Wolf Form (heritage)
    set udg_uabils[6] = 'A02W'  //Cloud (blizzard)
    set udg_uabils[7] = 'A02X'  //Healing Spray (hell fires)
    set udg_uabils[8] = 'A01N'  //Cloud (coolant flush)
    set udg_uabils[9] = 'A02D'  //Healing Spray (shipfire)
    set udg_uabils[10] = 'A02C' //Add Strength
    set udg_uabils[11] = 'A02E' //Add Agility
    set udg_uabils[12] = 'A02F' //Add Intelligence
    set udg_uabils[13] = 'A02G' //Healing Spray (windswipe)
    set udg_uabils[14] = 'A01T' //Spellbook (airform1)
    set udg_uabils[15] = 'A02N' //Carrion Swarm (Poison Nova)
    set udg_uabils[16] = 'A005' //Shadow Strike (Hell Fires)
    set udg_uabils[17] = 'A02Y' //Healing Spray (coolant flush)
    set udg_uabils[18] = 'A030' //Curse
    set udg_uabils[19] = 'A03B' //Faerie Fire(lure dragon)
    set udg_uabils[20] = 'S000' //Chaos (burrowed)
    set udg_uabils[21] = 'A03H' //Healing Spray (silencing souls)
    set udg_uabils[22] = 'A00A' //Wolf Form
    set udg_uabils[23] = 'A01E' //Chemical Rage (windswipe)
    set udg_uabils[24] = 'A03J' //Spellbook (airform2)
    set udg_uabils[25] = 'A03T' //Spellbook (airform3)
    set udg_uabils[26] = 'A03U' //Spellbook (airform4)
    set udg_uabils[27] = 'A03V' //Spellbook (airform5)
    set udg_uabils[28] = 'A03W' //Spellbook (airform6)
    set udg_uabils[29] = 'A03X' //Spellbook (airform7)
    set udg_uabils[30] = 'A03Y' //Spellbook (airform8)
    set udg_uabils[31] = 'A03Z' //Spellbook (airform9)
    set udg_uabils[32] = 'A040' //Spellbook (airform10)
    set udg_uabils[33] = 'A041' //Spellbook (airform11)
    set udg_uabils[34] = 'S007' //Chaos (pow lunatic)
    set udg_uabils[35] = 'S00D' //Chaos (pow flamelord)
    set udg_uabils[36] = 'S005' //Chaos (windlord)
    set udg_uabils[37] = 'S00C' //Chaos (pow whisper)
    set udg_uabils[38] = 'S003' //Chaos (pow mamak)
    set udg_uabils[39] = 'S002' //Chaos (pow terminator)
    set udg_uabils[40] = 'S00B' //Chaos (pow venomancer)
    set udg_uabils[41] = 'S009' //Chaos (pow bodyless)
    set udg_uabils[42] = 'S004' //Chaos (pow high inquisitor)
    set udg_uabils[43] = 'S00A' //Chaos (pow grand marshal)
    set udg_uabils[44] = 'S008' //Chaos (pow scarab king)
    set udg_uabils[45] = 'S006' //Chaos (pow elven prince)
    set udg_uabils[46] = 'S001' //Chaos (pow lunaticwolf)
    set udg_uabils[47] = 'S00E' //Chaos (windswipe1)
    set udg_uabils[48] = 'S00F' //Chaos (windswipe2)
    set udg_uabils[49] = 'S00G' //Chaos (windswipe3)
    set udg_uabils[50] = 'S00H' //Chaos (windswipe4)
    set udg_uabils[51] = 'S00I' //Chaos (windswipe5)
    set udg_uabils[52] = 'S00J' //Chaos (windswipe6)
    set udg_uabils[53] = 'S00K' //Chaos (windswipe7)
    set udg_uabils[54] = 'S00L' //Chaos (windswipe8)
    set udg_uabils[55] = 'S00M' //Chaos (windswipe9)
    set udg_uabils[56] = 'S00N' //Chaos (windswipe10)
    set udg_uabils[57] = 'S00O' //Chaos (windswipe11)
    set udg_uabils[58] = 'A03H' //Bash (Windswipe passive)
    set udg_uabils[59] = 'A01C' //Bloodlust
    set udg_uabils[60] = 'A04D' //Purge
    set udg_uabils[61] = 'A03J' //Permanent Invisibility (pow)
    set udg_uabils[62] = 'A02L' //Frost Armor (poison skin)
    
    set udg_orders[0] = "carrionswarm"
    set udg_orders[1] = "blizzard"
    set udg_orders[2] = "spiritlink"
    set udg_orders[3] = "silence"
    set udg_orders[4] = "bearform"
    set udg_orders[5] = "bearform"
    set udg_orders[6] = "cloudoffog"
    set udg_orders[7] = "healingspray"
    set udg_orders[8] = "cloudoffog"
    set udg_orders[9] = "healingspray"
    set udg_orders[13] = "healingspray"
    set udg_orders[14] = "healingspray"
    set udg_orders[15] = "carrionswarm"
    set udg_orders[16] = "shadowstrike"
    set udg_orders[17] = "healingspray"
    set udg_orders[18] = "curse"
    set udg_orders[19] = "faeriefire"
    set udg_orders[21] = "healingspray"
    set udg_orders[22] = "bearform"
    set udg_orders[23] = "chemicalrage"
    set udg_orders[59] = "bloodlust"
    set udg_orders[60] = "purge"
    set udg_orders[62] = "frostarmor"

endfunction

//DEBUG==============================================================================
function MakeDay takes nothing returns nothing
    call SetTimeOfDay( 5.90 )
endfunction

function MakeNight takes nothing returns nothing
    call SetTimeOfDay( 17.90 )
endfunction

function ShowMoveSpeed takes nothing returns nothing
    call Msg(R2S(GetUnitMoveSpeed(GroupPickRandomUnit(GetUnitsSelectedAll(Player(0))))))
endfunction

function ShowAnimation takes nothing returns nothing
    call SetUnitAnimationByIndex(GroupPickRandomUnit(GetUnitsSelectedAll(Player(0))), S2I(SubStringBJ(GetEventPlayerChatString(), 1, ( StringLength(GetEventPlayerChatString()) - 3 ))) )
endfunction

function ClearHero takes nothing returns nothing
    call CastWidgetAbility(Player(0),60,1,GroupPickRandomUnit(GetUnitsSelectedAll(Player(0))),0)
endfunction

function ShowName takes nothing returns nothing
    call Msg(GetUnitName(GroupPickRandomUnit(GetUnitsSelectedAll(Player(0)))))
endfunction

function InitDebug takes nothing returns nothing
    local trigger trig_MakeDay = CreateTrigger()
    local trigger trig_MakeNight = CreateTrigger()
    local trigger trig_ShowMoveSpeed = CreateTrigger()
    local trigger trig_ShowAnimation = CreateTrigger()
    local trigger trig_ClearHero = CreateTrigger()
    local trigger trig_ShowName = CreateTrigger()
    
    call TriggerRegisterPlayerChatEvent( trig_ShowName, Player(0), "name", true )
    call TriggerAddAction( trig_ShowName, function ShowName )
    call TriggerRegisterPlayerChatEvent( trig_MakeDay, Player(0), "day", true )
    call TriggerAddAction( trig_MakeDay, function MakeDay )
    call TriggerRegisterPlayerChatEvent( trig_ClearHero, Player(0), "clearhero", true )
    call TriggerAddAction( trig_ClearHero, function ClearHero )
    call TriggerRegisterPlayerChatEvent( trig_MakeNight, Player(0), "night", true )
    call TriggerAddAction( trig_MakeNight, function MakeNight )
    call TriggerRegisterPlayerChatEvent( trig_ShowMoveSpeed, Player(0), "ms", true )
    call TriggerAddAction( trig_ShowMoveSpeed, function ShowMoveSpeed )
    call TriggerRegisterPlayerChatEvent( trig_ShowAnimation, Player(0), "ani", false )
    call TriggerAddAction( trig_ShowAnimation, function ShowAnimation )
endfunction

//HeroTestMap==============================================================================
function RifleAliveCondition takes nothing returns boolean
    return (GetUnitTypeId(GetFilterUnit()) == 'h006' and  IsUnitAliveBJ(GetFilterUnit()) == true)
endfunction

function FootmenAliveCondition takes nothing returns boolean
    return (GetUnitTypeId(GetFilterUnit()) == 'h003' and  IsUnitAliveBJ(GetFilterUnit()) == true)
endfunction

function PaladinAliveCondition takes nothing returns boolean
    return (GetUnitTypeId(GetFilterUnit()) == 'H00M' and  IsUnitAliveBJ(GetFilterUnit()) == true)
endfunction

function RefreshLifeAndMana takes nothing returns nothing
    call SetUnitManaPercentBJ( GetEnumUnit(), 100 )
    call SetUnitLifePercentBJ( GetEnumUnit(), 100 )
endfunction

function HeroTestMapRefresh takes nothing returns nothing
    local integer i = 0
    local integer riflecount = 3
    local integer footmencount = 2
    local integer paladincount = 1
    local integer endindex = ( riflecount - 1 - CountUnitsInGroup(GetUnitsOfPlayerMatching(Player(PLAYER_NEUTRAL_AGGRESSIVE), Condition(function RifleAliveCondition))) )
    if udg_test_refreshheroes then
    call ForGroupBJ( GetUnitsOfPlayerAll(Player(0)), function RefreshLifeAndMana )
    endif
    
    loop
        exitwhen i > endindex
        call CreateNUnitsAtLoc( 1, 'h006', Player(PLAYER_NEUTRAL_AGGRESSIVE), GetRectCenter(gg_rct_Rect_001), bj_UNIT_FACING )
        //Enable rifle flying
        call UnitAddAbilityBJ( 'Amrf', GetLastCreatedUnit() )
        call UnitRemoveAbilityBJ( 'Amrf', GetLastCreatedUnit() )
        //Add to udg_unitdamaged eventlist
        call TriggerRegisterUnitEvent( udg_unitdamaged, GetLastCreatedUnit(), EVENT_UNIT_DAMAGED )
        set i = i + 1
    endloop
    
    set i = 0
    set endindex = ( footmencount - 1 - CountUnitsInGroup(GetUnitsOfPlayerMatching(Player(PLAYER_NEUTRAL_AGGRESSIVE), Condition(function FootmenAliveCondition))) )
    loop
        exitwhen i > endindex
        call CreateNUnitsAtLoc( 1, 'h003', Player(PLAYER_NEUTRAL_AGGRESSIVE), GetRectCenter(gg_rct_Rect_000), bj_UNIT_FACING )
        call UnitAddAbilityBJ( 'Amrf', GetLastCreatedUnit() )
        call UnitRemoveAbilityBJ( 'Amrf', GetLastCreatedUnit() )
        call TriggerRegisterUnitEvent( udg_unitdamaged, GetLastCreatedUnit(), EVENT_UNIT_DAMAGED )
        set i = i + 1
    endloop    
    
    set i = 0
    set endindex = ( paladincount - 1 - CountUnitsInGroup(GetUnitsOfPlayerMatching(Player(PLAYER_NEUTRAL_AGGRESSIVE), Condition(function PaladinAliveCondition))) )
    loop
        exitwhen i > endindex
        call CreateNUnitsAtLoc( 1, 'H00M', Player(PLAYER_NEUTRAL_AGGRESSIVE), GetRectCenter(gg_rct_Rect_002), bj_UNIT_FACING )
        call UnitAddAbilityBJ( 'Amrf', GetLastCreatedUnit() )
        call UnitRemoveAbilityBJ( 'Amrf', GetLastCreatedUnit() )
        call TriggerRegisterUnitEvent( udg_unitdamaged, GetLastCreatedUnit(), EVENT_UNIT_DAMAGED )
        set i = i + 1
    endloop
endfunction

function SetupUnit takes nothing returns nothing
    //Enable the unit to fly by adding & removing a flying ability.
    call UnitAddAbilityBJ( 'Amrf', GetEnumUnit() )
    call UnitRemoveAbilityBJ( 'Amrf', GetEnumUnit() )
    //Insert the unit into the eventlist of the trigger "udg_unitdamaged"
    call TriggerRegisterUnitEvent( udg_unitdamaged, GetEnumUnit(), EVENT_UNIT_DAMAGED )
    //
    call IssueImmediateOrderBJ( GetEnumUnit(), "holdposition" )
endfunction

function SwitchHeroRefresh takes nothing returns nothing
    if udg_test_refreshheroes == false then
        set udg_test_refreshheroes = true
        call Msg("hero refresh is now on")
    else
        set udg_test_refreshheroes = false        
        call Msg("hero refresh is now off")
    endif
endfunction

function InitHeroTestMap takes nothing returns nothing
    local trigger trig_HeroTestMapRefresh = CreateTrigger()
    local trigger trig_SwitchHeroRefresh = CreateTrigger()
    
    call TriggerRegisterTimerEventPeriodic( trig_HeroTestMapRefresh, 2 )
    call TriggerAddAction( trig_HeroTestMapRefresh, function HeroTestMapRefresh )
    call TriggerRegisterPlayerChatEvent( trig_SwitchHeroRefresh, Player(0), "herorefresh", false )
    call TriggerAddAction( trig_SwitchHeroRefresh, function SwitchHeroRefresh )
    call TriggerRegisterPlayerUnitEvent(udg_unitselected, Player(0), EVENT_PLAYER_UNIT_SELECTED, null)
      
    set udg_test_refreshheroes = true
    call TriggerSleepAction( 1.00 )
    //Disable Ability "Chemical Rage (windswipe)"
    call SetPlayerAbilityAvailableBJ( false, 'A01E', Player(0) )
    //
    call SetHandleBoolean(udg_test_lunatic,"morphdone",true)
    call SetTimeOfDay( 14.00 )
    call CreateFogModifierRectBJ( true, Player(0), FOG_OF_WAR_VISIBLE, GetPlayableMapRect() )
    call ForGroupBJ( GetUnitsInRectAll(GetPlayableMapRect()), function SetupUnit )
    
    call TriggerSleepAction(1)
    call RegionAddRect( udg_playground, gg_rct_Playground )
endfunction


Thanks!
Lordy
__________________
Being against ALL BJ is like being against ALL code written by other people.

Last edited by Lordy : 02-20-2007 at 03:17 PM.
Lordy is offline   Reply With Quote
Sponsored Links - Login to hide this ad!
Old 02-20-2007, 03:41 AM   #2
Av3n
Roar!
 
Av3n's Avatar


Project Leader: TBR
Project Member: PoC
 
Join Date: May 2006
Posts: 1,854

Submissions (7)

Av3n is a jewel in the rough (240)Av3n is a jewel in the rough (240)Av3n is a jewel in the rough (240)Av3n is a jewel in the rough (240)Av3n is a jewel in the rough (240)

Hero #4 extra-official winner2008 Spell olympics - Fire - BronzeHero Contest #3 - 3rd Place

Default

.. ever heard of JASS or TRIGGER tags boy, use JASScraft , Jass newgen paxck or PJASS to check ur code

-Av3n
__________________

Thanks to FatherTime for the sig
.:
Current ProjectsSubmissions
Power of CorruptionMy Terrain
The Black RoadMy Resources
Strikeforce
Twitter

Last edited by Av3n : 02-20-2007 at 03:42 AM.
Av3n is offline   Reply With Quote
Old 02-20-2007, 03:52 AM   #3
Alevice
It feels good
 
Alevice's Avatar
 
Join Date: Mar 2006
Posts: 1,305

Alevice is a jewel in the rough (190)Alevice is a jewel in the rough (190)Alevice is a jewel in the rough (190)

Default

Quote:
Originally Posted by Av3n
use JASScraft , Jass newgen paxck or PJASS to check ur code

what would they help with? he is not having syntax errors. I would agree with the individual excerpts point, tho
__________________
_-|-_

Alevice.jones is SC2 Beta, losers.

Check out my never updated deviantart gallery!!

Kalimdor Raiders (Race Contest #1) Pastebin Page
Cavern Crawlers (Race Contest #2) Pastebin Page
Airship Race Motherfuckers!
Quote:
Originally Posted by http://ajaxian.com/archives/would-you-like-a-_-with-that-new-library-gives-js-what-it-should-have#comment-276203
- Dont solve problems that dont exist.
- Improve the wheel, dont reinvent it.
- Port the wheel if it doesnt exist in your environment.
- Integrate the wheel into your project.
- Make sure you can replace your wooden wheel for a rubber one if someone else invents it.
Alevice is offline   Reply With Quote
Old 02-20-2007, 05:02 AM   #4
Av3n
Roar!
 
Av3n's Avatar


Project Leader: TBR
Project Member: PoC
 
Join Date: May 2006
Posts: 1,854

Submissions (7)

Av3n is a jewel in the rough (240)Av3n is a jewel in the rough (240)Av3n is a jewel in the rough (240)Av3n is a jewel in the rough (240)Av3n is a jewel in the rough (240)

Hero #4 extra-official winner2008 Spell olympics - Fire - BronzeHero Contest #3 - 3rd Place

Default

Off topic: Is it just me or are you an secondary art director?

-Av3n
__________________

Thanks to FatherTime for the sig
.:
Current ProjectsSubmissions
Power of CorruptionMy Terrain
The Black RoadMy Resources
Strikeforce
Twitter
Av3n is offline   Reply With Quote
Old 02-20-2007, 10:31 AM   #5
Lordy
User
 
Lordy's Avatar
 
Join Date: May 2006
Posts: 72

Submissions (1)

Lordy has little to show at this moment (7)

Send a message via MSN to Lordy
Default

Quote:
Originally Posted by Av3n
.. ever heard of JASS or TRIGGER tags boy, use JASScraft , Jass newgen paxck or PJASS to check ur code

-Av3n

Hmm, what are the tags and what are they for?
And yes thank god I have been using Jasscraft and of lately I have been running the world editor from the Jass newgen pack which to my knowdlegde uses PJASS to parse my code for errors :), everytime I press the test map button.
__________________
Being against ALL BJ is like being against ALL code written by other people.
Lordy is offline   Reply With Quote
Old 02-20-2007, 01:15 PM   #6
WNxCryptic
User
 
WNxCryptic's Avatar
 
Join Date: Dec 2006
Posts: 257

WNxCryptic is on a distinguished road (24)

Default

Jass tags are used to put things here on the boards in their seperate box so they can easily be identified as jass:

Collapse JASS:
function blah blah rar takes nothing returns my foot

endfunction

Its done by using [ JASS ] (without spaces) and ending the code with [ /JASS ] (again, without spaces).
__________________
WNxCryptic is offline   Reply With Quote
Old 02-20-2007, 02:26 PM   #7
Alevice
It feels good
 
Alevice's Avatar
 
Join Date: Mar 2006
Posts: 1,305

Alevice is a jewel in the rough (190)Alevice is a jewel in the rough (190)Alevice is a jewel in the rough (190)

Default

Quote:
Originally Posted by Av3n
Off topic: Is it just me or are you an secondary art director?

You make 'secondary' sound as a bad thing.
__________________
_-|-_

Alevice.jones is SC2 Beta, losers.

Check out my never updated deviantart gallery!!

Kalimdor Raiders (Race Contest #1) Pastebin Page
Cavern Crawlers (Race Contest #2) Pastebin Page
Airship Race Motherfuckers!
Quote:
Originally Posted by http://ajaxian.com/archives/would-you-like-a-_-with-that-new-library-gives-js-what-it-should-have#comment-276203
- Dont solve problems that dont exist.
- Improve the wheel, dont reinvent it.
- Port the wheel if it doesnt exist in your environment.
- Integrate the wheel into your project.
- Make sure you can replace your wooden wheel for a rubber one if someone else invents it.
Alevice is offline   Reply With Quote
Old 02-20-2007, 04:35 PM   #8
BlinkBoy
User
 
BlinkBoy's Avatar


Respected User
 
Join Date: Dec 2003
Posts: 835

Submissions (4)

BlinkBoy has a spectacular aura about (97)BlinkBoy has a spectacular aura about (97)BlinkBoy has a spectacular aura about (97)BlinkBoy has a spectacular aura about (97)

Outstanding Tutorial

Default

hmm, many of your functions can be optimized alot, first why do you got constant functions that create a big array of and assigns the same value to all of those arrays?

like:

Collapse JASS:
constant function IntAdd takes integer heronumber returns real
    local real array intadds
    set intadds[0] = 2
    set intadds[1] = 2
    set intadds[2] = 2
    set intadds[3] = 2
    set intadds[4] = 2
    set intadds[5] = 2
    set intadds[6] = 2
    set intadds[7] = 2
    set intadds[8] = 2
    set intadds[9] = 2
    set intadds[10] = 2
    set intadds[11] = 2
    return intadds[heronumber]
endfunction

you should just use 2 or a constant variable for 2. But I guess that I got not much knowledge of constant functions, so you may forget it.

anyways you should replace this function:

Collapse JASS:
constant function TwoPowInt takes integer i returns integer
    local integer a
    local integer b
    if i == 0 then
        return 0
    elseif i == 1 then
        return 2
    elseif i == 2 then
        return 4
    elseif i == 3 then
        return 8
    elseif i == 4 then
        return 16
    elseif i == 5 then
        return 32
    elseif i == 6 then
        return 64
    elseif i == 7 then
        return 128
    elseif i == 8 then
        return 256
    elseif i == 9 then
        return 512
    elseif i == 10 then
        return 1024
    elseif i == 11 then
        return 2048
    elseif i == 12 then
        return 4096
    elseif i > 12 then
        set a = 12
        set b = 4096
        loop
            exitwhen a == i
            set b = b * 2
            set a = a + 1
        endloop
        return b
    endif
    return 0
endfunction

for this one:

Collapse JASS:
// this is if you only want power of 2
function Power2 takes integer pw returns integer
if pw != 1 then
  return 2*Power2(pw - 1)
endif
return 2
endfunction
// Power, general.
function Power takes real num, integer pw returns real
if pw != 0 then
  return num*Power(pw - 1)
endif
return 1
endfunction
// both function use recurtion, the act of a function to call itself

well Idon't got much time to read everything, but that's why I've seen so far.
__________________
Tools:
NeoDex - a Gmax and 3ds Max modeling Toolset for Wc3!

Learn to animate! check out my: Basic Animation Tutorial!

Currently working at a sequel to my animation tutorial.

Last edited by BlinkBoy : 02-20-2007 at 04:37 PM.
BlinkBoy is offline   Reply With Quote
Old 02-21-2007, 03:20 AM   #9
Av3n
Roar!
 
Av3n's Avatar


Project Leader: TBR
Project Member: PoC
 
Join Date: May 2006
Posts: 1,854

Submissions (7)

Av3n is a jewel in the rough (240)Av3n is a jewel in the rough (240)Av3n is a jewel in the rough (240)Av3n is a jewel in the rough (240)Av3n is a jewel in the rough (240)

Hero #4 extra-official winner2008 Spell olympics - Fire - BronzeHero Contest #3 - 3rd Place

Default

Quote:
Originally Posted by Alevice
You make 'secondary' sound as a bad thing.

No im not im just shocked that yr an art director

-Av3n
__________________

Thanks to FatherTime for the sig
.:
Current ProjectsSubmissions
Power of CorruptionMy Terrain
The Black RoadMy Resources
Strikeforce
Twitter
Av3n is offline   Reply With Quote
Old 02-21-2007, 03:21 AM   #10
Alevice
It feels good
 
Alevice's Avatar
 
Join Date: Mar 2006
Posts: 1,305

Alevice is a jewel in the rough (190)Alevice is a jewel in the rough (190)Alevice is a jewel in the rough (190)

Default

Ha!
__________________
_-|-_

Alevice.jones is SC2 Beta, losers.

Check out my never updated deviantart gallery!!

Kalimdor Raiders (Race Contest #1) Pastebin Page
Cavern Crawlers (Race Contest #2) Pastebin Page
Airship Race Motherfuckers!
Quote:
Originally Posted by http://ajaxian.com/archives/would-you-like-a-_-with-that-new-library-gives-js-what-it-should-have#comment-276203
- Dont solve problems that dont exist.
- Improve the wheel, dont reinvent it.
- Port the wheel if it doesnt exist in your environment.
- Integrate the wheel into your project.
- Make sure you can replace your wooden wheel for a rubber one if someone else invents it.
Alevice is offline   Reply With Quote
Old 02-22-2007, 11:10 AM   #11
Lordy
User
 
Lordy's Avatar
 
Join Date: May 2006
Posts: 72

Submissions (1)

Lordy has little to show at this moment (7)

Send a message via MSN to Lordy
Default

To blinkboy:
Thanks for reading some! +Rep.
-The first constant function has a lot of the same values, those values have yet to be changed though when I balance the map.

-The power of two function has some values already set with the purpose of reducing computational workload, this is probably a rather useless reduction of computation. The recursive way of writing the power of two function is correct yes, but I doubt if it is faster than a non-recursive loop Power of 2 function.

I should probably just upload my map, else it's hard to make a lot of sense of my code. I attached the map in this post. Shoulda change the first post but.. whatever..
Attached Files
File Type: w3x febnieuwedittestversieherotestmap.w3x (623.5 KB, 11 views)
__________________
Being against ALL BJ is like being against ALL code written by other people.

Last edited by Lordy : 02-22-2007 at 10:24 PM.
Lordy is offline   Reply With Quote
Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off


All times are GMT. The time now is 08:38 AM.


Affiliates
The Hubb The JASS Vault Clan WEnW Campaign Creations Clan CBS GamesModding Flixreel Videos

Powered by vBulletin (Copyright ©2000 - 2019, Jelsoft Enterprises Ltd).
Hosted by www.OICcam.com
IT Support and Services provided by Executive IT Services