• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

Triggers

(6)BanditSilverpine v1.8c.w3x
Variables
Initialization
Melee Initialization
Timer Time Elapsed Initialization
Timer Time Elapsed Update
Bandit Mechanics
Bandit Kill Income
Bandit Pub Add Ability
Bandit Pub Replace Ability
Remove Set Rally Point
Bandit Pub Mercenary Recruitment Pool
Bandit Pub Gacha
Bandit Ruins Gacha
Bandit Breeding Pit
Bandit Breeding Pit Gacha
Bandit Commission
Bandit Commission Dragons
Bandit Hire Refund
Bandit Veteran Mercenaries
Bandit Elite Mercenaries
Bandit Ruins Add Ability
Bandit Ruins Mercenary Recruitment Pool
Bandit Market Add Item Pool
Bandit Market Item Pool
Remove Buildings Pool
Lootbox
---------------------------
Custom Skills
March of Time
Black Flag
Corpse Explosion Cancel Cast
Corpse Explosion Cast
Corpse Explosion Damage
Dark Portal
Cornered Animal Learn
Cornered Animal
Mass Invisibility
Entrap
Entrap Cancelled
-----Misc-----
Debug Hidden Spellbooks Revive
Debug Hidden Spellbooks Retrain
PDD Damage Library [looking_for_help]
DamageEvent
---------------------------
Backstab
Backstab Aura Add
Backstab Aura Remove
Effect Over Time System (EOT) [Wietlol]
EOT System
DOT Extension
Dispel Magic
Spell Steal
Purge
Disenchant
Disenchant Old
Anti Magic Shell
Devour Magic
Devour Magic Neutral Hostile
Detonate
Abolish Magic
---------------------------
Ray of Enfeeblement
Shield Smash
Knockback 2D [Bribe]
Requirement
Unit Indexer
---------------------------
Knockback 2D Config
Knockback 2D Destroy
Knockback 2D
Knockback 2D System
Knockback 2D Demo Related
On Damage
On Damage Copy
On Impact
On Spell Cast
On Spell Stop
Test
Charge Libraries
CREDITS
HOW TO IMPORT
Math
HandleTimers
Walkable
Knockback
Charge [Majin]
ChargeConfig
ChargeExec
Jump System [Paladon]
---------------------------
Readme
---------------------------
Jump System 1
Jump System 2
---------------------------
Actions to apply
---------------------------
Sample Spell Jump
Jump Slam
Jump Slam End
https://www.hiveworkshop.com/threads/no-town-hall-warning-for-custom-race.315986/#post-3351678
BloodSoul vJASS code for checking by town-hall classification.
//TESH.scrollpos=363
//TESH.alwaysfold=0
//==============================================================================================//
// WARNING: YOU MUST PASTE THE FOLLOWING CODE IN A PLACE WHERE YOUR "INITIALIZATION TRIGGER"... //
// IS CAPABLE OF ACCESSING IT. IT'S RECOMMENDED THAT YOU PASTE IT IN YOUR MAP HEADER            //
//                                                                                              //
// The main purpose of this is to just get rid of the bug where custom units flagged as         //
// town hall doesn't count for the CripplePlayer function. I also removed a few leaks generated //
// by Blizzard.                                                                                 //
//                                                                                              //
//==============================================================================================//


// Count units flagged as UNIT_TYPE_TOWNHALL
function GetAllyKeyStructureCount takes player whichPlayer returns integer
    local unit fog = null
    local group g = CreateGroup()
    local integer result = 0
    local integer playerIndex = 0
    
    loop
        exitwhen playerIndex == bj_MAX_PLAYERS
        if PlayersAreCoAllied(whichPlayer, Player(playerIndex)) then
            call GroupEnumUnitsOfPlayer(g, Player(playerIndex), null)
            loop
                set fog = FirstOfGroup(g)
                exitwhen fog == null
                call GroupRemoveUnit(g, fog)
                if IsUnitType(fog, UNIT_TYPE_TOWNHALL) and not IsUnitType(fog, UNIT_TYPE_DEAD) and GetUnitTypeId(fog) != 0 then
                    set result = result + 1
                endif
            endloop
        endif
        set playerIndex = playerIndex + 1
    endloop
    
    call DestroyGroup(g)
    set g = null
    return result
endfunction

function CheckForVictors takes force opponentlessPlayers returns force
    local integer    playerIndex
    local integer    opponentIndex
    local boolean    gameOver = false
    
    // Check to see if any players have opponents remaining.
    set playerIndex = 0
    loop
        if (not bj_meleeDefeated[playerIndex]) then
            // Determine whether or not this player has any remaining opponents.
            set opponentIndex = 0
            loop
                // If anyone has an opponent, noone can be victorious yet.
                if MeleePlayerIsOpponent(playerIndex, opponentIndex) then
                    call DestroyForce(opponentlessPlayers)
                    set opponentlessPlayers = null
                    return null
                endif

                set opponentIndex = opponentIndex + 1
                exitwhen opponentIndex == bj_MAX_PLAYERS
            endloop
            
            // Keep track of each opponentless player so that we can give
            // them a victory later.
            call ForceAddPlayer(opponentlessPlayers, Player(playerIndex))
            set gameOver = true
        endif
        
        set playerIndex = playerIndex + 1
        exitwhen playerIndex == bj_MAX_PLAYERS
    endloop

    // Set the game over global flag
    set bj_meleeGameOver = gameOver

    return opponentlessPlayers
endfunction

// Find opponentless players
function CheckForLosersAndVictors takes nothing returns nothing
    local integer    playerIndex
    local player     indexPlayer
    local force      defeatedPlayers = CreateForce()
    local force      victoriousPlayers = null
    local boolean    gameOver = false

    // If the game is already over, do nothing
    if (bj_meleeGameOver) then
        return
    endif

    // If the game was disconnected then it is over, in this case we
    // don't want to report results for anyone as they will most likely
    // conflict with the actual game results
    if (GetIntegerGameState(GAME_STATE_DISCONNECTED) != 0) then
        set bj_meleeGameOver = true
        return
    endif

    // Check each player to see if he or she has been defeated yet.
    set playerIndex = 0
    loop
        set indexPlayer = Player(playerIndex)

        if (not bj_meleeDefeated[playerIndex] and not bj_meleeVictoried[playerIndex]) then
            //call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "Player"+I2S(playerIndex)+" has "+I2S(MeleeGetAllyStructureCount(indexPlayer))+" ally buildings.")
            if (MeleeGetAllyStructureCount(indexPlayer) <= 0) then

                // Keep track of each defeated player so that we can give
                // them a defeat later.
                call ForceAddPlayer(defeatedPlayers, Player(playerIndex))

                // Set their defeated flag now so MeleeCheckForVictors
                // can detect victors.
                set bj_meleeDefeated[playerIndex] = true
            endif
        endif
            
        set playerIndex = playerIndex + 1
        exitwhen playerIndex == bj_MAX_PLAYERS
    endloop

    // Now that the defeated flags are set, check if there are any victors
    set victoriousPlayers = CheckForVictors(CreateForce())

    // Defeat all defeated players
    call ForForce(defeatedPlayers, function MeleeDoDefeatEnum)

    // Give victory to all victorious players
    call ForForce(victoriousPlayers, function MeleeDoVictoryEnum)

    // If the game is over we should remove all observers
    if (bj_meleeGameOver) then
        call MeleeRemoveObservers()
    endif
    
    // Destroy and null handles
    call DestroyForce(defeatedPlayers)
    if victoriousPlayers != null then
        call DestroyForce(victoriousPlayers)
        set victoriousPlayers = null
    endif
    set defeatedPlayers = null
    set indexPlayer = null
endfunction

// CRIPPLE
function CheckForCrippledPlayers takes nothing returns nothing
    local integer    playerIndex
    local player     indexPlayer
    local boolean    isNowCrippled

    // The "finish soon" exposure of all players overrides any "crippled" exposure
    if bj_finishSoonAllExposed then
        return
    endif

    // Check each player to see if he or she has been crippled or uncrippled.
    set playerIndex = 0
    loop
        set indexPlayer = Player(playerIndex)
        set isNowCrippled = (MeleeGetAllyStructureCount(indexPlayer) > 0) and (GetAllyKeyStructureCount(indexPlayer) <= 0)

        if (not bj_playerIsCrippled[playerIndex] and isNowCrippled) then

            // Player became crippled; start their cripple timer.
            set bj_playerIsCrippled[playerIndex] = true
            call TimerStart(bj_crippledTimer[playerIndex], bj_MELEE_CRIPPLE_TIMEOUT, false, function MeleeCrippledPlayerTimeout)

            if (GetLocalPlayer() == indexPlayer) then
                // Use only local code (no net traffic) within this block to avoid desyncs.

                // Show the timer window.
                call TimerDialogDisplay(bj_crippledTimerWindows[playerIndex], true)

                // Display a warning message.
                call DisplayTimedTextToPlayer(indexPlayer, 0, 0, bj_MELEE_CRIPPLE_MSG_DURATION, MeleeGetCrippledWarningMessage(indexPlayer))
            endif

        elseif (bj_playerIsCrippled[playerIndex] and not isNowCrippled) then

            // Player became uncrippled; stop their cripple timer.
            set bj_playerIsCrippled[playerIndex] = false
            call PauseTimer(bj_crippledTimer[playerIndex])

            if (GetLocalPlayer() == indexPlayer) then
                // Use only local code (no net traffic) within this block to avoid desyncs.

                // Hide the timer window for this player.
                call TimerDialogDisplay(bj_crippledTimerWindows[playerIndex], false)

                // Display a confirmation message if the player's team is still alive.
                if (MeleeGetAllyStructureCount(indexPlayer) > 0) then
                    if (bj_playerIsExposed[playerIndex]) then
                        call DisplayTimedTextToPlayer(indexPlayer, 0, 0, bj_MELEE_CRIPPLE_MSG_DURATION, GetLocalizedString("CRIPPLE_UNREVEALED"))
                    else
                        call DisplayTimedTextToPlayer(indexPlayer, 0, 0, bj_MELEE_CRIPPLE_MSG_DURATION, GetLocalizedString("CRIPPLE_UNCRIPPLED"))
                    endif
                endif
            endif

            // If the player granted shared vision, deny that vision now.
            call MeleeExposePlayer(indexPlayer, false)

        endif
            
        set playerIndex = playerIndex + 1
        exitwhen playerIndex == bj_MAX_PLAYERS
    endloop
    
    set indexPlayer = null
endfunction

// UNIT DIES
function TriggerActionCheckLostUnit takes nothing returns nothing
    if IsUnitType(GetTriggerUnit(), UNIT_TYPE_STRUCTURE) then
        // We only need to check for mortality if this was the last building.
        if (GetPlayerStructureCount(GetOwningPlayer(GetTriggerUnit()), true) <= 0) then
            call CheckForLosersAndVictors()
        endif

        // Check if the lost unit has crippled or uncrippled the player.
        // (A team with 0 units is dead, and thus considered uncrippled.)
        call CheckForCrippledPlayers()
    endif
endfunction

function TriggerActionAllianceChange takes nothing returns nothing
    call CheckForLosersAndVictors()
    call CheckForCrippledPlayers()
endfunction

function TriggerActionCheckAddedUnit takes nothing returns nothing
    // If the player was crippled, this unit may have uncrippled him/her.
    if (bj_playerIsCrippled[GetPlayerId(GetOwningPlayer(GetTriggerUnit()))]) then
        call CheckForCrippledPlayers()
    endif
endfunction

function TriggerActionPlayerDefeated takes nothing returns nothing
    local player thePlayer = GetTriggerPlayer()
    call CachePlayerHeroData(thePlayer)

    if (MeleeGetAllyCount(thePlayer) > 0) then
        // If at least one ally is still alive and kicking, share units with
        // them and proceed with death.
        call ShareEverythingWithTeam(thePlayer)
        if (not bj_meleeDefeated[GetPlayerId(thePlayer)]) then
            call MeleeDoDefeat(thePlayer)
        endif
    else
        // If no living allies remain, swap all units and buildings over to
        // neutral_passive and proceed with death.
        call MakeUnitsPassiveForTeam(thePlayer)
        if (not bj_meleeDefeated[GetPlayerId(thePlayer)]) then
            call MeleeDoDefeat(thePlayer)
        endif
    endif
    call CheckForLosersAndVictors()
    set thePlayer = null
endfunction

function TriggerActionPlayerLeft takes nothing returns nothing
    local player thePlayer = GetTriggerPlayer()

    // Just show game over for observers when they leave
    if (IsPlayerObserver(thePlayer)) then
        call RemovePlayerPreserveUnitsBJ(thePlayer, PLAYER_GAME_RESULT_NEUTRAL, false)
        set thePlayer = null
        return
    endif

    call CachePlayerHeroData(thePlayer)

    // This is the same as defeat except the player generates the message 
    // "player left the game" as opposed to "player was defeated".

    if (MeleeGetAllyCount(thePlayer) > 0) then
        // If at least one ally is still alive and kicking, share units with
        // them and proceed with death.
        call ShareEverythingWithTeam(thePlayer)
        call MeleeDoLeave(thePlayer)
    else
        // If no living allies remain, swap all units and buildings over to
        // neutral_passive and proceed with death.
        call MakeUnitsPassiveForTeam(thePlayer)
        call MeleeDoLeave(thePlayer)
    endif
    call CheckForLosersAndVictors()
    set thePlayer = null
endfunction

function MeleeVictoryDefeat takes nothing returns nothing
    local trigger    trig
    local integer    index
    local player     indexPlayer

    // Create a timer window for the "finish soon" timeout period, it has no timer
    // because it is driven by real time (outside of the game state to avoid desyncs)
    set bj_finishSoonTimerDialog = CreateTimerDialog(null)

    // Set a trigger to fire when we receive a "finish soon" game event
    set trig = CreateTrigger()
    call TriggerRegisterGameEvent(trig, EVENT_GAME_TOURNAMENT_FINISH_SOON)
    call TriggerAddAction(trig, function MeleeTriggerTournamentFinishSoon)

    // Set a trigger to fire when we receive a "finish now" game event
    set trig = CreateTrigger()
    call TriggerRegisterGameEvent(trig, EVENT_GAME_TOURNAMENT_FINISH_NOW)
    call TriggerAddAction(trig, function MeleeTriggerTournamentFinishNow)

    // Set up each player's mortality code.
    set index = 0
    loop
        set indexPlayer = Player(index)

        // Make sure this player slot is playing.
        if (GetPlayerSlotState(indexPlayer) == PLAYER_SLOT_STATE_PLAYING) then
            set bj_meleeDefeated[index] = false
            set bj_meleeVictoried[index] = false

            // Create a timer and timer window in case the player is crippled.
            set bj_playerIsCrippled[index] = false
            set bj_playerIsExposed[index] = false
            set bj_crippledTimer[index] = CreateTimer()
            set bj_crippledTimerWindows[index] = CreateTimerDialog(bj_crippledTimer[index])
            call TimerDialogSetTitle(bj_crippledTimerWindows[index], MeleeGetCrippledTimerMessage(indexPlayer))

            // Set a trigger to fire whenever a building is cancelled for this player.
            set trig = CreateTrigger()
            call TriggerRegisterPlayerUnitEvent(trig, indexPlayer, EVENT_PLAYER_UNIT_CONSTRUCT_CANCEL, null)
            call TriggerAddAction(trig, function TriggerActionCheckLostUnit)

            // Set a trigger to fire whenever a unit dies for this player.
            call TriggerRegisterPlayerUnitEvent(trig, indexPlayer, EVENT_PLAYER_UNIT_DEATH, null)
            call TriggerAddAction(trig, function TriggerActionCheckLostUnit)

            // Set a trigger to fire whenever a unit begins construction for this player
            set trig = CreateTrigger()
            call TriggerRegisterPlayerUnitEvent(trig, indexPlayer, EVENT_PLAYER_UNIT_CONSTRUCT_START, null)
            call TriggerAddAction(trig, function TriggerActionCheckAddedUnit)

            // Set a trigger to fire whenever this player defeats-out
            set trig = CreateTrigger()
            call TriggerRegisterPlayerEvent(trig, indexPlayer, EVENT_PLAYER_DEFEAT)
            call TriggerAddAction(trig, function TriggerActionPlayerDefeated)

            // Set a trigger to fire whenever this player leaves
            set trig = CreateTrigger()
            call TriggerRegisterPlayerEvent(trig, indexPlayer, EVENT_PLAYER_LEAVE)
            call TriggerAddAction(trig, function TriggerActionPlayerLeft)

            // Set a trigger to fire whenever this player changes his/her alliances.
            set trig = CreateTrigger()
            call TriggerRegisterPlayerAllianceChange(trig, indexPlayer, ALLIANCE_PASSIVE)
            call TriggerRegisterPlayerStateEvent(trig, indexPlayer, PLAYER_STATE_ALLIED_VICTORY, EQUAL, 1)
            call TriggerAddAction(trig, function TriggerActionAllianceChange)
        else
            set bj_meleeDefeated[index] = true
            set bj_meleeVictoried[index] = false

            // Handle leave events for observers
            if (IsPlayerObserver(indexPlayer)) then
                // Set a trigger to fire whenever this player leaves
                set trig = CreateTrigger()
                call TriggerRegisterPlayerEvent(trig, indexPlayer, EVENT_PLAYER_LEAVE)
                call TriggerAddAction(trig, function TriggerActionPlayerLeft)
            endif
        endif

        set index = index + 1
        exitwhen index == bj_MAX_PLAYERS
    endloop

    // Test for victory / defeat at startup, in case the user has already won / lost.
    // Allow for a short time to pass first, so that the map can finish loading.
    call TimerStart(CreateTimer(), 2.0, false, function TriggerActionAllianceChange)
endfunction

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

native GetUnitGoldCost takes integer unitid returns integer
native GetUnitWoodCost takes integer unitid returns integer

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//  EOT System header file
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

function ConvertAttackTypeReverse takes attacktype at returns integer
    if at == ATTACK_TYPE_NORMAL then
        return 0
    elseif at == ATTACK_TYPE_MELEE then
        return 1
    elseif at == ATTACK_TYPE_PIERCE then
        return 2
    elseif at == ATTACK_TYPE_SIEGE then
        return 3
    elseif at == ATTACK_TYPE_MAGIC then
        return 4
    elseif at == ATTACK_TYPE_CHAOS then
        return 5
    elseif at == ATTACK_TYPE_HERO then
        return 6
    endif
    return 0
endfunction

function ConvertDamageTypeReverse takes damagetype dt returns integer
    if dt == DAMAGE_TYPE_UNKNOWN then
        return 0
    elseif dt == DAMAGE_TYPE_NORMAL then
        return 4
    elseif dt == DAMAGE_TYPE_ENHANCED then
        return 5
    elseif dt == DAMAGE_TYPE_FIRE then
        return 8
    elseif dt == DAMAGE_TYPE_COLD then
        return 9
    elseif dt == DAMAGE_TYPE_LIGHTNING then
        return 10
    elseif dt == DAMAGE_TYPE_POISON then
        return 11
    elseif dt == DAMAGE_TYPE_DISEASE then
        return 12
    elseif dt == DAMAGE_TYPE_DIVINE then
        return 13
    elseif dt == DAMAGE_TYPE_MAGIC then
        return 14
    elseif dt == DAMAGE_TYPE_SONIC then
        return 15
    elseif dt == DAMAGE_TYPE_ACID then
        return 16
    elseif dt == DAMAGE_TYPE_FORCE then
        return 17
    elseif dt == DAMAGE_TYPE_DEATH then
        return 18
    elseif dt == DAMAGE_TYPE_MIND then
        return 19
    elseif dt == DAMAGE_TYPE_PLANT then
        return 20
    elseif dt == DAMAGE_TYPE_DEFENSIVE then
        return 21
    elseif dt == DAMAGE_TYPE_DEMOLITION then
        return 22
    elseif dt == DAMAGE_TYPE_SLOW_POISON then
        return 23
    elseif dt == DAMAGE_TYPE_SPIRIT_LINK then
        return 24
    elseif dt == DAMAGE_TYPE_SHADOW_STRIKE then
        return 25
    elseif dt == DAMAGE_TYPE_UNIVERSAL then
        return 26
    endif
    return 0
endfunction

//Reset all variables to null.
function EOT_Set_Default_Variables takes nothing returns nothing
    set udg_EOT_Param_Source = null
    set udg_EOT_Param_Target = null
    set udg_EOT_Param_Duration = 0.
    set udg_EOT_Param_Remaining_Duration = -1.
    set udg_EOT_Param_Interval = 0.
    set udg_EOT_Param_Remaining_Interval = -1.
    set udg_EOT_Param_Hidden = false
    set udg_EOT_Param_Buff = 0
    set udg_EOT_Param_Buff_Holder = 0
    set udg_EOT_Param_Buff_Holder_Level = 1
    set udg_EOT_Param_Ability = 0
    set udg_EOT_Param_Ability_Level = 1
    set udg_EOT_Param_Type = 0
    set udg_EOT_Param_Subtype = 0
    set udg_EOT_Param_Subtype2 = 0
    set udg_EOT_Param_Positive = false
    set udg_EOT_Param_Can_Dispell = true
    set udg_EOT_Param_Is_Passive = false
    //set udg_EOT_Param_Is_Paused = false
    set udg_EOT_Param_Special_Effect = null
    set udg_EOT_Param_Special_Effect_Model = ""
    set udg_EOT_Param_Special_Effect_Point = ""
    
    set udg_EOT_Event_Null_Variables = 1
    set udg_EOT_Event_Null_Variables = 0
endfunction

//Save an EOT in the cache.
function EOT_Save_To_Cache takes integer cacheId returns nothing
    call SaveUnitHandle(    udg_EOT_Hashtable, cacheId + 100, 1000, udg_EOT_Param_Source)
    call SaveUnitHandle(    udg_EOT_Hashtable, cacheId + 100, 1001, udg_EOT_Param_Target)
    call SaveReal(          udg_EOT_Hashtable, cacheId + 100, 1002, udg_EOT_Param_Duration)
    call SaveReal(          udg_EOT_Hashtable, cacheId + 100, 1003, udg_EOT_Param_Remaining_Duration)
    call SaveReal(          udg_EOT_Hashtable, cacheId + 100, 1004, udg_EOT_Param_Interval)
    call SaveReal(          udg_EOT_Hashtable, cacheId + 100, 1005, udg_EOT_Param_Remaining_Interval)
    call SaveBoolean(       udg_EOT_Hashtable, cacheId + 100, 1006, udg_EOT_Param_Hidden)
    call SaveInteger(       udg_EOT_Hashtable, cacheId + 100, 1007, udg_EOT_Param_Buff)
    call SaveInteger(       udg_EOT_Hashtable, cacheId + 100, 1008, udg_EOT_Param_Buff_Holder)
    call SaveInteger(       udg_EOT_Hashtable, cacheId + 100, 1009, udg_EOT_Param_Buff_Holder_Level)
    call SaveInteger(       udg_EOT_Hashtable, cacheId + 100, 1010, udg_EOT_Param_Ability)
    call SaveInteger(       udg_EOT_Hashtable, cacheId + 100, 1011, udg_EOT_Param_Ability_Level)
    call SaveInteger(       udg_EOT_Hashtable, cacheId + 100, 1012, udg_EOT_Param_Type)
    call SaveInteger(       udg_EOT_Hashtable, cacheId + 100, 1013, udg_EOT_Param_Subtype)
    call SaveInteger(       udg_EOT_Hashtable, cacheId + 100, 1014, udg_EOT_Param_Subtype2)
    call SaveBoolean(       udg_EOT_Hashtable, cacheId + 100, 1015, udg_EOT_Param_Positive)
    call SaveBoolean(       udg_EOT_Hashtable, cacheId + 100, 1016, udg_EOT_Param_Can_Dispell)
    call SaveBoolean(       udg_EOT_Hashtable, cacheId + 100, 1017, udg_EOT_Param_Is_Passive)
    //call SaveBoolean(       udg_EOT_Hashtable, cacheId + 100, 1018, udg_EOT_Param_Is_Paused)
    call SaveEffectHandle(  udg_EOT_Hashtable, cacheId + 100, 1019, udg_EOT_Param_Special_Effect)
    call SaveStr(           udg_EOT_Hashtable, cacheId + 100, 1020, udg_EOT_Param_Special_Effect_Model)
    call SaveStr(           udg_EOT_Hashtable, cacheId + 100, 1021, udg_EOT_Param_Special_Effect_Point)
endfunction

//Load an EOT from the cache.
function EOT_Load_From_Cache takes integer cacheId returns nothing
    set udg_EOT_Param_Source                = LoadUnitHandle(   udg_EOT_Hashtable, cacheId + 100, 1000)
    set udg_EOT_Param_Target                = LoadUnitHandle(   udg_EOT_Hashtable, cacheId + 100, 1001)
    set udg_EOT_Param_Duration              = LoadReal(         udg_EOT_Hashtable, cacheId + 100, 1002)
    set udg_EOT_Param_Remaining_Duration    = LoadReal(         udg_EOT_Hashtable, cacheId + 100, 1003)
    set udg_EOT_Param_Interval              = LoadReal(         udg_EOT_Hashtable, cacheId + 100, 1004)
    set udg_EOT_Param_Remaining_Interval    = LoadReal(         udg_EOT_Hashtable, cacheId + 100, 1005)
    set udg_EOT_Param_Hidden                = LoadBoolean(      udg_EOT_Hashtable, cacheId + 100, 1006)
    set udg_EOT_Param_Buff                  = LoadInteger(      udg_EOT_Hashtable, cacheId + 100, 1007)
    set udg_EOT_Param_Buff_Holder           = LoadInteger(      udg_EOT_Hashtable, cacheId + 100, 1008)
    set udg_EOT_Param_Buff_Holder_Level     = LoadInteger(      udg_EOT_Hashtable, cacheId + 100, 1009)
    set udg_EOT_Param_Ability               = LoadInteger(      udg_EOT_Hashtable, cacheId + 100, 1010)
    set udg_EOT_Param_Ability_Level         = LoadInteger(      udg_EOT_Hashtable, cacheId + 100, 1011)
    set udg_EOT_Param_Type                  = LoadInteger(      udg_EOT_Hashtable, cacheId + 100, 1012)
    set udg_EOT_Param_Subtype               = LoadInteger(      udg_EOT_Hashtable, cacheId + 100, 1013)
    set udg_EOT_Param_Subtype               = LoadInteger(      udg_EOT_Hashtable, cacheId + 100, 1014)
    set udg_EOT_Param_Positive              = LoadBoolean(      udg_EOT_Hashtable, cacheId + 100, 1015)
    set udg_EOT_Param_Can_Dispell           = LoadBoolean(      udg_EOT_Hashtable, cacheId + 100, 1016)
    set udg_EOT_Param_Is_Passive            = LoadBoolean(      udg_EOT_Hashtable, cacheId + 100, 1017)
    //set udg_EOT_Param_Is_Paused             = LoadBoolean(      udg_EOT_Hashtable, cacheId + 100, 1018)
    set udg_EOT_Param_Special_Effect        = LoadEffectHandle( udg_EOT_Hashtable, cacheId + 100, 1019)
    set udg_EOT_Param_Special_Effect_Model  = LoadStr(          udg_EOT_Hashtable, cacheId + 100, 1020)
    set udg_EOT_Param_Special_Effect_Point  = LoadStr(          udg_EOT_Hashtable, cacheId + 100, 1021)
endfunction

//Save and Load additional data to an EOT.
//Raw values:
function EOT_Save_Integer takes integer id, integer value returns nothing
    call SaveInteger(udg_EOT_Hashtable, udg_EOT_Param_Id, id + 1000, value)
endfunction
function EOT_Save_Real takes integer id, real value returns nothing
    call SaveReal(udg_EOT_Hashtable, udg_EOT_Param_Id, id + 1000, value)
endfunction
function EOT_Save_String takes integer id, string value returns nothing
    call SaveStr(udg_EOT_Hashtable, udg_EOT_Param_Id, id + 1000, value)
endfunction
function EOT_Save_Boolean takes integer id, boolean value returns nothing
    call SaveBoolean(udg_EOT_Hashtable, udg_EOT_Param_Id, id + 1000, value)
endfunction

function EOT_Load_Integer takes integer id returns integer
    return LoadInteger(udg_EOT_Hashtable, udg_EOT_Param_Id, id + 1000)
endfunction
function EOT_Load_Real takes integer id returns real
    return LoadReal(udg_EOT_Hashtable, udg_EOT_Param_Id, id + 1000)
endfunction
function EOT_Load_String takes integer id returns string
    return LoadStr(udg_EOT_Hashtable, udg_EOT_Param_Id, id + 1000)
endfunction
function EOT_Load_Boolean takes integer id returns boolean
    return LoadBoolean(udg_EOT_Hashtable, udg_EOT_Param_Id, id + 1000)
endfunction

//Handles:
function EOT_Save_Unit takes integer id, unit value returns nothing
    call SaveUnitHandle(udg_EOT_Hashtable, udg_EOT_Param_Id, id + 1000, value)
endfunction
function EOT_Save_Player takes integer id, player value returns nothing
    call SavePlayerHandle(udg_EOT_Hashtable, udg_EOT_Param_Id, id + 1000, value)
endfunction
function EOT_Save_Item takes integer id, item value returns nothing
    call SaveItemHandle(udg_EOT_Hashtable, udg_EOT_Param_Id, id + 1000, value)
endfunction
function EOT_Save_Group takes integer id, group value returns nothing
    call SaveGroupHandle(udg_EOT_Hashtable, udg_EOT_Param_Id, id + 1000, value)
endfunction
function EOT_Save_Effect takes integer id, effect value returns nothing
    call SaveEffectHandle(udg_EOT_Hashtable, udg_EOT_Param_Id, id + 1000, value)
endfunction
function EOT_Save_Location takes integer id, location value returns nothing
    call SaveLocationHandle(udg_EOT_Hashtable, udg_EOT_Param_Id, id + 1000, value)
endfunction
function EOT_Save_Lightning takes integer id, lightning value returns nothing
    call SaveLightningHandle(udg_EOT_Hashtable, udg_EOT_Param_Id, id + 1000, value)
endfunction

function EOT_Load_Unit takes integer id returns unit
    return LoadUnitHandle(udg_EOT_Hashtable, udg_EOT_Param_Id, id + 1000)
endfunction
function EOT_Load_Player takes integer id returns player
    return LoadPlayerHandle(udg_EOT_Hashtable, udg_EOT_Param_Id, id + 1000)
endfunction
function EOT_Load_Item takes integer id returns item
    return LoadItemHandle(udg_EOT_Hashtable, udg_EOT_Param_Id, id + 1000)
endfunction
function EOT_Load_Group takes integer id returns group
    return LoadGroupHandle(udg_EOT_Hashtable, udg_EOT_Param_Id, id + 1000)
endfunction
function EOT_Load_Effect takes integer id returns effect
    return LoadEffectHandle(udg_EOT_Hashtable, udg_EOT_Param_Id, id + 1000)
endfunction
function EOT_Load_Location takes integer id returns location
    return LoadLocationHandle(udg_EOT_Hashtable, udg_EOT_Param_Id, id + 1000)
endfunction
function EOT_Load_Lightning takes integer id returns lightning
    return LoadLightningHandle(udg_EOT_Hashtable, udg_EOT_Param_Id, id + 1000)
endfunction
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//  EOT System header file end
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Name Type is_array initial_value
CenterPoint location No
DamageEventAmount real No
DamageEventSource unit No
DOT_Attack_Type attacktype No
DOT_Damage real No
DOT_Damage_Type damagetype No
EOT_Amount integer No
EOT_Array_Ability abilcode Yes
EOT_Array_Ability_Level integer Yes
EOT_Array_Buff buffcode Yes
EOT_Array_Buff_Holder abilcode Yes
EOT_Array_Buff_Holder_Level integer Yes
EOT_Array_Can_Dispell boolean Yes
EOT_Array_Duration real Yes
EOT_Array_Hidden boolean Yes
EOT_Array_Id integer Yes
EOT_Array_Interval real Yes
EOT_Array_Is_Passive boolean Yes
EOT_Array_On_Period_Trigger trigger Yes
EOT_Array_Positive boolean Yes
EOT_Array_Remaining_Duration real Yes
EOT_Array_Remaining_Interval real Yes
EOT_Array_Source unit Yes
EOT_Array_Special_Effect effect Yes
EOT_Array_Special_Effect_Model string Yes
EOT_Array_Special_Effect_Point string Yes
EOT_Array_Subtype integer Yes
EOT_Array_Subtype2 integer Yes
EOT_Array_Target unit Yes
EOT_Array_Type integer Yes
EOT_Event_An_EOT_Has_Expired real No
EOT_Event_An_EOT_Is_Created real No
EOT_Event_An_EOT_Is_Destroyed real No
EOT_Event_An_EOT_Is_Dispelled real No
EOT_Event_Creation_After real No
EOT_Event_Creation_Before real No
EOT_Event_Destruction_After real No
EOT_Event_Destruction_Before real No
EOT_Event_Dispell_After real No
EOT_Event_Dispell_Before real No
EOT_Event_Expire_After real No
EOT_Event_Expire_Before real No
EOT_Event_Get_Data real No
EOT_Event_Interval_After real No
EOT_Event_Interval_Before real No
EOT_Event_Null_Variables real No
EOT_Event_On_Interval real No
EOT_Event_Save_Data real No
EOT_Hashtable hashtable No
EOT_Index integer No
EOT_Param_Ability abilcode No
EOT_Param_Ability_Level integer No
EOT_Param_Buff buffcode No
EOT_Param_Buff_Holder abilcode No
EOT_Param_Buff_Holder_Level integer No
EOT_Param_Can_Dispell boolean No
EOT_Param_Destroy boolean No
EOT_Param_Destroy_Passive boolean No
EOT_Param_Duration real No
EOT_Param_Expire boolean No
EOT_Param_Force_Destroy boolean No
EOT_Param_Hidden boolean No
EOT_Param_Id integer No
EOT_Param_Interval real No
EOT_Param_Is_Passive boolean No
EOT_Param_Negative boolean No
EOT_Param_Positive boolean No
EOT_Param_Remaining_Duration real No
EOT_Param_Remaining_Interval real No
EOT_Param_Source unit No
EOT_Param_Special_Effect effect No
EOT_Param_Special_Effect_Model string No
EOT_Param_Special_Effect_Point string No
EOT_Param_Subtype integer No
EOT_Param_Subtype2 integer No
EOT_Param_Target unit No
EOT_Param_Type integer No
EOT_Timer timer No
EOT_Trigger_Create_EOT trigger No
EOT_Trigger_Destroy_EOT trigger No
EOT_Trigger_Get_Data trigger No
EOT_Trigger_Remove_EOTs trigger No
EOT_Trigger_Save_Data trigger No
EOT_Unique_Id integer No
IsDamageSpell boolean No
IsUnitBeingKnockedBack boolean Yes
JD_Angle real Yes
JD_Animations string Yes
JD_Distances real Yes
JD_Effect string Yes
JD_Group group No
JD_HighSettings real Yes
JD_Integers integer Yes
JD_JumpEndEvent real No
JD_JumpHigh real Yes
JD_ReachedDistance real Yes
JD_RealTimer real Yes
JD_SpeedUnits real Yes
JD_TempPoint location Yes
JD_TreesDestroy boolean Yes
JD_Unit unit Yes
JDA_Animation string No
JDA_AnimationSpeed real No
JDA_Collusion boolean No
JDA_DestroyTrees_Dash boolean No
JDA_JumpHigh_Distance real No
JDA_SpecialEffect string No
JDA_Speed real No
JDA_TargetPoint location No
JDA_Unit unit No
K2DAmphibious boolean Yes
K2DAngle real Yes
K2DBounce boolean Yes
K2DCollision real Yes
K2DCos real Yes
K2DCosD1 real Yes
K2DCosD2 real Yes
K2DCosH real Yes
K2DDebrisKiller unit No
K2DDestRadius real Yes
K2DDistanceLeft real Yes
K2DFlying boolean Yes
K2DFreeze boolean Yes
K2DFriction real Yes
K2DFXModel string Yes
K2DFXRate real Yes
K2DFXTimeLeft real Yes
K2DHeight real Yes
K2DHeightThreshold real Yes
K2DImpact trigger Yes
K2DItem item No
K2DItemOffset boolean No
K2DItemsFound boolean No
K2DKillTrees boolean Yes
K2DLastX real Yes
K2DLastY real Yes
K2DMaxDestRadius real No
K2DMaxX real No
K2DMaxY real No
K2DMinX real No
K2DMinY real No
K2DNext integer Yes
K2DOverride boolean Yes
K2DPause boolean Yes
K2DPrev integer Yes
K2DRadius integer Yes
K2DRegion rect No
K2DSimple boolean Yes
K2DSin real Yes
K2DSinD1 real Yes
K2DSinD2 real Yes
K2DSinH real Yes
K2DSource unit Yes
K2DTimeLeft real Yes
K2DTimeout real No
K2DTimer timer No
K2DUnbiasedCollision boolean Yes
K2DVelocity real Yes
K2DX real No
K2DY real No
Knockback2DAmphibious boolean No
Knockback2DAngle real No
Knockback2DBounces boolean No
Knockback2DCollision real No
Knockback2DDefaultBounce boolean No
Knockback2DDefaultDestRadius real No
Knockback2DDefaultFriction real No
Knockback2DDefaultFX string No
Knockback2DDefaultFXRate real No
Knockback2DDefaultGravity real No
Knockback2DDefaultKillTrees boolean No
Knockback2DDefaultPause boolean No
Knockback2DDestRadius real No
Knockback2DDistance real No
Knockback2DFriction real No
Knockback2DFXRate real No
Knockback2DGravity real No
Knockback2DHeight real No
Knockback2DKillTrees boolean No
Knockback2DLoopFX string No
Knockback2DOnImpact trigger No
Knockback2DOverride boolean No
Knockback2DPause boolean No
Knockback2DRobustPathing integer No
Knockback2DSimple boolean No
Knockback2DSource unit No
Knockback2DTime real No
Knockback2DTreeOrDebris string No
Knockback2DUnbiasedCollision boolean No
Knockback2DUnit unit No
LeaklessGroup group No
PDD_allocatedAttacks integer No
PDD_allocCounter integer No
PDD_amount real No
PDD_ATTACK_TYPE_UNIVERSAL attacktype No
PDD_BRACERS_SPELL_DMG_RED real No
PDD_CODE integer No
PDD_DAMAGE_TYPE_DETECTOR integer No
PDD_damageEvent trigger No
PDD_damageEventTrigger real No
PDD_damageHandler trigger No
PDD_damageType integer No
PDD_ETHEREAL_DAMAGE_FACTOR real No
PDD_h hashtable No
PDD_PHYSICAL integer No
PDD_pureAmount real No
PDD_runAllocatedAttacks trigger No
PDD_SET_MAX_LIFE integer No
PDD_source unit No
PDD_SPELL integer No
PDD_SPELL_DMG_REDUCTION_ITEM integer No
PDD_SPELL_RESIST_AUTO_DETECT boolean No
PDD_target unit No
PDD_totalAllocs integer No
PDD_TRIGGER_CLEANUP_PERIOD real No
PDD_UNIT_MIN_LIFE real No
Radians_QuarterPi real No
Radians_QuarterTurn real No
Radians_Turn real No
TargetPoint location No
Tauren_Shockwave boolean Yes
Tauren_WarStomp boolean Yes
TempAbility abilcode No
TempBackstabAngle real Yes
TempBackstabPoint location Yes
TempBlackMarketItemPool group No
TempCaster unit No
TempCasterUnit unit No
TempDummyUnit unit No
TempInt integer No
TempInt2 integer No
TempInteger integer No
TempLoc location No
TempLocation location No
TempMercRecruitPubPool group No
TempMercRecruitRuinsPool group No
TempOwner player No
TempPickedUnit unit No
TempPlayerUnit unit Yes
TempPoint location No
TempSoldUnitCostGold real No
TempSoldUnitCostLumber real No
TempUnit unit No
TempUnitGroup group No
TempUnitKilled unit No
TempUnitKiller unit No
TempUnitSold unit No
TempUnitType unitcode No
TimerTimeElapsed timer No
TimerTimeElapsedSeconds real No
TimerTimeElapsedWindow timerdialog No
UDex integer No
UDexGen integer No
UDexNext integer Yes
UDexPrev integer Yes
UDexRecycle integer No
UDexUnits unit Yes
UDexWasted integer No
UnitIndexerEnabled boolean No
UnitIndexEvent real No
Default melee game initialization for all players
Melee Initialization
Events
Map initialization
Conditions
Actions
Player - Set the current research level of R009 (Unexpected type: 'techcode') to 1 for Neutral Hostile
Player - Set the current research level of R00A (Unexpected type: 'techcode') to 1 for Neutral Hostile
Melee Game - Use melee time of day (for all players)
Melee Game - Limit Heroes to 1 per Hero-type (for all players)
Melee Game - Give trained Heroes a Scroll of Town Portal (for all players)
Melee Game - Set starting resources (for all players)
Melee Game - Remove creeps and critters from used start locations (for all players)
Melee Game - Create starting units (for all players)
Melee Game - Run melee AI scripts (for computer players)
Melee Game - Enforce victory/defeat conditions (for all players)
Custom script: call MeleeVictoryDefeat()
Player Group - Pick every player in (All players) and do (Actions)
Loop - Actions
Player - Limit training of Enforcer (Paladin) to 1 for (Picked player)
Player - Limit training of Assassin (Ranger) to 1 for (Picked player)
Player - Limit training of Dark Wizard (Archmage) to 1 for (Picked player)
Player - Limit training of Bandit Lord (Dark Knight) to 1 for (Picked player)
Player - Disable Hide Veteran Mercenaries Bonus (Spell Book) for (Picked player)
Player - Disable Hide Veteran Mercenaries Mana Bonus (Spell Book) for (Picked player)
Player - Disable Hide Temp Shield Smash Buff (Spell Book) for (Picked player)
Player - Disable Hide Temp Enforcer's Bonus Ultimate (Spell Book) for (Picked player)
Player - Disable Hide Temp Backstab Buff (Spell Book) for (Picked player)
Player - Disable Hide Temp Ray of Enfeeblement Debuff (Spell Book) for (Picked player)
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Race of (Picked player)) Equal to Human
((Picked player) handicap) Equal to 90.00
Then - Actions
Player - Set (Picked player) handicap to 100 %
Custom script: set bj_wantDestroyGroup = true
Unit Group - Pick every unit in (Units owned by (Picked player) matching (((Matching unit) is A peon-type unit) Equal to True).) and do (Replace (Picked unit) with a Laborer (Peasant) using The new unit's max life and mana)
Custom script: set bj_wantDestroyGroup = true
Unit Group - Pick every unit in (Units owned by (Picked player) matching (((Matching unit) is A town-hall-type unit) Equal to True).) and do (Replace (Picked unit) with a Bandit Encampment (Town Hall) using The new unit's max life and mana)
Custom script: set bj_wantDestroyGroup = true
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
((Picked player) controller) Equal to Computer
Then - Actions
AI - Start melee AI script for (Picked player) : FleckBanditCrucibleBanditsAI.ai (Unexpected type: 'aiscript')
Else - Actions
Else - Actions
Player - Set name of Neutral Hostile to Neutral Hostile
Set Variable Set TempUnitGroup = (Units of type Seedy Pub (Barracks))
Unit Group - Pick every unit in TempUnitGroup and do (Actions)
Loop - Actions
Unit - Add Seedy Pub (Critical Strike) to (Picked unit)
Custom script: call DestroyGroup(udg_TempUnitGroup)
Set Variable Set TempUnitGroup = (Units of type Tower Ruins (Arcane Sanctum))
Unit Group - Pick every unit in TempUnitGroup and do (Actions)
Loop - Actions
Unit - Add Tower Ruins (Critical Strike) to (Picked unit)
Custom script: call DestroyGroup(udg_TempUnitGroup)
Set Variable Set TempUnitGroup = (Units of type Dragon Breeding Pit (Gryphon Aviary))
Unit Group - Pick every unit in TempUnitGroup and do (Actions)
Loop - Actions
Unit - Add Dragon Breeding Pit (Critical Strike) to (Picked unit)
Custom script: call DestroyGroup(udg_TempUnitGroup)
Melee Game - Run melee AI scripts (for computer players)
Quest - Create a Required quest titled Map Information with the description Current Map Version: 1.8cYou are playing v1.8c of The Bandit's Crucible. Visit https://www.hiveworkshop.com/ for the most current version. , using icon path ReplaceableTextures\CommandButtons\BTNSpy.blp
Quest - Create a Required quest titled Version Changelog: 1.0 with the description Initial release. , using icon path ReplaceableTextures\CommandButtons\BTNBookOfSummoning.blp
Quest - Create a Required quest titled Version Changelog: 1.1 with the description Dragon Breeding Pit building and ability tooltip is now consistent.Added a questlog explaining the Bandit mercenary hire pool.Expanded Seedy Pub and Tower Ruins mercenary building ability tooltips.Increased mercenary hire pool chance from 45% to 50%.Split the icon credits questlog into two. , using icon path ReplaceableTextures\CommandButtons\BTNBookOfSummoning.blp
Quest - Create a Required quest titled Version Changelog: 1.2 with the description Greatly reduces Furious Charge cooldown and mana cost.Furious Charge can now target heroes.Flanking Aura now properly works above level 1.Fixed Flanking Aura triggering. , using icon path ReplaceableTextures\CommandButtons\BTNBookOfSummoning.blp
Quest - Create a Required quest titled Version Changelog: 1.3 with the description Updated mercenary hire pool triggers so that every Seedy Pub and Tower Ruins always start with a random set of mercenaries.Increased mercenary hire pool chance from 50% to 60%.Updated Seedy Pub, Tower Ruins, Black Market tooltips.Bandit weapon and armor upgrades now also apply to Laborers, Chaplains, Rogue Wizards and Renegade Wizards.Added bronze dragon whelps and drakes, added a new researchable ability for Bronze Drakes that increases the movement speed of friendly units.Removed Scroll of Regeneration, Lesser Clarity Potion, Sentry Wards, Spider Broach from Black Market.Added Black Market item pool and questlog.Updated Bandit AI script to stop tower spam. , using icon path ReplaceableTextures\CommandButtons\BTNBookOfSummoning.blp
Quest - Create a Required quest titled Version Changelog: 1.4 with the description Updated PDD, EOT triggering in preparation for merging this race with my other altered melee races.Neutral Hostile now starts with March of Time researched.Updated misc triggering. , using icon path ReplaceableTextures\CommandButtons\BTNBookOfSummoning.blp
Quest - Create a Required quest titled Version Changelog: 1.5 with the description Updated Knockback triggering.Added Roll Gacha ability to Seedy Pubs and Tower Ruins.Added time elasped timer.Added space to quotes and colorcodes in tooltips.Fixed heroglow bug.Bandit Lord hero ai should now cast Meteoric Smash.Fixed Meteoric Smash triggers to work for other players.Increased Corpse Explosion cast range from 500 to 600.Increased Shadow Flame gold cost from 135 to 145.Decreased Shadow Flame lumber cost from 215 to 205.Increased March of Time lumber cost from 100 to 125.Changed Chaplain icon.Ported the custom race to (6) Silverpine Forest. , using icon path ReplaceableTextures\CommandButtons\BTNBookOfSummoning.blp
Quest - Create a Required quest titled Version Changelog: 1.6 with the description Added a 120 second duration to units summoned from Dark Wizard's Dark Portal ultimate ability.Increased Roll Gacha gold cost from 150 to 175.Added Roll Gacha equivalent for Dragon Breeding Pit.Added collision box to Dragon Breeding Pit model.Added models for some items. , using icon path ReplaceableTextures\CommandButtons\BTNBookOfSummoning.blp
Quest - Create a Required quest titled Version Changelog: 1.7 with the description Replaced the icons of Rogue, Enforcer, Assassin, Renegade Wizard, Heretic, Mud Golem, Ogre Mauler, Forest Troll Berserker and Murloc Mutant to better differentiate them.Replaced the default icon of Bandit Lord.Changed the scaling of Ring of Potection item from 0.90 to 0.80Changed the scaling of Bracer of Agility item from 1.00 to 0.80Changed Thunderbrew Ale Priority from 0 to 33.Added lootbox item in Black Market. , using icon path ReplaceableTextures\CommandButtons\BTNBookOfSummoning.blp
Quest - Create a Required quest titled Version Changelog: 1.8 with the description Updated Custom Skills Trigerring.Added Shadow Flame research to neutral hostile.Added unit inventory and Glyph of Ultravision upgrades to Seedy Pub and Tower Ruins mercenaries.Added colorcode to Seedy Pub and Tower Ruins mercenaries ability tooltips.Changed Entrap base ability from Storm Bolt to Chain Lightning.And more patch notes that was unfortunately lost while updating. , using icon path ReplaceableTextures\CommandButtons\BTNBookOfSummoning.blp
Quest - Create a Required quest titled Version Changelog: 1.8c with the description Fixed incorrect requirements for Black Flame and March of Time in Silverpine map, thanks to FeelMyRash for reporting.Added summon duration to Dark Wizard's Dark Portal ability tooltip.Updated Bandit Encampment tooltip.Fixed tavern mercenaries bug for Bandits. , using icon path ReplaceableTextures\CommandButtons\BTNBookOfSummoning.blp
Quest - Create a Required quest titled Bandit AI with the description Set human computer with 90% handicap for bandit ai. , using icon path ReplaceableTextures\CommandButtons\BTNBandit.blp
Quest - Create a Required quest titled Merc Recruitment Pool with the description Upon finishing building a Seedy Pub or Tower Ruins, starts with a random mercenary group immediately ready for hire. The mercenary hire pool refresh randomly from a range between 300-420 seconds with 60% chance for a new mercenary group.Seedy Pub Mercenaries3 Rogues, 2 Enforcers, 3 Assassins4 Forest Trolls, 2 Forest Troll Trappers, 1 Forest Troll Berserker4 Ogre Warriors, 2 Ogre Mauler3 Gnoll Brute, 3 Gnoll AssassinsTower Ruins Mercenaries3 Chaplains, 1 Heretic, 1 Renegade Wizard3 Deceivers, 3 Rogue Wizards3 Forest Troll Shadow Priests, 2 Ogre Magis3 Kobold Geomancers, 3 Gnoll Wardens4 Mud Golems, 2 Rock Golems , using icon path ReplaceableTextures\CommandButtons\BTNTavern.blp
Quest - Create a Required quest titled Black Market Item Pool with the description Upon finishing building a Black Market, starts with an additional random set of items. The item pool refresh randomly from a range between 220-300 seconds with 60% chance for a new set of items.Black Market Items2 Scrolls of Regeneration, 2 Spider Silk Broaches2 Healing Salves, 1 Wand of Illusion2 Scrolls of Mana, 1 Sentry Wards2 Vampiric Potions, 1 Lesser Replenishment Potion1Wand of Mana Stealing, 1 Lesser Replenishment Potion , using icon path BTNBanditMarketPlace.blp
Quest - Create a Optional quest titled Bandit Credits with the description |c00FFFC01Models|r|c00FFFC01Laborer|r (Bandit_Repairman) - Zurenol, DeuceGorgon|c00FFFC01Bandit Rider|r (Mounted Bandit) - Wandering Soul|c00FFFC01Enforcer, Assassin|r (Bandit) - IronMaiden|c00FFFC01Dark Wizard|r - warcraftunderground.freeforums.net|c00FFFC01Bandit Lord|r - warcraftunderground.freeforums.net|c00FFFC01Buildings|r|c00FFFC01Bandit Encampment|r (Encampment) - Kitabatake|c00FFFC01Bandit Tent|r (Tent and Derivatives) - Blizzard Entertainment, Ujimasa Hojo|c00FFFC01Mercenary Camp|r (Mercenary Camp and Derivatives) - Blizzard Entertainment, Ujimasa Hojo|c00FFFC01Thieves' Guild|r (Thieves' Guild and Derivatives) - Ujimasa Hojo|c00FFFC01Seedy Pub|r (Tavern) - Mike|c00FFFC01Black Market|r (Marketplace and Derivatives) - Blizzard Entertainment, Ujimasa Hojo|c00FFFC01Hidden Cache|r (Hut (Gnoll) and Derivatives) - Ujimasa Hojo|c00FFFC01Tower Ruins|r (Hut (Furbolg) and Derivatives) - Blizzard Entertainment, Ujimasa Hojo|c00FFFC01Dragon Breeding Pit|r (DragonRoost) - ELDERTITANFALL , using icon path ReplaceableTextures\CommandButtons\BTNBandit.blp
Quest - Create a Optional quest titled Bandit Credits (2) with the description |c00FFFC01Icons|r|c00FFFC01Bandit Encampment Icon|r (BTNTent) - Blizzard Entertainment, genin32|c00FFFC01Bandit Tent Icon|r (Tent and Derivatives) - Blizzard Entertainment, Ujimasa Hojo|c00FFFC01Thieves' Guild Icon|r (Thieves' Guild and Derivatives) - Ujimasa Hojo|c00FFFC01Seedy Pub Icon|r (BTNTavern) - Eagle XI|c00FFFC01Dragon Breeding Pit Icon|r (BTNEgg) - maxor_gan|c00FFFC01Hero Enforcer Icon|r (BTNAngarakWarriorIcon) - Amargaard|c00FFFC01Hero Assassin Icon|r (BTNAngarakWarriorIcon2) - Amargaard|c00FFFC01Hero Dark Wizard Icon|r (BTNBanditWizard) - Marcos DAB|c00FFFC01Bandit Rider Icon|r (Horse) - BLazeKraze|c00FFFC01Chaplain Icon|r (BTNChaplain) - Blizzard Entertainment, Darkfang|c00FFFC01Black Dragon Whelp Icon|r (Dragon Whelps) - Null|c00FFFC01Bronze Dragon Whelp Icon|r (Dragon Whelps) - Null, Hermit|c00FFFC01Stealth Icon|r (Bandit Hide) - BLazeKraze|c00FFFC01Spoils of War Icon|r (BTNTreasureChest) - PeeKay|c00FFFC01Bandit Axe Upgrade Icons|r - viiva|c00FFFC01Bandit Shield Upgrade Icons|r - UnholyDobry|c00FFFC01Reinforced Booze Icon|r (BTNDrinkAle) - Sin'dorei300|c00FFFC01Contract Negotiation Icon|r (BTNEconomics) - NFWar|c00FFFC01Veteran Mercenaries Icon|r (Rank 0-5) - Lockheart|c00FFFC01Seedy Pub Ability Icon|r (BTNSpell_Misc_Drink) - Blizzard |c00FFFC01Tower Ruins Mercenaries Icon|r (BTNBookofBlood) - Elenai|c00FFFC01Shadow Flame Icon|r (Soulfire Bundle) - poaalpina, Goblinounours|c00FFFC01March of Time Icon|r (BTN.TimeUp) - OgeRfaCes|c00FFFC01Roll Gacha Icon|r (BTNdice) - trippledota|c00FFFC01Accelerate Egg Growth Icon|r (BTNDragonEyeUpdate02) - ~Nightmare , using icon path ReplaceableTextures\CommandButtons\BTNBanditSpearThrower.blp
Quest - Create a Optional quest titled Bandit Credits (3) with the description |c00FFFC01Icons|r|c00FFFC01Furious Charge Ability Icon|r (BTNCharge) - KelThuzad|c00FFFC01Meteoric Smash Ability Icon|r (BTNSunFragment) - D.ee|c00FFFC01Black Flag Icon|r (BTNKingdomFlag) - Marcos DAB|c00FFFC01Shield Smash Icon|r (BTNShieldBash) - zbc|c00FFFC01Intimidation Aura Icon|r (BTNBattleRage) - -Berz-|c00FFFC01Cornered Animal Icon|r (Ferocity Upgrade) - Darkfang, Blizzard Entertainment|c00FFFC01Entrap Icon|r (BTNEnsnareSeaCreatures) - Sunreaver|c00FFFC01Flanking Aura Icon|r (BTNTraitor) - Darkfang|c00FFFC01Sabotage Icon|r (BTNINV_Misc_Bomb_05) - Blizzard Entertainment|c00FFFC01Corpse Explosion Icon|r (BTNSpell_Shadow_AbominationExplosion) - Blizzard Entertainment|c00FFFC01Ray of Enfeeblement Icon|r (BTNBeamBlast) - The Panda|c00FFFC01Atrophy Aura Icon|r (BTNDER_Flesh_Decay) - CRAZYRUSSIAN|c00FFFC01Hero Bandit Lord Icon|r (HQ Icons - Classic Bandits) - Mustang|c00FFFC01Rogue Icon|r (HQ Icons - Classic Bandits) - Mustang|c00FFFC01Enforcer Icon|r (HQ Icons - Classic Bandits) - Mustang|c00FFFC01Assassin Icon|r (HQ Icons - Classic Bandits) - Mustang|c00FFFC01Renegade Wizard Icon|r (HQ Icons - Classic Bandits) - Mustang|c00FFFC01Heretic Icon|r (BTNAcolyte) - ~Nightmare|c00FFFC01Mud Golem Icon|r (HQ Classic Golems) - Mustang|c00FFFC01Ogre Mauler Icon|r (BTNOrcOgre01) - Marcos DAB|c00FFFC01Forest Troll Berserker Icon|r (BTNTroll) - Mr.Goblin|c00FFFC01Murloc Mutant Icon|r (Murloc) - Murlocologist , using icon path BTNHQRogue.blp
Quest - Create a Optional quest titled Bandit Credits (4) with the description |c00FFFC01Special Effects|r|c00FFFC01Intimidation Aura|r (Domination Aura) - Direfury|c00FFFC01Intimidation Aura Debuff|r (Disarm) - Mythic|c00FFFC01Black Flag Effect|r (Surrender (effect)) - Kitabatake|c00FFFC012nd Rank, 3rd Rank Buff|r - B1oodwork, ILH|c00FFFC01Shield Bash|r (Charge Effect) - Shardeth|c00FFFC01Cornered Animal Buff|r (Burning Rage) - Mythic|c00FFFC01Atrophy Aura|r (Exhuming Aura) - 00110000|c00FFFC01Ray of Enfeeblement Missile|r (Prism Ray (3-Tiered)) - Cherrymage|c00FFFC01Ray of Enfeeblement Effect|r (Arcane Nova) - dhguardianes|c00FFFC01Ray of Enfeeblement Debuff|r (Disarm) - Mythic|c00FFFC01Lootbox Special Effect|r (Wooden Treasure Boxes - Pack) - stan0033 , using icon path BTNHQBanditLord.blp
Quest - Create a Optional quest titled Item Credits with the description |c00FFFC01Item Models|r|c00FFFC01Amulet of Spell Shield, Belt of Giant Strength +6, Boots of Speed, Circlet of Nobility, Claws of Attack, Cloak of Shadows, Gauntlets of Ogre Strength +3, Khadgar's Gem of Health, Mantle of Intelligence +3, Periapt of Vitality, Slippers of Agility +3, Health Stone, Mana Stone, Potion of Greater Mana, Replenishment Potion, Scroll of Restoration, Crown of Kings +5, Kelen's Dagger of Escape, Mask of Death, Potion of Healing, Potion of Mana, Scroll of Healing, Scroll of Mana, Scroll of Protection, Gem of True Seeing, Greater Replenishment Potion, Lesser Replenishment Potion, Minor Replenishment Potion|r (Icons to Models Pack) - KAIL333XZ|c00FFFC01Ring of Protection|r (RingOfProtection) - republicola|c00FFFC01Gloves of Haste|r (Gloves of Speed) - Matarael|c00FFFC01Boots of Quel'Thalas +6|r (Elven Boots) - Matarael and Mc!|c00FFFC01Tome of Retraining|r (Tome Of Retraining) - Mc !|c00FFFC01Book of the Dead, Tome of Experience. Tome of Greater Experience, Manual of Health|r (Books) - AnimE|c00FFFC01Helm of Valor, Medallion of Courage, Pendant of Energy, Pendant of Mana, Sobi Mask, Staff of Silence, The Lion Horn of Stormwind, Healing Wards, Talisman of the Wild, Wand of Lightning Shield, Wand of Mana Stealing, Staff of Negation, Bracer of Agility|r (Items from Icons) - AnimE|c00FFFC01Ancient Janggo of Endurance, Cloak of Flames, Crystal Ball, Ring of Regeneration, Robe of the Magi +6, Scourge Bone Chimes, Warsong Battle Drums, Dust of Appearance|r (item models) - terrio|c00FFFC01Tome of Knowledge, Tome of Power|r (Item_Pack) - YC|c00FFFC01Ice Shard|r (Ice Shield) - Matarael|c00FFFC01Alleria's Flute of Accuracy|r (Staff) - Matarael|c00FFFC01Ankh of Reincarnation|r (Ankh of Resurrection) - Matarael|c00FFFC01Orb of Frost, Orb of Corruption, Orb of Fire, Orb of Venom|r (Orbs of Frostcraft) - Mythic|c00FFFC01Orb of Darkness, Orb of Lightning|r (Orbs) - IrokeZ|c00FFFC01Scroll of Animate Dead, Scroll of Resurrection, Scroll of the Beast, Scroll of Town Portal, Arcane Scroll, Greater Scroll of Replenishment, Lesser Scroll of Replenishment, Scroll of the Unholy Legion|r (Scrolls) - Ket|c00FFFC01Potion of Omniscience|r (Potions) - Ket|c00FFFC01Shimmerglaze Roast|r (Ham) - RightField|c00FFFC01Thunderbrew Ale|r (Cider) - HerrDave , using icon path ReplaceableTextures\CommandButtons\BTNRingGreen.blp
Quest - Create a Optional quest titled Item Credits (2) with the description |c00FFFC01Item Icons|r|c00FFFC01Tome of Agility Icon|r (BTNTomeGreen) - Grunts_Fadora|c00FFFC01Tome of Strength Icon|r (BTNTomeRed) - Grunts_Fadora|c00FFFC01Tome of Knowledge Icon|r (BTNWeaver) - Novart|c00FFFC01Thunderbrew Ale Icon|r (BTNINV_Misc_Mug) - Blizzard Entertainment|c00FFFC01Lootbox Icon|r (BTNTreasureChest) - PrinceYaser , using icon path ReplaceableTextures\CommandButtons\BTNRingPurple.blp
Quest - Create a Optional quest titled Other Credits with the description |c00FFFC01Hero Glow|r - assasin lord|c00FFFC01How to add Hero Glow without Modeling|r - supertoinkz|c00FFFC01Physical Damage Detection Engine GUI v 1.3.0.0|r - looking_for_help aka eey|c00FFFC01[GUI] Effect Over Time System 2.3.1|r - Wietlol|c00FFFC01GUI Knockback 2.5D v4.2.5.0|r - Bribe|c00FFFC01Jump System [Paladon]|r - Paladon, Lender for adding game event JDA_JumpEndEvent|c00FFFC01vJASS Charge 1.00|r - Majin, Silvenon (Knockback Function), Vexorian (Handle Timers Function), Captain Griffen (Attach Timer Function)|c00FFFC01Warcraft III Viewer|r|c00FFFC01War3 Model Editor|r - Magos|c00FFFC01Button Manager v1.8.2|r - Shadow Daemon|c00FFFC01BloodSoul's vJASS code|r for checking by town-hall classification.|c00FFFC01World Editor Help Zone|r - edo494, Jampion, Kitabatake, doom_sheep|c00FFFC01Single Target Spell for Multiple Units Tutorial|r - Rheiko|c00FFFC01The mysteries of the Spellbook|r - Diablo-dk , using icon path ReplaceableTextures\CommandButtons\BTNVillagerMan.blp
https://www.hiveworkshop.com/threads/upwards-counting-timer.175541/
Timer Time Elapsed Initialization
Events
Time - Elapsed game time is 0.01 seconds
Conditions
Actions
Countdown Timer - Create a timer window for TimerTimeElapsed with title Time Elapsed:
Set Variable Set TimerTimeElapsedWindow = (Last created timer window)
https://www.hiveworkshop.com/threads/upwards-counting-timer.175541/
Timer Time Elapsed Update
Events
Time - Every 1.00 seconds of game time
Conditions
Actions
Set Variable Set TimerTimeElapsedSeconds = (TimerTimeElapsedSeconds + 1)
Countdown Timer - Start TimerTimeElapsed as a One-shot timer that will expire in TimerTimeElapsedSeconds seconds
Countdown Timer - Pause TimerTimeElapsed
Bandit Kill Income
Events
Unit - A unit Dies
Conditions
((Dying unit) is A structure) Equal to False
(Owner of (Dying unit)) Not equal to Neutral Hostile
(Owner of (Dying unit)) Not equal to Neutral Passive
(Current research level of R000 (Unexpected type: 'techcode') for (Owner of (Killing unit))) Equal to 1
Actions
Set Variable Set TempUnitKilled = (Dying unit)
Set Variable Set TempUnitKiller = (Killing unit)
Special Effect - Create a special effect attached to the origin (Unexpected type: 'attachpoint') of TempUnitKilled using UI\Feedback\GoldCredit\GoldCredit.mdl
Special Effect - Destroy (Last created special effect)
Player - Add ((Level of TempUnitKilled) x 5) to (Owner of TempUnitKiller) . Current gold
Player - Add ((Level of TempUnitKilled) x 5) to (Owner of TempUnitKiller) . Current lumber
Floating Text - Create floating text that reads (+ + (String(((Level of TempUnitKilled) x 5)))) at ((Position of (Dying unit)) offset by (-40.00, 0)) with Z offset 0 , using font size 10 , color ( 100 %, 100 %, 0.00 %), and 0 % transparency
Floating Text - Show (Last created floating text) for (All allies of (Owner of TempUnitKiller).)
Floating Text - Hide (Last created floating text) for (All enemies of (Owner of TempUnitKiller).)
Floating Text - Change (Last created floating text) : Disable permanence
Floating Text - Change the lifespan of (Last created floating text) to 5.00 seconds
Floating Text - Change the fading age of (Last created floating text) to 1.00 seconds
Floating Text - Set the velocity of (Last created floating text) to 100.00 towards 90 degrees
-------- --------
Floating Text - Create floating text that reads (+ + (String(((Level of TempUnitKilled) x 5)))) at ((Position of (Dying unit)) offset by (0.00, 0)) with Z offset 0 , using font size 10 , color ( 50.00 %, 100 %, 50.00 %), and 0 % transparency
Floating Text - Show (Last created floating text) for (All allies of (Owner of TempUnitKiller).)
Floating Text - Hide (Last created floating text) for (All enemies of (Owner of TempUnitKiller).)
Floating Text - Change (Last created floating text) : Disable permanence
Floating Text - Change the lifespan of (Last created floating text) to 5.00 seconds
Floating Text - Change the fading age of (Last created floating text) to 1.00 seconds
Floating Text - Set the velocity of (Last created floating text) to 100.00 towards 90 degrees
Bandit Pub Add Ability
Events
Unit - A unit Finishes construction
Conditions
(Unit-type of (Triggering unit)) Equal to Seedy Pub (Barracks)
Actions
Set Variable Set TempUnit = (Constructed structure)
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Current research level of R001 (Unexpected type: 'techcode') for (Owner of TempUnit)) Equal to 1
Then - Actions
Unit - Add Seedy Pub Upgrade (Critical Strike) to TempUnit
Else - Actions
Unit - Add Seedy Pub (Critical Strike) to TempUnit
Unit Group - Add TempUnit to TempMercRecruitPubPool
Unit Group - Pick every unit in TempMercRecruitPubPool and do (Actions)
Loop - Actions
Set Variable Set TempUnit = No unit
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
Or - Any (Conditions) are true
Conditions
(Level of Seedy Pub (Critical Strike) for (Picked unit)) Greater than 0
(Level of Seedy Pub Upgrade (Critical Strike) for (Picked unit)) Greater than 0
((Picked unit) is alive) Equal to True
Then - Actions
Set Variable Set TempInt2 = (Random integer number between 1 and 100)
Neutral Building - Remove Rogue (Rogue) from (Picked unit)
Neutral Building - Remove Enforcer (Enforcer) from (Picked unit)
Neutral Building - Remove Assassin (Assassin) from (Picked unit)
Neutral Building - Remove Forest Troll from (Picked unit)
Neutral Building - Remove Forest Troll Trapper (Forest Troll Trapper) from (Picked unit)
Neutral Building - Remove Forest Troll Berserker (Forest Troll Berserker) from (Picked unit)
Neutral Building - Remove Ogre Warrior from (Picked unit)
Neutral Building - Remove Ogre Mauler (Ogre Mauler) from (Picked unit)
Neutral Building - Remove Gnoll Brute from (Picked unit)
Neutral Building - Remove Gnoll Assassin (Gnoll Assassin) from (Picked unit)
Neutral Building - Remove Murloc Plaguebearer (Murloc Plaguebearer) from (Picked unit)
Neutral Building - Remove Murloc Flesheater (Murloc Flesheater) from (Picked unit)
Neutral Building - Remove Murloc Mutant (Murloc Mutant) from (Picked unit)
-------- Give a 20% chance for bandit mercs. --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
TempInt2 Less than or equal to 20
Then - Actions
Neutral Building - Add Rogue (Rogue) to (Picked unit) with 3 in stock and a max stock of 3
Neutral Building - Add Enforcer (Enforcer) to (Picked unit) with 2 in stock and a max stock of 2
Neutral Building - Add Assassin (Assassin) to (Picked unit) with 3 in stock and a max stock of 3
Else - Actions
-------- Give a 20% chance for troll mercs. --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
TempInt2 Less than or equal to 40
TempInt2 Greater than 20
Then - Actions
Neutral Building - Add Forest Troll to (Picked unit) with 4 in stock and a max stock of 4
Neutral Building - Add Forest Troll Trapper (Forest Troll Trapper) to (Picked unit) with 2 in stock and a max stock of 2
Neutral Building - Add Forest Troll Berserker (Forest Troll Berserker) to (Picked unit) with 1 in stock and a max stock of 1
Else - Actions
-------- Give a 20% chance for ogre mercs. --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
TempInt2 Less than or equal to 60
TempInt2 Greater than 40
Then - Actions
Neutral Building - Add Ogre Warrior to (Picked unit) with 4 in stock and a max stock of 4
Neutral Building - Add Ogre Mauler (Ogre Mauler) to (Picked unit) with 2 in stock and a max stock of 2
Else - Actions
-------- Give a 20% chance for gnoll mercs. --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
TempInt2 Less than or equal to 80
TempInt2 Greater than 60
Then - Actions
Neutral Building - Add Gnoll Brute to (Picked unit) with 3 in stock and a max stock of 3
Neutral Building - Add Gnoll Assassin (Gnoll Assassin) to (Picked unit) with 3 in stock and a max stock of 3
Else - Actions
-------- Give a 20% chance for murloc mercs. --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
TempInt2 Less than or equal to 100
TempInt2 Greater than 80
Then - Actions
Neutral Building - Add Murloc Plaguebearer (Murloc Plaguebearer) to (Picked unit) with 4 in stock and a max stock of 4
Neutral Building - Add Murloc Flesheater (Murloc Flesheater) to (Picked unit) with 2 in stock and a max stock of 2
Neutral Building - Add Murloc Mutant (Murloc Mutant) to (Picked unit) with 1 in stock and a max stock of 1
Else - Actions
Unit Group - Remove (Picked unit) from TempMercRecruitPubPool .
Else - Actions
Bandit Pub Replace Ability
Events
Unit - A unit Finishes research
Conditions
(Researched tech-type) Equal to R001 (Unexpected type: 'techcode')
Actions
Set Variable Set TempOwner = (Owner of (Researching unit))
Set Variable Set TempUnitGroup = (Units of type Seedy Pub (Barracks))
Unit Group - Pick every unit in TempUnitGroup and do (Actions)
Loop - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Owner of (Picked unit)) Equal to TempOwner
Then - Actions
Unit - Remove Seedy Pub (Critical Strike) from (Picked unit)
Unit - Add Seedy Pub Upgrade (Critical Strike) to (Picked unit)
Else - Actions
Custom script: call DestroyGroup(udg_TempUnitGroup)
Set Variable Set TempUnitGroup = (Units of type Tower Ruins (Arcane Sanctum))
Unit Group - Pick every unit in TempUnitGroup and do (Actions)
Loop - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Owner of (Picked unit)) Equal to TempOwner
Then - Actions
Unit - Remove Tower Ruins (Critical Strike) from (Picked unit)
Unit - Add Tower Ruins Upgrade (Critical Strike) to (Picked unit)
Else - Actions
Custom script: call DestroyGroup(udg_TempUnitGroup)
https://www.hiveworkshop.com/threads/how-delete-set-rally-point-abillty-from-map.205234/
Remove Set Rally Point
Events
Unit - A unit Begins construction
Conditions
Or - Any (Conditions) are true
Conditions
(Unit-type of (Constructing structure)) Equal to Seedy Pub (Barracks)
(Unit-type of (Constructing structure)) Equal to Tower Ruins (Arcane Sanctum)
(Unit-type of (Constructing structure)) Equal to Dragon Breeding Pit (Gryphon Aviary)
Actions
Unit - Remove Rally from (Constructing structure)
Bandit Pub Mercenary Recruitment Pool
Events
Time - Every (Random real number between 300.00 and 420.00) seconds of game time
Conditions
Actions
Set Variable Set TempMercRecruitPubPool = (Units of type Seedy Pub (Barracks))
Unit Group - Pick every unit in TempMercRecruitPubPool and do (Actions)
Loop - Actions
Set Variable Set TempInt = (Random integer number between 1 and 100)
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
Or - Any (Conditions) are true
Conditions
(Level of Seedy Pub (Critical Strike) for (Picked unit)) Greater than 0
(Level of Seedy Pub Upgrade (Critical Strike) for (Picked unit)) Greater than 0
((Picked unit) is alive) Equal to True
TempInt Less than or equal to 60
Then - Actions
Set Variable Set TempInt2 = (Random integer number between 1 and 100)
Neutral Building - Remove Rogue (Rogue) from (Picked unit)
Neutral Building - Remove Enforcer (Enforcer) from (Picked unit)
Neutral Building - Remove Assassin (Assassin) from (Picked unit)
Neutral Building - Remove Forest Troll from (Picked unit)
Neutral Building - Remove Forest Troll Trapper (Forest Troll Trapper) from (Picked unit)
Neutral Building - Remove Forest Troll Berserker (Forest Troll Berserker) from (Picked unit)
Neutral Building - Remove Ogre Warrior from (Picked unit)
Neutral Building - Remove Ogre Mauler (Ogre Mauler) from (Picked unit)
Neutral Building - Remove Gnoll Brute from (Picked unit)
Neutral Building - Remove Gnoll Assassin (Gnoll Assassin) from (Picked unit)
Neutral Building - Remove Murloc Plaguebearer (Murloc Plaguebearer) from (Picked unit)
Neutral Building - Remove Murloc Flesheater (Murloc Flesheater) from (Picked unit)
Neutral Building - Remove Murloc Mutant (Murloc Mutant) from (Picked unit)
-------- Give a 20% chance for bandit mercs. --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
TempInt2 Less than or equal to 20
Then - Actions
Neutral Building - Add Rogue (Rogue) to (Picked unit) with 3 in stock and a max stock of 3
Neutral Building - Add Enforcer (Enforcer) to (Picked unit) with 2 in stock and a max stock of 2
Neutral Building - Add Assassin (Assassin) to (Picked unit) with 3 in stock and a max stock of 3
Else - Actions
-------- Give a 20% chance for troll mercs. --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
TempInt2 Less than or equal to 40
TempInt2 Greater than 20
Then - Actions
Neutral Building - Add Forest Troll to (Picked unit) with 4 in stock and a max stock of 4
Neutral Building - Add Forest Troll Trapper (Forest Troll Trapper) to (Picked unit) with 2 in stock and a max stock of 2
Neutral Building - Add Forest Troll Berserker (Forest Troll Berserker) to (Picked unit) with 1 in stock and a max stock of 1
Else - Actions
-------- Give a 20% chance for ogre mercs. --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
TempInt2 Less than or equal to 60
TempInt2 Greater than 40
Then - Actions
Neutral Building - Add Ogre Warrior to (Picked unit) with 4 in stock and a max stock of 4
Neutral Building - Add Ogre Mauler (Ogre Mauler) to (Picked unit) with 2 in stock and a max stock of 2
Else - Actions
-------- Give a 20% chance for gnoll mercs. --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
TempInt2 Less than or equal to 80
TempInt2 Greater than 60
Then - Actions
Neutral Building - Add Gnoll Brute to (Picked unit) with 3 in stock and a max stock of 3
Neutral Building - Add Gnoll Assassin (Gnoll Assassin) to (Picked unit) with 3 in stock and a max stock of 3
Else - Actions
-------- Give a 20% chance for murloc mercs. --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
TempInt2 Less than or equal to 100
TempInt2 Greater than 80
Then - Actions
Neutral Building - Add Murloc Plaguebearer (Murloc Plaguebearer) to (Picked unit) with 4 in stock and a max stock of 4
Neutral Building - Add Murloc Flesheater (Murloc Flesheater) to (Picked unit) with 2 in stock and a max stock of 2
Neutral Building - Add Murloc Mutant (Murloc Mutant) to (Picked unit) with 1 in stock and a max stock of 1
Else - Actions
Unit Group - Remove (Picked unit) from TempMercRecruitPubPool .
Floating Text - Create floating text that reads New mercenaries have arrived! above (Picked unit) with Z offset 0 , using font size 10 , color ( 100.00 %, 100 %, 100.00 %), and 0 % transparency
Floating Text - Show (Last created floating text) for (All allies of (Owner of (Picked unit)).)
Floating Text - Hide (Last created floating text) for (All enemies of (Owner of (Picked unit)).)
Floating Text - Change (Last created floating text) : Disable permanence
Floating Text - Change the lifespan of (Last created floating text) to 5.00 seconds
Floating Text - Change the fading age of (Last created floating text) to 1.00 seconds
Floating Text - Set the velocity of (Last created floating text) to 64.00 towards 90 degrees
Else - Actions
Bandit Pub Gacha
Events
Unit - A unit Finishes training a unit
Conditions
(Unit-type of (Trained unit)) Equal to Dummy Roll Gacha (Footman)
Actions
Unit - Remove (Entering unit) from the game
Set Variable Set TempUnit = (Triggering unit)
Unit Group - Add TempUnit to TempMercRecruitPubPool
Unit Group - Pick every unit in TempMercRecruitPubPool and do (Actions)
Loop - Actions
Set Variable Set TempInt2 = (Random integer number between 1 and 100)
Neutral Building - Remove Rogue (Rogue) from (Picked unit)
Neutral Building - Remove Enforcer (Enforcer) from (Picked unit)
Neutral Building - Remove Assassin (Assassin) from (Picked unit)
Neutral Building - Remove Forest Troll from (Picked unit)
Neutral Building - Remove Forest Troll Trapper (Forest Troll Trapper) from (Picked unit)
Neutral Building - Remove Forest Troll Berserker (Forest Troll Berserker) from (Picked unit)
Neutral Building - Remove Ogre Warrior from (Picked unit)
Neutral Building - Remove Ogre Mauler (Ogre Mauler) from (Picked unit)
Neutral Building - Remove Gnoll Brute from (Picked unit)
Neutral Building - Remove Gnoll Assassin (Gnoll Assassin) from (Picked unit)
Neutral Building - Remove Murloc Plaguebearer (Murloc Plaguebearer) from (Picked unit)
Neutral Building - Remove Murloc Flesheater (Murloc Flesheater) from (Picked unit)
Neutral Building - Remove Murloc Mutant (Murloc Mutant) from (Picked unit)
-------- Give a 20% chance for bandit mercs. --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
TempInt2 Less than or equal to 20
Then - Actions
Neutral Building - Add Rogue (Rogue) to (Picked unit) with 3 in stock and a max stock of 3
Neutral Building - Add Enforcer (Enforcer) to (Picked unit) with 2 in stock and a max stock of 2
Neutral Building - Add Assassin (Assassin) to (Picked unit) with 3 in stock and a max stock of 3
Else - Actions
-------- Give a 20% chance for troll mercs. --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
TempInt2 Less than or equal to 40
TempInt2 Greater than 20
Then - Actions
Neutral Building - Add Forest Troll to (Picked unit) with 4 in stock and a max stock of 4
Neutral Building - Add Forest Troll Trapper (Forest Troll Trapper) to (Picked unit) with 2 in stock and a max stock of 2
Neutral Building - Add Forest Troll Berserker (Forest Troll Berserker) to (Picked unit) with 1 in stock and a max stock of 1
Else - Actions
-------- Give a 20% chance for ogre mercs. --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
TempInt2 Less than or equal to 60
TempInt2 Greater than 40
Then - Actions
Neutral Building - Add Ogre Warrior to (Picked unit) with 4 in stock and a max stock of 4
Neutral Building - Add Ogre Mauler (Ogre Mauler) to (Picked unit) with 2 in stock and a max stock of 2
Else - Actions
-------- Give a 20% chance for gnoll mercs. --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
TempInt2 Less than or equal to 80
TempInt2 Greater than 60
Then - Actions
Neutral Building - Add Gnoll Brute to (Picked unit) with 3 in stock and a max stock of 3
Neutral Building - Add Gnoll Assassin (Gnoll Assassin) to (Picked unit) with 3 in stock and a max stock of 3
Else - Actions
-------- Give a 20% chance for murloc mercs. --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
TempInt2 Less than or equal to 100
TempInt2 Greater than 80
Then - Actions
Neutral Building - Add Murloc Plaguebearer (Murloc Plaguebearer) to (Picked unit) with 4 in stock and a max stock of 4
Neutral Building - Add Murloc Flesheater (Murloc Flesheater) to (Picked unit) with 2 in stock and a max stock of 2
Neutral Building - Add Murloc Mutant (Murloc Mutant) to (Picked unit) with 1 in stock and a max stock of 1
Else - Actions
Unit Group - Remove (Picked unit) from TempMercRecruitPubPool .
Floating Text - Create floating text that reads New mercenaries have arrived! above (Picked unit) with Z offset 0 , using font size 10 , color ( 100.00 %, 100 %, 100.00 %), and 0 % transparency
Floating Text - Show (Last created floating text) for (All allies of (Owner of (Picked unit)).)
Floating Text - Hide (Last created floating text) for (All enemies of (Owner of (Picked unit)).)
Floating Text - Change (Last created floating text) : Disable permanence
Floating Text - Change the lifespan of (Last created floating text) to 5.00 seconds
Floating Text - Change the fading age of (Last created floating text) to 1.00 seconds
Floating Text - Set the velocity of (Last created floating text) to 64.00 towards 90 degrees
Bandit Ruins Gacha
Events
Unit - A unit Finishes training a unit
Conditions
(Unit-type of (Trained unit)) Equal to Dummy Roll Gacha Ruins (Footman)
Actions
Unit - Remove (Entering unit) from the game
Set Variable Set TempUnit = (Triggering unit)
Unit Group - Add TempUnit to TempMercRecruitRuinsPool
Unit Group - Pick every unit in TempMercRecruitRuinsPool and do (Actions)
Loop - Actions
Set Variable Set TempInt2 = (Random integer number between 1 and 100)
Neutral Building - Remove Chaplain (Chaplain) from (Picked unit)
Neutral Building - Remove Heretic (Heretic) from (Picked unit)
Neutral Building - Remove Renegade Wizard (Renegade Wizard) from (Picked unit)
Neutral Building - Remove Deceiver (Deceiver) from (Picked unit)
Neutral Building - Remove Rogue Wizard (Rogue Wizard) from (Picked unit)
Neutral Building - Remove Forest Troll Shadow Priest (Forest Troll Shadow Priest) from (Picked unit)
Neutral Building - Remove Ogre Magi (Ogre Magi) from (Picked unit)
Neutral Building - Remove Kobold Geomancer (Kobold Geomancer) from (Picked unit)
Neutral Building - Remove Gnoll Warden (Gnoll Warden) from (Picked unit)
Neutral Building - Remove Mud Golem (Mud Golem) from (Picked unit)
Neutral Building - Remove Rock Golem (Rock Golem) from (Picked unit)
-------- Give a 20% chance for bandit mercs variation 1. --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
TempInt2 Less than or equal to 20
Then - Actions
Neutral Building - Add Chaplain (Chaplain) to (Picked unit) with 3 in stock and a max stock of 3
Neutral Building - Add Heretic (Heretic) to (Picked unit) with 1 in stock and a max stock of 1
Neutral Building - Add Renegade Wizard (Renegade Wizard) to (Picked unit) with 1 in stock and a max stock of 1
Else - Actions
-------- Give a 20% chance for bandit mercs variation 2. --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
TempInt2 Less than or equal to 40
TempInt2 Greater than 20
Then - Actions
Neutral Building - Add Deceiver (Deceiver) to (Picked unit) with 3 in stock and a max stock of 3
Neutral Building - Add Rogue Wizard (Rogue Wizard) to (Picked unit) with 3 in stock and a max stock of 3
Else - Actions
-------- Give a 20% chance to for troll and ogre mercs. --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
TempInt2 Less than or equal to 60
TempInt2 Greater than 40
Then - Actions
Neutral Building - Add Forest Troll Shadow Priest (Forest Troll Shadow Priest) to (Picked unit) with 3 in stock and a max stock of 3
Neutral Building - Add Ogre Magi (Ogre Magi) to (Picked unit) with 2 in stock and a max stock of 2
Else - Actions
-------- Give a 20% chance to for kobold and gnoll mercs. --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
TempInt2 Less than or equal to 80
TempInt2 Greater than 60
Then - Actions
Neutral Building - Add Kobold Geomancer (Kobold Geomancer) to (Picked unit) with 3 in stock and a max stock of 3
Neutral Building - Add Gnoll Warden (Gnoll Warden) to (Picked unit) with 3 in stock and a max stock of 3
Else - Actions
-------- Give a 20% chance to for golem mercs. --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
TempInt2 Less than or equal to 100
TempInt2 Greater than 80
Then - Actions
Neutral Building - Add Mud Golem (Mud Golem) to (Picked unit) with 4 in stock and a max stock of 4
Neutral Building - Add Rock Golem (Rock Golem) to (Picked unit) with 2 in stock and a max stock of 2
Else - Actions
Unit Group - Remove (Picked unit) from TempMercRecruitRuinsPool .
Floating Text - Create floating text that reads New mercenaries have arrived! above (Picked unit) with Z offset 0 , using font size 10 , color ( 100.00 %, 100 %, 100.00 %), and 0 % transparency
Floating Text - Show (Last created floating text) for (All allies of (Owner of (Picked unit)).)
Floating Text - Hide (Last created floating text) for (All enemies of (Owner of (Picked unit)).)
Floating Text - Change (Last created floating text) : Disable permanence
Floating Text - Change the lifespan of (Last created floating text) to 5.00 seconds
Floating Text - Change the fading age of (Last created floating text) to 1.00 seconds
Floating Text - Set the velocity of (Last created floating text) to 64.00 towards 90 degrees
Bandit Breeding Pit
Events
Unit - A unit Finishes construction
Conditions
(Unit-type of (Triggering unit)) Equal to Dragon Breeding Pit (Gryphon Aviary)
Actions
Set Variable Set TempUnit = (Constructed structure)
Neutral Building - Add Black Dragon Whelp (Black Dragon Whelp) to TempUnit with 0 in stock and a max stock of 4
Neutral Building - Add Black Drake (Black Drake) to TempUnit with 0 in stock and a max stock of 2
Neutral Building - Add Bronze Dragon Whelp (Bronze Dragon Whelp) to TempUnit with 0 in stock and a max stock of 4
Neutral Building - Add Bronze Drake (Bronze Drake) to TempUnit with 0 in stock and a max stock of 2
Bandit Breeding Pit Gacha
Events
Unit - A unit Finishes training a unit
Conditions
(Unit-type of (Trained unit)) Equal to Dummy Roll Gacha Dragon (Footman)
Actions
Set Variable Set TempUnit = (Triggering unit)
Neutral Building - Remove Black Dragon Whelp (Black Dragon Whelp) from TempUnit
Neutral Building - Remove Black Drake (Black Drake) from TempUnit
Neutral Building - Remove Bronze Dragon Whelp (Bronze Dragon Whelp) from TempUnit
Neutral Building - Remove Bronze Drake (Bronze Drake) from TempUnit
Neutral Building - Add Black Dragon Whelp (Black Dragon Whelp) to TempUnit with 4 in stock and a max stock of 4
Neutral Building - Add Black Drake (Black Drake) to TempUnit with 2 in stock and a max stock of 2
Neutral Building - Add Bronze Dragon Whelp (Bronze Dragon Whelp) to TempUnit with 4 in stock and a max stock of 4
Neutral Building - Add Bronze Drake (Bronze Drake) to TempUnit with 2 in stock and a max stock of 2
https://www.hiveworkshop.com/threads/trigger-get-price-of-unit.263610/
edo494

https://www.hiveworkshop.com/threads/getting-the-gold-lumber-cost-of-unit.295718/
Jampion
Bandit Commission
Events
Unit - A unit Sells a unit
Conditions
Or - Any (Conditions) are true
Conditions
(Unit-type of (Selling unit)) Equal to Seedy Pub (Barracks)
(Unit-type of (Selling unit)) Equal to Tower Ruins (Arcane Sanctum)
(Owner of (Selling unit)) Not equal to (Owner of (Sold unit))
Actions
Set Variable Set TempUnitSold = (Sold unit)
Set Variable Set TempOwner = (Owner of (Selling unit))
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Current research level of R001 (Unexpected type: 'techcode') for TempOwner) Equal to 1
Then - Actions
Custom script: set udg_TempSoldUnitCostGold = GetUnitGoldCost(GetUnitTypeId(GetSoldUnit()))
Game - Display to (All players matching ((Matching player) Equal to TempOwner).) the text: (Name of TempUnitSold)
Game - Display to (All players matching ((Matching player) Equal to TempOwner).) the text: (Gold Cost: + (String(TempSoldUnitCostGold, 1, 1)))
Set Variable Set TempSoldUnitCostGold = (TempSoldUnitCostGold x 0.20)
Player - Add (Integer(TempSoldUnitCostGold)) to TempOwner . Current gold
Game - Display to (All players matching ((Matching player) Equal to TempOwner).) the text: (Gold Cost Fee: + (String(TempSoldUnitCostGold, 1, 1)))
Custom script: set udg_TempSoldUnitCostLumber = GetUnitWoodCost(GetUnitTypeId(GetSoldUnit()))
Game - Display to (All players matching ((Matching player) Equal to TempOwner).) the text: (Lumber Cost: + (String(TempSoldUnitCostLumber, 1, 1)))
Set Variable Set TempSoldUnitCostLumber = (TempSoldUnitCostLumber x 0.20)
Player - Add (Integer(TempSoldUnitCostLumber)) to TempOwner . Current lumber
Game - Display to (All players matching ((Matching player) Equal to TempOwner).) the text: (Lumber Cost Fee: + (String(TempSoldUnitCostLumber, 1, 1)))
Else - Actions
Custom script: set udg_TempSoldUnitCostGold = GetUnitGoldCost(GetUnitTypeId(GetSoldUnit()))
Game - Display to (All players matching ((Matching player) Equal to TempOwner).) the text: (Name of TempUnitSold)
Game - Display to (All players matching ((Matching player) Equal to TempOwner).) the text: (Gold Cost: + (String(TempSoldUnitCostGold, 1, 1)))
Set Variable Set TempSoldUnitCostGold = (TempSoldUnitCostGold x 0.10)
Player - Add (Integer(TempSoldUnitCostGold)) to TempOwner . Current gold
Game - Display to (All players matching ((Matching player) Equal to TempOwner).) the text: (Gold Cost Fee: + (String(TempSoldUnitCostGold, 1, 1)))
Custom script: set udg_TempSoldUnitCostLumber = GetUnitWoodCost(GetUnitTypeId(GetSoldUnit()))
Game - Display to (All players matching ((Matching player) Equal to TempOwner).) the text: (Lumber Cost: + (String(TempSoldUnitCostLumber, 1, 1)))
Set Variable Set TempSoldUnitCostLumber = (TempSoldUnitCostLumber x 0.10)
Player - Add (Integer(TempSoldUnitCostLumber)) to TempOwner . Current lumber
Game - Display to (All players matching ((Matching player) Equal to TempOwner).) the text: (Lumber Cost Fee: + (String(TempSoldUnitCostLumber, 1, 1)))
https://www.hiveworkshop.com/threads/trigger-get-price-of-unit.263610/
edo494

https://www.hiveworkshop.com/threads/getting-the-gold-lumber-cost-of-unit.295718/
Jampion
Bandit Commission Dragons
Events
Unit - A unit Sells a unit
Conditions
(Unit-type of (Selling unit)) Equal to Dragon Breeding Pit (Gryphon Aviary)
(Owner of (Selling unit)) Not equal to (Owner of (Sold unit))
Actions
Set Variable Set TempUnitSold = (Sold unit)
Set Variable Set TempOwner = (Owner of (Selling unit))
Custom script: set udg_TempSoldUnitCostGold = GetUnitGoldCost(GetUnitTypeId(GetSoldUnit()))
Game - Display to (All players matching ((Matching player) Equal to TempOwner).) the text: (Name of TempUnitSold)
Game - Display to (All players matching ((Matching player) Equal to TempOwner).) the text: (Gold Cost: + (String(TempSoldUnitCostGold, 1, 1)))
Set Variable Set TempSoldUnitCostGold = (TempSoldUnitCostGold x 0.30)
Player - Add (Integer(TempSoldUnitCostGold)) to TempOwner . Current gold
Game - Display to (All players matching ((Matching player) Equal to TempOwner).) the text: (Gold Cost Fee: + (String(TempSoldUnitCostGold, 1, 1)))
Custom script: set udg_TempSoldUnitCostLumber = GetUnitWoodCost(GetUnitTypeId(GetSoldUnit()))
Game - Display to (All players matching ((Matching player) Equal to TempOwner).) the text: (Lumber Cost: + (String(TempSoldUnitCostLumber, 1, 1)))
Set Variable Set TempSoldUnitCostLumber = (TempSoldUnitCostLumber x 0.30)
Player - Add (Integer(TempSoldUnitCostLumber)) to TempOwner . Current lumber
Game - Display to (All players matching ((Matching player) Equal to TempOwner).) the text: (Lumber Cost Fee: + (String(TempSoldUnitCostLumber, 1, 1)))
https://www.hiveworkshop.com/threads/trigger-get-price-of-unit.263610/
edo494

https://www.hiveworkshop.com/threads/getting-the-gold-lumber-cost-of-unit.295718/
Jampion
Bandit Hire Refund
Events
Unit - A unit Sells a unit
Conditions
Or - Any (Conditions) are true
Conditions
(Unit-type of (Selling unit)) Equal to Seedy Pub (Barracks)
(Unit-type of (Selling unit)) Equal to Tower Ruins (Arcane Sanctum)
(Owner of (Selling unit)) Equal to (Owner of (Sold unit))
Actions
Set Variable Set TempUnitSold = (Sold unit)
Set Variable Set TempOwner = (Owner of (Selling unit))
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Current research level of R001 (Unexpected type: 'techcode') for TempOwner) Equal to 1
Then - Actions
Custom script: set udg_TempSoldUnitCostGold = GetUnitGoldCost(GetUnitTypeId(GetSoldUnit()))
Game - Display to (All players matching ((Matching player) Equal to TempOwner).) the text: (Name of TempUnitSold)
Game - Display to (All players matching ((Matching player) Equal to TempOwner).) the text: (Gold Cost: + (String(TempSoldUnitCostGold, 1, 1)))
Set Variable Set TempSoldUnitCostGold = (TempSoldUnitCostGold x 0.20)
Player - Add (Integer(TempSoldUnitCostGold)) to TempOwner . Current gold
Game - Display to (All players matching ((Matching player) Equal to TempOwner).) the text: (Gold Cost Refund: + (String(TempSoldUnitCostGold, 1, 1)))
Custom script: set udg_TempSoldUnitCostLumber = GetUnitWoodCost(GetUnitTypeId(GetSoldUnit()))
Game - Display to (All players matching ((Matching player) Equal to TempOwner).) the text: (Lumber Cost: + (String(TempSoldUnitCostLumber, 1, 1)))
Set Variable Set TempSoldUnitCostLumber = (TempSoldUnitCostLumber x 0.20)
Player - Add (Integer(TempSoldUnitCostLumber)) to TempOwner . Current lumber
Game - Display to (All players matching ((Matching player) Equal to TempOwner).) the text: (Lumber Cost Refund: + (String(TempSoldUnitCostLumber, 1, 1)))
Else - Actions
https://www.hiveworkshop.com/threads/the-mysteries-of-the-spellbook.33039/
Bandit Veteran Mercenaries
Events
Unit - A unit Sells a unit
Conditions
(Current research level of R002 (Unexpected type: 'techcode') for (Owner of (Sold unit))) Equal to 1
Actions
Set Variable Set TempUnit = (Sold unit)
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Current research level of R002 (Unexpected type: 'techcode') for (Owner of TempUnit)) Equal to 1
(TempUnit is A Hero) Equal to False
Then - Actions
Unit - Add Hide Veteran Mercenaries Bonus (Spell Book) to TempUnit
Else - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Current research level of R002 (Unexpected type: 'techcode') for (Owner of TempUnit)) Equal to 1
(Mana of TempUnit) Greater than or equal to 1.00
(TempUnit is A Hero) Equal to False
Then - Actions
Unit - Add Hide Veteran Mercenaries Mana Bonus (Spell Book) to TempUnit
Else - Actions
https://www.hiveworkshop.com/threads/the-mysteries-of-the-spellbook.33039/
Bandit Elite Mercenaries
Events
Unit - A unit Sells a unit
Conditions
(Current research level of R002 (Unexpected type: 'techcode') for (Owner of (Sold unit))) Greater than 1
Actions
Set Variable Set TempUnit = (Sold unit)
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Current research level of R002 (Unexpected type: 'techcode') for (Owner of TempUnit)) Greater than 1
(TempUnit is A Hero) Equal to False
Then - Actions
Unit - Add Hide Veteran Mercenaries Bonus (Spell Book) to TempUnit
Unit - Set level of Hide Veteran Mercenaries Bonus (Spell Book) for TempUnit to 2
Else - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Current research level of R002 (Unexpected type: 'techcode') for (Owner of TempUnit)) Greater than 1
(Mana of TempUnit) Greater than or equal to 1.00
(TempUnit is A Hero) Equal to False
Then - Actions
Unit - Add Hide Veteran Mercenaries Mana Bonus (Spell Book) to TempUnit
Unit - Set level of Hide Veteran Mercenaries Mana Bonus (Spell Book) for TempUnit to 2
Else - Actions
Bandit Ruins Add Ability
Events
Unit - A unit Finishes construction
Conditions
(Unit-type of (Triggering unit)) Equal to Tower Ruins (Arcane Sanctum)
Actions
Set Variable Set TempUnit = (Constructed structure)
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Current research level of R001 (Unexpected type: 'techcode') for (Owner of TempUnit)) Equal to 1
Then - Actions
Unit - Add Tower Ruins Upgrade (Critical Strike) to TempUnit
Else - Actions
Unit - Add Tower Ruins (Critical Strike) to TempUnit
Unit Group - Add TempUnit to TempMercRecruitRuinsPool
Unit Group - Pick every unit in TempMercRecruitRuinsPool and do (Actions)
Loop - Actions
Set Variable Set TempUnit = No unit
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
Or - Any (Conditions) are true
Conditions
(Level of Tower Ruins (Critical Strike) for (Picked unit)) Greater than 0
(Level of Tower Ruins Upgrade (Critical Strike) for (Picked unit)) Greater than 0
((Picked unit) is alive) Equal to True
Then - Actions
Set Variable Set TempInt2 = (Random integer number between 1 and 100)
Neutral Building - Remove Chaplain (Chaplain) from (Picked unit)
Neutral Building - Remove Heretic (Heretic) from (Picked unit)
Neutral Building - Remove Renegade Wizard (Renegade Wizard) from (Picked unit)
Neutral Building - Remove Deceiver (Deceiver) from (Picked unit)
Neutral Building - Remove Rogue Wizard (Rogue Wizard) from (Picked unit)
Neutral Building - Remove Forest Troll Shadow Priest (Forest Troll Shadow Priest) from (Picked unit)
Neutral Building - Remove Ogre Magi (Ogre Magi) from (Picked unit)
Neutral Building - Remove Kobold Geomancer (Kobold Geomancer) from (Picked unit)
Neutral Building - Remove Gnoll Warden (Gnoll Warden) from (Picked unit)
Neutral Building - Remove Mud Golem (Mud Golem) from (Picked unit)
Neutral Building - Remove Rock Golem (Rock Golem) from (Picked unit)
-------- Give a 20% chance for bandit mercs variation 1. --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
TempInt2 Less than or equal to 20
Then - Actions
Neutral Building - Add Chaplain (Chaplain) to (Picked unit) with 3 in stock and a max stock of 3
Neutral Building - Add Heretic (Heretic) to (Picked unit) with 1 in stock and a max stock of 1
Neutral Building - Add Renegade Wizard (Renegade Wizard) to (Picked unit) with 1 in stock and a max stock of 1
Else - Actions
-------- Give a 20% chance for bandit mercs variation 2. --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
TempInt2 Less than or equal to 40
TempInt2 Greater than 20
Then - Actions
Neutral Building - Add Deceiver (Deceiver) to (Picked unit) with 3 in stock and a max stock of 3
Neutral Building - Add Rogue Wizard (Rogue Wizard) to (Picked unit) with 3 in stock and a max stock of 3
Else - Actions
-------- Give a 20% chance to for troll and ogre mercs. --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
TempInt2 Less than or equal to 60
TempInt2 Greater than 40
Then - Actions
Neutral Building - Add Forest Troll Shadow Priest (Forest Troll Shadow Priest) to (Picked unit) with 3 in stock and a max stock of 3
Neutral Building - Add Ogre Magi (Ogre Magi) to (Picked unit) with 2 in stock and a max stock of 2
Else - Actions
-------- Give a 20% chance to for kobold and gnoll mercs. --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
TempInt2 Less than or equal to 80
TempInt2 Greater than 60
Then - Actions
Neutral Building - Add Kobold Geomancer (Kobold Geomancer) to (Picked unit) with 3 in stock and a max stock of 3
Neutral Building - Add Gnoll Warden (Gnoll Warden) to (Picked unit) with 3 in stock and a max stock of 3
Else - Actions
-------- Give a 20% chance to for golem mercs. --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
TempInt2 Less than or equal to 100
TempInt2 Greater than 80
Then - Actions
Neutral Building - Add Mud Golem (Mud Golem) to (Picked unit) with 4 in stock and a max stock of 4
Neutral Building - Add Rock Golem (Rock Golem) to (Picked unit) with 2 in stock and a max stock of 2
Else - Actions
Unit Group - Remove (Picked unit) from TempMercRecruitRuinsPool .
Else - Actions
Bandit Ruins Mercenary Recruitment Pool
Events
Time - Every (Random real number between 300.00 and 420.00) seconds of game time
Conditions
Actions
Set Variable Set TempMercRecruitRuinsPool = (Units of type Tower Ruins (Arcane Sanctum))
Unit Group - Pick every unit in TempMercRecruitRuinsPool and do (Actions)
Loop - Actions
Set Variable Set TempInt = (Random integer number between 1 and 100)
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
Or - Any (Conditions) are true
Conditions
(Level of Tower Ruins (Critical Strike) for (Picked unit)) Greater than 0
(Level of Tower Ruins Upgrade (Critical Strike) for (Picked unit)) Greater than 0
((Picked unit) is alive) Equal to True
TempInt Less than or equal to 60
Then - Actions
Set Variable Set TempInt2 = (Random integer number between 1 and 100)
Neutral Building - Remove Chaplain (Chaplain) from (Picked unit)
Neutral Building - Remove Heretic (Heretic) from (Picked unit)
Neutral Building - Remove Renegade Wizard (Renegade Wizard) from (Picked unit)
Neutral Building - Remove Deceiver (Deceiver) from (Picked unit)
Neutral Building - Remove Rogue Wizard (Rogue Wizard) from (Picked unit)
Neutral Building - Remove Forest Troll Shadow Priest (Forest Troll Shadow Priest) from (Picked unit)
Neutral Building - Remove Ogre Magi (Ogre Magi) from (Picked unit)
Neutral Building - Remove Kobold Geomancer (Kobold Geomancer) from (Picked unit)
Neutral Building - Remove Gnoll Warden (Gnoll Warden) from (Picked unit)
Neutral Building - Remove Mud Golem (Mud Golem) from (Picked unit)
Neutral Building - Remove Rock Golem (Rock Golem) from (Picked unit)
-------- Give a 20% chance for bandit mercs variation 1. --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
TempInt2 Less than or equal to 20
Then - Actions
Neutral Building - Add Chaplain (Chaplain) to (Picked unit) with 3 in stock and a max stock of 3
Neutral Building - Add Heretic (Heretic) to (Picked unit) with 1 in stock and a max stock of 1
Neutral Building - Add Renegade Wizard (Renegade Wizard) to (Picked unit) with 1 in stock and a max stock of 1
Else - Actions
-------- Give a 20% chance for bandit mercs variation 2. --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
TempInt2 Less than or equal to 40
TempInt2 Greater than 20
Then - Actions
Neutral Building - Add Deceiver (Deceiver) to (Picked unit) with 3 in stock and a max stock of 3
Neutral Building - Add Rogue Wizard (Rogue Wizard) to (Picked unit) with 3 in stock and a max stock of 3
Else - Actions
-------- Give a 20% chance to for troll and ogre mercs. --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
TempInt2 Less than or equal to 60
TempInt2 Greater than 40
Then - Actions
Neutral Building - Add Forest Troll Shadow Priest (Forest Troll Shadow Priest) to (Picked unit) with 3 in stock and a max stock of 3
Neutral Building - Add Ogre Magi (Ogre Magi) to (Picked unit) with 2 in stock and a max stock of 2
Else - Actions
-------- Give a 20% chance to for kobold and gnoll mercs. --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
TempInt2 Less than or equal to 80
TempInt2 Greater than 60
Then - Actions
Neutral Building - Add Kobold Geomancer (Kobold Geomancer) to (Picked unit) with 3 in stock and a max stock of 3
Neutral Building - Add Gnoll Warden (Gnoll Warden) to (Picked unit) with 3 in stock and a max stock of 3
Else - Actions
-------- Give a 20% chance to for golem mercs. --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
TempInt2 Less than or equal to 100
TempInt2 Greater than 80
Then - Actions
Neutral Building - Add Mud Golem (Mud Golem) to (Picked unit) with 4 in stock and a max stock of 4
Neutral Building - Add Rock Golem (Rock Golem) to (Picked unit) with 2 in stock and a max stock of 2
Else - Actions
Unit Group - Remove (Picked unit) from TempMercRecruitRuinsPool .
Floating Text - Create floating text that reads New mercenaries have arrived! above (Picked unit) with Z offset 0 , using font size 10 , color ( 100.00 %, 100 %, 100.00 %), and 0 % transparency
Floating Text - Show (Last created floating text) for (All allies of (Owner of (Picked unit)).)
Floating Text - Hide (Last created floating text) for (All enemies of (Owner of (Picked unit)).)
Floating Text - Change (Last created floating text) : Disable permanence
Floating Text - Change the lifespan of (Last created floating text) to 5.00 seconds
Floating Text - Change the fading age of (Last created floating text) to 1.00 seconds
Floating Text - Set the velocity of (Last created floating text) to 64.00 towards 90 degrees
Else - Actions
Bandit Market Add Item Pool
Events
Unit - A unit Finishes construction
Conditions
(Unit-type of (Triggering unit)) Equal to Black Market (Arcane Vault)
Actions
Set Variable Set TempUnit = (Constructed structure)
Unit Group - Add TempUnit to TempBlackMarketItemPool
Unit Group - Pick every unit in TempBlackMarketItemPool and do (Actions)
Loop - Actions
Set Variable Set TempUnit = No unit
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
((Picked unit) is alive) Equal to True
Then - Actions
Set Variable Set TempInt2 = (Random integer number between 1 and 100)
Neutral Building - Remove Scroll of Regeneration from (Picked unit)
Neutral Building - Remove Spider Silk Broach from (Picked unit)
Neutral Building - Remove Healing Salve from (Picked unit)
Neutral Building - Remove Wand of Illusion from (Picked unit)
Neutral Building - Remove Scroll of Mana from (Picked unit)
Neutral Building - Remove Sentry Wards from (Picked unit)
Neutral Building - Remove Vampiric Potion from (Picked unit)
Neutral Building - Remove Lesser Replenishment Potion from (Picked unit)
Neutral Building - Remove Wand of Mana Stealing from (Picked unit)
-------- Give a 20% chance for item variation 1. --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
TempInt2 Less than or equal to 20
Then - Actions
Neutral Building - Add Scroll of Regeneration to (Picked unit) with 2 in stock and a max stock of 2
Neutral Building - Add Spider Silk Broach to (Picked unit) with 2 in stock and a max stock of 2
Else - Actions
-------- Give a 20% chance for item variation 2. --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
TempInt2 Less than or equal to 40
TempInt2 Greater than 20
Then - Actions
Neutral Building - Add Healing Salve to (Picked unit) with 2 in stock and a max stock of 2
Neutral Building - Add Wand of Illusion to (Picked unit) with 1 in stock and a max stock of 1
Else - Actions
-------- Give a 20% chance for item variation 3. --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
TempInt2 Less than or equal to 60
TempInt2 Greater than 40
Then - Actions
Neutral Building - Add Scroll of Mana to (Picked unit) with 2 in stock and a max stock of 2
Neutral Building - Add Sentry Wards to (Picked unit) with 1 in stock and a max stock of 1
Else - Actions
-------- Give a 20% chance for item variation 4. --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
TempInt2 Less than or equal to 80
TempInt2 Greater than 60
Then - Actions
Neutral Building - Add Vampiric Potion to (Picked unit) with 2 in stock and a max stock of 2
Neutral Building - Add Lesser Replenishment Potion to (Picked unit) with 1 in stock and a max stock of 1
Else - Actions
-------- Give a 20% chance for item variation 5. --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
TempInt2 Less than or equal to 100
TempInt2 Greater than 80
Then - Actions
Neutral Building - Add Wand of Mana Stealing to (Picked unit) with 1 in stock and a max stock of 1
Neutral Building - Add Lesser Replenishment Potion to (Picked unit) with 1 in stock and a max stock of 1
Else - Actions
Unit Group - Remove (Picked unit) from TempBlackMarketItemPool .
Else - Actions
Bandit Market Item Pool
Events
Time - Every (Random real number between 220.00 and 300.00) seconds of game time
Conditions
Actions
Set Variable Set TempBlackMarketItemPool = (Units of type Black Market (Arcane Vault))
Unit Group - Pick every unit in TempBlackMarketItemPool and do (Actions)
Loop - Actions
Set Variable Set TempInt = (Random integer number between 1 and 100)
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
((Picked unit) is alive) Equal to True
TempInt Less than or equal to 60
Then - Actions
Set Variable Set TempInt2 = (Random integer number between 1 and 100)
Neutral Building - Remove Scroll of Regeneration from (Picked unit)
Neutral Building - Remove Spider Silk Broach from (Picked unit)
Neutral Building - Remove Healing Salve from (Picked unit)
Neutral Building - Remove Wand of Illusion from (Picked unit)
Neutral Building - Remove Scroll of Mana from (Picked unit)
Neutral Building - Remove Sentry Wards from (Picked unit)
Neutral Building - Remove Vampiric Potion from (Picked unit)
Neutral Building - Remove Lesser Replenishment Potion from (Picked unit)
Neutral Building - Remove Wand of Mana Stealing from (Picked unit)
-------- Give a 20% chance for item variation 1. --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
TempInt2 Less than or equal to 20
Then - Actions
Neutral Building - Add Scroll of Regeneration to (Picked unit) with 2 in stock and a max stock of 2
Neutral Building - Add Spider Silk Broach to (Picked unit) with 2 in stock and a max stock of 2
Else - Actions
-------- Give a 20% chance for item variation 2. --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
TempInt2 Less than or equal to 40
TempInt2 Greater than 20
Then - Actions
Neutral Building - Add Healing Salve to (Picked unit) with 2 in stock and a max stock of 2
Neutral Building - Add Wand of Illusion to (Picked unit) with 1 in stock and a max stock of 1
Else - Actions
-------- Give a 20% chance for item variation 3. --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
TempInt2 Less than or equal to 60
TempInt2 Greater than 40
Then - Actions
Neutral Building - Add Scroll of Mana to (Picked unit) with 2 in stock and a max stock of 2
Neutral Building - Add Sentry Wards to (Picked unit) with 1 in stock and a max stock of 1
Else - Actions
-------- Give a 20% chance for item variation 4. --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
TempInt2 Less than or equal to 80
TempInt2 Greater than 60
Then - Actions
Neutral Building - Add Vampiric Potion to (Picked unit) with 2 in stock and a max stock of 2
Neutral Building - Add Lesser Replenishment Potion to (Picked unit) with 1 in stock and a max stock of 1
Else - Actions
-------- Give a 20% chance for item variation 5. --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
TempInt2 Less than or equal to 100
TempInt2 Greater than 80
Then - Actions
Neutral Building - Add Wand of Mana Stealing to (Picked unit) with 1 in stock and a max stock of 1
Neutral Building - Add Lesser Replenishment Potion to (Picked unit) with 1 in stock and a max stock of 1
Else - Actions
Floating Text - Create floating text that reads New items have arrived! above (Picked unit) with Z offset 0 , using font size 10 , color ( 100.00 %, 100 %, 100.00 %), and 0 % transparency
Floating Text - Show (Last created floating text) for (All allies of (Owner of (Picked unit)).)
Floating Text - Hide (Last created floating text) for (All enemies of (Owner of (Picked unit)).)
Floating Text - Change (Last created floating text) : Disable permanence
Floating Text - Change the lifespan of (Last created floating text) to 5.00 seconds
Floating Text - Change the fading age of (Last created floating text) to 1.00 seconds
Floating Text - Set the velocity of (Last created floating text) to 64.00 towards 90 degrees
Else - Actions
Custom script: call DestroyGroup(udg_TempBlackMarketItemPool)
Remove Buildings Pool
Events
Unit - A unit Dies
Conditions
Or - Any (Conditions) are true
Conditions
(Unit-type of (Triggering unit)) Equal to Seedy Pub (Barracks)
(Unit-type of (Triggering unit)) Equal to Tower Ruins (Arcane Sanctum)
(Unit-type of (Triggering unit)) Equal to Black Market (Arcane Vault)
Actions
Set Variable Set TempUnitKilled = (Dying unit)
Unit Group - Remove TempUnitKilled from TempMercRecruitPubPool .
Unit Group - Remove TempUnitKilled from TempMercRecruitRuinsPool .
Unit Group - Remove TempUnitKilled from TempBlackMarketItemPool .
Lootbox
Events
Unit - A unit Uses an item
Conditions
(Item-type of (Item being manipulated)) Equal to Lootbox
Actions
Set Variable Set TempLoc = (Position of (Hero manipulating item))
Set Variable Set TempInt = (Random integer number between 1 and 100)
-------- Give a 70% chance for lvl1 permanent items. --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
TempInt Less than or equal to 70
Then - Actions
Item - Create (Random level 1.Permanent item-type) at TempLoc
Special Effect - Create a special effect at TempLoc using treasure_box_creative.mdx
Special Effect - Destroy (Last created special effect)
Special Effect - Create a special effect at TempLoc using Abilities\Spells\Items\ResourceItems\ResourceEffectTarget.mdl
Special Effect - Destroy (Last created special effect)
Special Effect - Create a special effect at TempLoc using UI\Feedback\GoldCredit\GoldCredit.mdl
Special Effect - Destroy (Last created special effect)
Else - Actions
-------- Give a 20% chance for lvl2 permanent items. --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
TempInt Less than or equal to 80
TempInt Greater than 70
Then - Actions
Item - Create (Random level 2.Permanent item-type) at TempLoc
Special Effect - Create a special effect at TempLoc using treasure_box_creative.mdx
Special Effect - Destroy (Last created special effect)
Special Effect - Create a special effect at TempLoc using Abilities\Spells\Items\ResourceItems\ResourceEffectTarget.mdl
Special Effect - Destroy (Last created special effect)
Special Effect - Create a special effect at TempLoc using UI\Feedback\GoldCredit\GoldCredit.mdl
Special Effect - Destroy (Last created special effect)
Else - Actions
-------- Give a 10% chance for lvl3 permanent items. --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
TempInt Less than or equal to 100
TempInt Greater than 80
Then - Actions
Item - Create (Random level 3.Permanent item-type) at TempLoc
Special Effect - Create a special effect at TempLoc using treasure_box_creative.mdx
Special Effect - Destroy (Last created special effect)
Special Effect - Create a special effect at TempLoc using Abilities\Spells\Items\ResourceItems\ResourceEffectTarget.mdl
Special Effect - Destroy (Last created special effect)
Special Effect - Create a special effect at TempLoc using UI\Feedback\GoldCredit\GoldCredit.mdl
Special Effect - Destroy (Last created special effect)
Else - Actions
225 cost
70% chance lvl1
20% chance lvl2
10% chance lvl3

Lvl1
Cloak of Shadows 100g
Gauntlets of Ogre Strength +3 100g
Mantle of Intelligence +3 100g
Slippers of Agility +3 100g

Lvl2
Boots of Speed 150g
Circlet of Nobility 175g
Claws of Attack +6 100g
Gloves of Haste 100g
Ring of Protection +2 150g
Staff of Teleportation 100g

Lvl3
Claws of Attack +9 400g
Pendant of Energy 400g
Periapt of Vitality 350g
Ring of Protection +3 400g
Ring of Regeneration 200g
Talisman of Evasion 400g
March of Time
Events
Unit - A unit Starts the effect of an ability
Conditions
(Ability being cast) Equal to March of Time (Roar)
Actions
Set Variable Set TempOwner = (Owner of (Casting unit))
Set Variable Set TempCasterUnit = (Casting unit)
Set Variable Set TempPoint = (Position of (Casting unit))
Item - Create March of Time at TempPoint
Unit - Create 1 . Dummy March of Time (Footman) for TempOwner at TempPoint facing Default building facing degrees
Custom script: call RemoveLocation(udg_TempPoint)
Set Variable Set TempDummyUnit = (Last created unit)
Unit - Add a 1.00 second Generic expiration timer to TempDummyUnit
Unit - Add Inventory (Hero) to TempDummyUnit
Unit - Order TempDummyUnit to Right-Click . (Last created item)
Black Flag
Events
Unit - A unit Dies
Conditions
Or - Any (Conditions) are true
Conditions
(Unit-type of (Killing unit)) Equal to Bandit Lord (Dark Knight)
(Unit-type of (Killing unit)) Equal to Dummy (Footman)
(Level of Black Flag (Critical Strike) for (Killing unit)) Greater than 0
(Owner of (Killing unit)) Not equal to (Owner of (Dying unit))
((Dying unit) is A structure) Equal to False
((Dying unit) is A Hero) Equal to False
((Dying unit) is A flying unit) Equal to False
((Dying unit) is Summoned) Equal to False
((Dying unit) is Mechanical) Equal to False
((Dying unit) is An Ancient) Equal to False
((Dying unit) is Ethereal) Equal to False
Actions
Set Variable Set TempInt = (Random integer number between 1 and 100)
Set Variable Set TempUnitKilled = (Dying unit)
Set Variable Set TempUnitKiller = (Killing unit)
Set Variable Set TempUnitType = (Unit-type of TempUnitKilled)
Set Variable Set TempLoc = (Position of TempUnitKilled)
Set Variable Set TempOwner = (Owner of TempUnitKiller)
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Level of Black Flag (Critical Strike) for TempUnitKiller) Equal to 1
TempInt Less than or equal to 15
Then - Actions
Unit - Create 1 . TempUnitType for TempOwner at TempLoc facing (Facing of TempUnitKilled) degrees
Unit - Set life of (Last created unit) to 50.00 %
Unit - Set mana of (Last created unit) to 0.00 %
Special Effect - Create a special effect attached to the overhead (Unexpected type: 'attachpoint') of (Last created unit) using Surrender(Buff).mdx
Special Effect - Destroy (Last created special effect)
Unit - Remove TempUnitKilled from the game
Custom script: call RemoveLocation(udg_TempLoc)
Skip remaining actions
Else - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Level of Black Flag (Critical Strike) for TempUnitKiller) Equal to 2
TempInt Less than or equal to 30
Then - Actions
Unit - Create 1 . TempUnitType for TempOwner at TempLoc facing (Facing of TempUnitKilled) degrees
Unit - Set life of (Last created unit) to 50.00 %
Unit - Set mana of (Last created unit) to 0.00 %
Special Effect - Create a special effect attached to the overhead (Unexpected type: 'attachpoint') of (Last created unit) using Surrender(Buff).mdx
Special Effect - Destroy (Last created special effect)
Unit - Remove TempUnitKilled from the game
Custom script: call RemoveLocation(udg_TempLoc)
Skip remaining actions
Else - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Level of Black Flag (Critical Strike) for TempUnitKiller) Equal to 3
TempInt Less than or equal to 45
Then - Actions
Unit - Create 1 . TempUnitType for TempOwner at TempLoc facing (Facing of TempUnitKilled) degrees
Unit - Set life of (Last created unit) to 50.00 %
Unit - Set mana of (Last created unit) to 0.00 %
Special Effect - Create a special effect attached to the overhead (Unexpected type: 'attachpoint') of (Last created unit) using Surrender(Buff).mdx
Special Effect - Destroy (Last created special effect)
Unit - Remove TempUnitKilled from the game
Custom script: call RemoveLocation(udg_TempLoc)
Else - Actions
Corpse Explosion Cancel Cast
Events
Unit - A unit Begins casting an ability
Conditions
(Ability being cast) Equal to Corpse Explosion (Channel)
(Number of units in (Units within 300.00 of (Target point of ability being cast) matching ((((Matching unit) is dead) Equal to True) and (((Matching unit) is A structure) Equal to False)).)) Equal to 0
Actions
Set Variable Set TempCasterUnit = (Casting unit)
Unit - Order TempCasterUnit to Stop .
Game - Display to (Player group((Owner of TempCasterUnit))) the text: Must target corpses.
Animation - Play TempCasterUnit 's stand animation
https://www.hiveworkshop.com/threads/2-common-corpse-spells.106768/
doom_sheep
Corpse Explosion Cast
Events
Unit - A unit Starts the effect of an ability
Conditions
(Ability being cast) Equal to Corpse Explosion (Channel)
Actions
Unit Group - Pick every unit in (Random 5 units from (Units within 300.00 of (Target point of ability being cast) matching ((((Matching unit) is A structure) Equal to False) and (((Matching unit) is dead) Equal to True)).)) and do (Actions)
Loop - Actions
Set Variable Set TempPickedUnit = (Picked unit)
Set Variable Set TempCasterUnit = (Casting unit)
Special Effect - Create a special effect at (Position of TempPickedUnit) using Objects\Spawnmodels\Undead\UndeadLargeDeathExplode\UndeadLargeDeathExplode.mdl
Special Effect - Destroy (Last created special effect)
Trigger - Run Corpse_Explosion_Damage <gen> (ignoring conditions)
Unit - Remove TempPickedUnit from the game
Corpse Explosion Damage
Events
Conditions
Actions
Set Variable Set TempUnitGroup = (Units within 200.00 of (Position of TempPickedUnit) matching ((((Matching unit) is Magic Immune) Equal to False) and ((((Matching unit) belongs to an enemy of (Owner of TempCasterUnit).) Equal to True) and (((Matching unit) is dead) Equal to False))).)
Unit Group - Pick every unit in TempUnitGroup and do (Actions)
Loop - Actions
Unit - Cause TempCasterUnit to damage (Picked unit) , dealing (40.00 x (Real((Level of Corpse Explosion (Channel) for TempCasterUnit)))) damage of attack type Spells and damage type Normal
Custom script: call DestroyGroup(udg_TempUnitGroup)
Dark Portal
Events
Unit - A unit Spawns a summoned unit
Conditions
(Unit-type of (Summoning unit)) Equal to Dark Wizard (Archmage)
Actions
Set Variable Set TempUnit = (Summoned unit)
Unit - Add a 120.00 second Generic expiration timer to TempUnit
Unit - Remove classification of Summoned from TempUnit
Cornered Animal Learn
Events
Unit - A unit Learns a skill
Conditions
(Learned Hero Skill) Equal to Cornered Animal (Exhume Corpses)
Actions
Unit - Add Hide Temp Enforcer's Bonus Ultimate (Spell Book) to (Learning Hero)
Cornered Animal
Events
Time - Every 1.00 seconds of game time
Conditions
Actions
Set Variable Set TempUnitGroup = (Units of type Enforcer (Paladin))
Unit Group - Pick every unit in TempUnitGroup and do (Actions)
Loop - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Level of Cornered Animal (Exhume Corpses) for (Picked unit)) Greater than 0
(Level of Cornered Animal Aura (Command Aura) for (Picked unit)) Greater than 1
(Percentage life of (Picked unit)) Greater than 80.00
Then - Actions
Unit - Set level of Cornered Animal Aura (Command Aura) for (Picked unit) to 1
Unit - Remove MISSING STRING BOac (Command Aura) buff from (Picked unit)
Else - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Level of Cornered Animal (Exhume Corpses) for (Picked unit)) Greater than 0
(Level of Cornered Animal Aura (Command Aura) for (Picked unit)) Not equal to 2
(Percentage life of (Picked unit)) Less than or equal to 80.00
(Percentage life of (Picked unit)) Greater than 60.00
Then - Actions
Unit - Set level of Cornered Animal Aura (Command Aura) for (Picked unit) to 2
Unit - Remove MISSING STRING BOac (Command Aura) buff from (Picked unit)
Else - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Level of Cornered Animal (Exhume Corpses) for (Picked unit)) Greater than 0
(Level of Cornered Animal Aura (Command Aura) for (Picked unit)) Not equal to 3
(Percentage life of (Picked unit)) Less than or equal to 60.00
(Percentage life of (Picked unit)) Greater than 40.00
Then - Actions
Unit - Set level of Cornered Animal Aura (Command Aura) for (Picked unit) to 3
Unit - Remove MISSING STRING BOac (Command Aura) buff from (Picked unit)
Else - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Level of Cornered Animal (Exhume Corpses) for (Picked unit)) Greater than 0
(Level of Cornered Animal Aura (Command Aura) for (Picked unit)) Not equal to 4
(Percentage life of (Picked unit)) Less than or equal to 40.00
(Percentage life of (Picked unit)) Greater than 20.00
Then - Actions
Unit - Set level of Cornered Animal Aura (Command Aura) for (Picked unit) to 4
Unit - Remove MISSING STRING BOac (Command Aura) buff from (Picked unit)
Else - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Level of Cornered Animal (Exhume Corpses) for (Picked unit)) Greater than 0
(Level of Cornered Animal Aura (Command Aura) for (Picked unit)) Not equal to 5
(Percentage life of (Picked unit)) Less than or equal to 20.00
Then - Actions
Unit - Set level of Cornered Animal Aura (Command Aura) for (Picked unit) to 5
Unit - Remove MISSING STRING BOac (Command Aura) buff from (Picked unit)
Else - Actions
Custom script: call DestroyGroup(udg_TempUnitGroup)
https://www.hiveworkshop.com/threads/single-target-spell-for-multiple-units.242153/
by Rheiko

Sets range depending on lvl
Mass Invisibility
Events
Unit - A unit Starts the effect of an ability
Conditions
(Ability being cast) Equal to Stealth March (Channel)
Actions
Set Variable Set TempCasterUnit = (Triggering unit)
Set Variable Set TempOwner = (Triggering player)
Set Variable Set TempPoint = (Position of TempCasterUnit)
Unit - Create 1 . Dummy (Footman) for TempOwner at TempPoint facing Default building facing degrees
Set Variable Set TempDummyUnit = (Last created unit)
Unit - Add Mass Invisibility Dummy (Invisibility) to TempDummyUnit
Unit - Set level of Mass Invisibility Dummy (Invisibility) for TempDummyUnit to (Level of Stealth March (Channel) for TempCasterUnit)
Unit - Add a 1.00 second Generic expiration timer to TempDummyUnit
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Level of Stealth March (Channel) for TempCasterUnit) Equal to 1
Then - Actions
Set Variable Set TempUnitGroup = (Units within 260.00 of TempPoint.)
Else - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Level of Stealth March (Channel) for TempCasterUnit) Equal to 2
(Level of Stealth March (Channel) for TempCasterUnit) Not equal to 3
Then - Actions
Set Variable Set TempUnitGroup = (Units within 360.00 of TempPoint.)
Else - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Level of Stealth March (Channel) for TempCasterUnit) Equal to 3
(Level of Stealth March (Channel) for TempCasterUnit) Not equal to 2
Then - Actions
Set Variable Set TempUnitGroup = (Units within 460.00 of TempPoint.)
Else - Actions
-------- --------
-------- --------
Unit Group - Pick every unit in TempUnitGroup and do (Actions)
Loop - Actions
Set Variable Set TempPickedUnit = (Picked unit)
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(TempPickedUnit belongs to an enemy of TempOwner.) Equal to False
(TempPickedUnit belongs to an enemy of Neutral Passive.) Equal to False
(Owner of TempPickedUnit) Not equal to Neutral Passive
(TempPickedUnit is A structure) Not equal to True
Then - Actions
Unit - Order TempDummyUnit to Human Sorceress - Invisibility . TempPickedUnit
Else - Actions
Custom script: call RemoveLocation(udg_TempPoint)
Custom script: call DestroyGroup(udg_TempUnitGroup)
Entrap
Events
Unit - A unit Starts the effect of an ability
Conditions
(Ability being cast) Equal to Entrap (Chain Lightning)
Actions
Set Variable Set TempCasterUnit = (Triggering unit)
Set Variable Set TempUnit = (Target unit of ability being cast)
Set Variable Set TempOwner = (Triggering player)
Set Variable Set TempPoint = (Position of TempCasterUnit)
Unit - Create 1 . Assassin (Assassin) for TempOwner at TempPoint facing (Facing of TempCasterUnit) degrees
Set Variable Set TempDummyUnit = (Last created unit)
Unit - Add Entrap (Aerial Shackles) to TempDummyUnit
Unit - Set level of Entrap (Aerial Shackles) for TempDummyUnit to (Level of Entrap (Chain Lightning) for TempCasterUnit)
Unit - Order TempDummyUnit to Human Dragonhawk Rider - Aerial Shackles . TempUnit
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Level of Entrap (Aerial Shackles) for TempDummyUnit) Equal to 1
Then - Actions
Unit - Add a 15.00 second Generic expiration timer to TempDummyUnit
Else - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Level of Entrap (Aerial Shackles) for TempDummyUnit) Equal to 2
Then - Actions
Unit - Add a 30.00 second Generic expiration timer to TempDummyUnit
Else - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Level of Entrap (Aerial Shackles) for TempDummyUnit) Equal to 3
Then - Actions
Unit - Add a 45.00 second Generic expiration timer to TempDummyUnit
Else - Actions
Custom script: call RemoveLocation(udg_TempPoint)
Entrap Cancelled
Events
Unit - A unit Stops casting an ability
Conditions
(Unit-type of (Casting unit)) Equal to Assassin (Assassin)
Actions
Unit - Remove (Casting unit) from the game
Debug Hidden Spellbooks Revive
Events
Unit - A unit Finishes reviving
Conditions
Or - Any (Conditions) are true
Conditions
(Level of Cornered Animal Aura (Command Aura) for (Reviving Hero)) Greater than 1
Actions
Set Variable Set TempUnit = (Reviving Hero)
Unit - Set level of Cornered Animal Aura (Command Aura) for TempUnit to 1
Unit - Remove MISSING STRING BOac (Command Aura) buff from TempUnit
Debug Hidden Spellbooks Retrain
Events
Unit - A unit Uses an item
Conditions
(Item-type of (Item being manipulated)) Equal to Tome of Retraining
Or - Any (Conditions) are true
Conditions
(Unit-type of (Hero manipulating item)) Equal to Enforcer (Paladin)
Actions
Set Variable Set TempUnit = (Hero manipulating item)
Unit - Remove Hide Temp Enforcer's Bonus Ultimate (Spell Book) from TempUnit
Unit - Remove MISSING STRING BOac (Command Aura) buff from TempUnit
//TESH.scrollpos=120
//TESH.alwaysfold=0
////////////////////////////////////////////////////////////////////////////////////
//
//  Physical Damage Detection Engine GUI v 1.3.0.0
//  ----------------------------------------------
//  By looking_for_help aka eey
//
//  This system is able to detect, modify and deal damage. It can differentiate
//  between physical and spell damage, as well as block, reduce or increase the
//  applied damage to a desired value. You can also allocate damage events from
//  running damage events.
//
//  This is the GUI version of the system, meaning that you can use this with the
//  standard editor and basically without any knowledge of JASS.
//
////////////////////////////////////////////////////////////////////////////////////
//
//  Implementation
//  --------------
//  1.  Create all variables that this system uses (compare the variable editor).
//      You don't have to set them to specific values, they get initialized
//      automatically by the system so just create them.
//  2.  Copy this trigger to your map. You can then add damage handlers by using
//      the event "value of real variable becomes equal to 1" with the variable
//      udg_PDD_damageEventTrigger. Compare the OnDamage trigger for an example usage.
//  3.  Copy the two custom abilities to your map and make sure they have the
//      correct ID. You can specify the ID in the function InitGlobalVariables
//      above.
//  4.  Go to the locust swarm ability and invert its damage return portion
//      from (default) 0.75 to -0.75.
//  5.  Remove the spell damage reduction ability from the spell damage reduction
//      items you use (runed bracers). You can configure the resistance of this
//      item in the InitGlobalVariables function, modifying the global variable
//      udg_PDD_BRACERS_SPELL_DMG_RED.
//
////////////////////////////////////////////////////////////////////////////////////
//
//  Important Notes
//  ---------------
//  1.  Life Drain does not work with this system, so you should use a triggered
//      version of this spell if you want to use it.
//  2.  Same for Finger of Death, if you want to use this spell bug free with this
//      system, you should use a triggered version of it.
//  3.  If you use damage modifiers by setting the damage amount variable, you have
//      to use GetUnitLife, GetUnitMaxLife and SetUnitLife instead of GetWidgetLife,
//      GetUnitState for UNIT_STATE_MAX_LIFE and SetWidgetLife in your whole map to
//      ensure there occure no bugs.
//  4.  The boolean udg_PDD_SPELL_RESIST_AUTO_DETECT is only neccessary set to true
//      if you want to use a customized damage table with spell damage resistance
//      above 100%. If this is not the case, it should be set to false, as the
//      system is faster then and still works correct.
//  5.  As already mentioned you can't use the spell reduction ability when using this
//      system (runed bracers and elunes grace). If you want to use them, you can
//      trigger them by using the damage modifiers. Runed bracers is already considered
//      in this system, so you don't have to code it.
//
////////////////////////////////////////////////////////////////////////////////////
//  
//  System API
//  ----------
//  real damageEventTrigger
//      - Use the event "value of real variable becomes equal to 1" to detect a damage
//        event. In this event you can use the following API. Compare the OnDamage
//        trigger for an example usage.
//
//  unit target
//      - In this global unit variable, the damaged unit is saved. Don't write any-
//        thing into this variable, use it as readonly.
//
//  unit source
//      - In this global unit variable, the damage source is saved. Don't write any-
//        thing into this variable, use it as readonly.
//
//  real amount
//      - In this global real variable, the amount of damage is saved. This amount
//        can be modified by simply setting it to the desired amount that should be
//        applied to the target. Set the amount to 0.0 to block the damage completly.
//        Negative values will result in heal.
//
//  integer damageType
//      - In this global integer variable, the damage type of the current damage is
//        saved. Use it to differentiate between physical, spell and code damage. The
//        variable can takes the values PHYSICAL == 0, SPELL == 1 and CODE == 2. Don't
//        write anything into this variable, use it as readonly.        
//
//  function GetUnitLife takes unit u returns real
//      - Use this function instead of the GetWidgetLife native. It ensures that you
//        get the correct health value, even when damage modifiers are applied. If
//        you don't use damage modifiers at all, you don't need this function.
//
//  function GetUnitMaxLife takes unit u returns real
//      - Use this function instead of the GetUnitState(u, UNIT_STATE_MAX_LIFE) native.
//        It will return the correct value, even when damage modifiers are applied. If
//        you don't use damage modifiers at all, you don't need this function.
//
//  function SetUnitLife takes unit u, real newLife returns nothing
//      - Use this function instead of the SetWidgetLife(u, newLife) native if you use
//        damage modifiers in your map. Same rules as for the GetUnitMaxLife and the
//        GetUnitMaxLife functions.
//
//  function UnitDamageTargetEx takes unit localSource, unit localTarget, real localAmount, boolean attack, boolean ranged, attacktype localAttackType, damagetype localDamageType, weapontype localWeaponType returns boolean
//      - Use this function to deal damage from a running damage event. It works exactly
//        the same as the native UnitDamageTarget but is recursion safe so that you can
//        realize damage reflection for example with this. Don't ever use this function
//        outside of an onDamage event. 
//
//  function AddDamageHandler takes code damageHandler returns nothing
//      - Allows you to add a damage handler function to the system. This is not
//        required for GUI users, only for vanilla JASS users. GUI users should
//        use the real variable damageEventTrigger to add damage handlers to this
//        system as explained above.
//
//  function RemoveDamageHandler takes code damageHandler returns nothing
//      - Allows you to remove a damage handler function from the system dynamic-
//        ally. If you added the same handler function multiple times to the sys-
//        tem, this function will remove all of these equal functions. This is not
//        required for GUI users, only for vanilla JASS users.
//
//////////////////////////////////////////////////////////////////////////////////


//////////////////////////////////////////////////////////////////////////////////
//  Configurable globals
//////////////////////////////////////////////////////////////////////////////////

function InitGlobalVariables takes nothing returns nothing
    // Put here the correct ability IDs
    set udg_PDD_DAMAGE_TYPE_DETECTOR = 'A00P'
    set udg_PDD_SET_MAX_LIFE = 'A00O'
   
    // Here you can configure some stuff, read the documentation for further info
    set udg_PDD_SPELL_DMG_REDUCTION_ITEM = 'brac'
    set udg_PDD_SPELL_RESIST_AUTO_DETECT = false
    set udg_PDD_ETHEREAL_DAMAGE_FACTOR = 1.66
    set udg_PDD_BRACERS_SPELL_DMG_RED = 0.33
    set udg_PDD_TRIGGER_CLEANUP_PERIOD = 60.0
endfunction

//////////////////////////////////////////////////////////////////////////////////
//  End of configurable globals
//////////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////////
//  User functions
//////////////////////////////////////////////////////////////////////////////////

function AddDamageHandler takes code func returns nothing
    local integer id = GetHandleId(Condition(func))
    local integer index = 0
   
    // Loop to manage equal damage handlers
    loop
        exitwhen ( LoadTriggerConditionHandle(udg_PDD_h, id, index) == null )
        set index = index + 1
    endloop
    // Store the desired damage handler function
    call SaveTriggerConditionHandle(udg_PDD_h, id, index, TriggerAddCondition(udg_PDD_damageHandler, Filter(func)))
endfunction

function RemoveDamageHandler takes code func returns nothing
    local integer id = GetHandleId(Condition(func))
    local integer index = 0
   
    // Loop through all equal damage handlers
    loop
        exitwhen ( LoadTriggerConditionHandle(udg_PDD_h, id, index) == null )
        call TriggerRemoveCondition(udg_PDD_damageHandler, LoadTriggerConditionHandle(udg_PDD_h, id, index))
        set index = index + 1
    endloop
   
    // Clean things up
    call FlushChildHashtable(udg_PDD_h, id)
endfunction

function GetUnitLife takes unit u returns real
    local boolean duringModification
    local integer uId = GetHandleId(u)
    local real health
    local real storedHealth = LoadReal(udg_PDD_h, uId, 2)
    local real storedDamage = LoadReal(udg_PDD_h, uId, 1)
   
    // Check if the unit is being rescued from damage
    set duringModification = GetUnitAbilityLevel(u, udg_PDD_SET_MAX_LIFE) > 0
    if duringModification then
        call UnitRemoveAbility(u, udg_PDD_SET_MAX_LIFE)
    endif

    // Get the correct health value of the unit
    if storedHealth != 0.0 then
        set health = storedHealth - storedDamage
    else
        set health = GetWidgetLife(u) - storedDamage
    endif

    // Restore the rescue ability and return
    if duringModification then
        call UnitAddAbility(u, udg_PDD_SET_MAX_LIFE)
    endif
    return health
endfunction

function GetUnitMaxLife takes unit u returns real
    local real maxHealth
   
    // Check if the unit is being rescued from damage
    if GetUnitAbilityLevel(u, udg_PDD_SET_MAX_LIFE) > 0 then
        call UnitRemoveAbility(u, udg_PDD_SET_MAX_LIFE)
        set maxHealth = GetUnitState(u, UNIT_STATE_MAX_LIFE)
        call UnitAddAbility(u, udg_PDD_SET_MAX_LIFE)
        return maxHealth
    endif
   
    // If the unit isn't being rescued, use the standard native
    return GetUnitState(u, UNIT_STATE_MAX_LIFE)
endfunction

function SetUnitLife takes unit u, real newLife returns nothing
    local integer targetId
    local integer oldTimerId
    local real oldHealth

    // Check if the unit is being rescued from damage
    if GetUnitAbilityLevel(u, udg_PDD_SET_MAX_LIFE) > 0 then
        call UnitRemoveAbility(u, udg_PDD_SET_MAX_LIFE)
        call SetWidgetLife(u, newLife)
        call UnitAddAbility(u, udg_PDD_SET_MAX_LIFE)
       
        // Get the unit specific timer information
        set targetId = GetHandleId(u)
        set oldHealth = LoadReal(udg_PDD_h, targetId, 0)
       
        // Update the unit specific timer information
        if oldHealth != 0.0 then
            set oldTimerId = LoadInteger(udg_PDD_h, targetId, 3)
            call SaveReal(udg_PDD_h, targetId, 2, newLife)
            call SaveReal(udg_PDD_h, targetId, 0, newLife)
            call SaveReal(udg_PDD_h, oldTimerId, 4, newLife)
        endif
        return
    endif
   
    // If the unit isn't being rescued, use the standard native
    call SetWidgetLife(u, newLife)
endfunction

function UnitDamageTargetEx takes unit localSource, unit localTarget, real localAmount, boolean attack, boolean ranged, attacktype localAttackType, damagetype localDamageType, weapontype localWeaponType returns boolean
    // Avoid infinite loop due to recursion
    if udg_PDD_damageType == udg_PDD_CODE then
        return false
    endif
   
    // Avoid allocating attacks on units that are about to be killed
    if ( localTarget == udg_PDD_target and GetUnitLife(localTarget) - udg_PDD_amount < udg_PDD_UNIT_MIN_LIFE ) then
        return false
    endif
   
    // Store all damage parameters determined by the user
    set udg_PDD_allocatedAttacks = udg_PDD_allocatedAttacks + 1
    call SaveUnitHandle(udg_PDD_h, udg_PDD_allocatedAttacks, 0, localSource)
    call SaveUnitHandle(udg_PDD_h, udg_PDD_allocatedAttacks, 1, localTarget)
    call SaveReal(udg_PDD_h, udg_PDD_allocatedAttacks, 2, localAmount)
    call SaveBoolean(udg_PDD_h, udg_PDD_allocatedAttacks, 3, attack)
    call SaveBoolean(udg_PDD_h, udg_PDD_allocatedAttacks, 4, ranged)
    call SaveInteger(udg_PDD_h, udg_PDD_allocatedAttacks, 5, GetHandleId(localAttackType))
    call SaveInteger(udg_PDD_h, udg_PDD_allocatedAttacks, 6, GetHandleId(localDamageType))
    call SaveInteger(udg_PDD_h, udg_PDD_allocatedAttacks, 7, GetHandleId(localWeaponType))

    // Return true if the damage was allocated
    return true
endfunction

////////////////////////////////////////////////////////////////////////////////////
//  Sub functions
////////////////////////////////////////////////////////////////////////////////////

function DealFixDamage takes unit source, unit target, real pureAmount returns nothing
    local real MAX_DAMAGE = 1000000.0
    local real beforeHitpoints
    local real newHitpoints

    // Ensure the amount is positive
    if pureAmount < 0 then
        set pureAmount = -pureAmount
    endif

    // Save the targets hitpoints
    set beforeHitpoints = GetWidgetLife(target)
    set newHitpoints = beforeHitpoints - pureAmount

    // Apply the desired, fixed amount
    if newHitpoints >= udg_PDD_UNIT_MIN_LIFE then
        call SetUnitState(target, UNIT_STATE_LIFE, newHitpoints)
    else
        if ( IsUnitType(target, UNIT_TYPE_ETHEREAL) == false ) then
            call SetWidgetLife(target, 1.0)
            call UnitDamageTarget(source, target, MAX_DAMAGE, true, false, udg_PDD_ATTACK_TYPE_UNIVERSAL, DAMAGE_TYPE_UNIVERSAL, null)
            call SetWidgetLife(target, 0.0)
        else
            call UnitRemoveAbility(target, udg_PDD_DAMAGE_TYPE_DETECTOR)
            call SetWidgetLife(target, 1.0)
            call UnitDamageTarget(source, target, MAX_DAMAGE, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_UNIVERSAL, null)
            call SetWidgetLife(target, 0.0)
        endif
    endif
endfunction

function GetUnitSpellResistance takes unit u returns real
    local real originalHP
    local real beforeHP
    local real afterHP
    local real resistance
    local real DUMMY_DAMAGE = 100
    local real DUMMY_FACTOR = 0.01
   
    // Deal spell damage in order to get the units resistance
    call UnitRemoveAbility(udg_PDD_target, udg_PDD_DAMAGE_TYPE_DETECTOR)
    set originalHP = GetWidgetLife(udg_PDD_target)
    call UnitAddAbility(udg_PDD_target, udg_PDD_SET_MAX_LIFE)
    call SetWidgetLife(udg_PDD_target, 20000.0)
    set beforeHP = GetWidgetLife(udg_PDD_target)
    call DisableTrigger(udg_PDD_damageEvent)
    call UnitDamageTarget(udg_PDD_source, udg_PDD_target, DUMMY_DAMAGE, true, false, null, DAMAGE_TYPE_UNIVERSAL, null)
    call EnableTrigger(udg_PDD_damageEvent)
    set afterHP = GetWidgetLife(udg_PDD_target)
    call UnitRemoveAbility(udg_PDD_target, udg_PDD_SET_MAX_LIFE)
    call SetWidgetLife(udg_PDD_target, originalHP)
    call UnitAddAbility(udg_PDD_target, udg_PDD_DAMAGE_TYPE_DETECTOR)
    call UnitMakeAbilityPermanent(udg_PDD_target, true, udg_PDD_DAMAGE_TYPE_DETECTOR)

    // Calculate this resistance
    set resistance = DUMMY_FACTOR*(beforeHP - afterHP)

    // If the resistance was greater than 100%, return it
    if resistance > 1.0 then
        return resistance
    else
        return 1.0
    endif
endfunction

function UnitHasItemOfType takes unit u, integer itemId returns integer
    local integer index = 0
    local item indexItem

    // Check if the target has a spell damage reducing item
    loop
        set indexItem = UnitItemInSlot(u, index)
        if ( indexItem != null ) and ( GetItemTypeId(indexItem) == itemId ) then
			set indexItem = null
            return index + 1
        endif

        set index = index + 1
        exitwhen index >= bj_MAX_INVENTORY
    endloop
	set indexItem = null
    return 0
endfunction


////////////////////////////////////////////////////////////////////////////////////
//  Damage Engine
////////////////////////////////////////////////////////////////////////////////////

function AfterDamage takes nothing returns nothing
    local timer time = GetExpiredTimer()
    local integer id = GetHandleId(time)
    local unit localSource = LoadUnitHandle(udg_PDD_h, id, 0)
    local unit localTarget = LoadUnitHandle(udg_PDD_h, id, 1)
    local real pureAmount = LoadReal(udg_PDD_h, id, 2)
    local real amount = LoadReal(udg_PDD_h, id, 3)
    local real originalHealth = LoadReal(udg_PDD_h, id, 4)

    // If the damage was modified, restore units health
    if originalHealth != 0.0 then
        call UnitRemoveAbility(localTarget, udg_PDD_SET_MAX_LIFE)
        call SetWidgetLife(localTarget, originalHealth)
    endif

    // Apply the desired amount of damage
    if amount > 0.0 then
        call DisableTrigger(udg_PDD_damageEvent)
        call DealFixDamage(localSource, localTarget, amount)
        call EnableTrigger(udg_PDD_damageEvent)
    else
        call SetWidgetLife(localTarget, originalHealth - amount)
    endif
   
    // Clean things up
    call FlushChildHashtable(udg_PDD_h, id)
    call FlushChildHashtable(udg_PDD_h, GetHandleId(localTarget))
    call DestroyTimer(time)
    set time = null
    set localSource = null
    set localTarget = null
endfunction

function DamageEngine takes nothing returns nothing
    local timer time
    local integer id
    local real health
    local real rawAmount
    local real originalHealth
    local integer targetId
    local integer oldTimerId
    local real oldHealth
    local real oldOriginalHealth
    local real oldAmount
    
    set rawAmount = GetEventDamage()
    if rawAmount == 0.0 then
        return
    endif
    set udg_PDD_source = GetEventDamageSource()
    set udg_PDD_target = GetTriggerUnit()
   
    // Determine the damage type
    if rawAmount > 0.0 then
        if udg_PDD_damageType != udg_PDD_CODE then
            set udg_PDD_damageType = udg_PDD_PHYSICAL
        endif
        set udg_PDD_amount = rawAmount
    else
        if udg_PDD_damageType != udg_PDD_CODE then
            set udg_PDD_damageType = udg_PDD_SPELL
        endif
        set udg_PDD_amount = -rawAmount
    endif
   
    // Register spell reduction above 100%
    if udg_PDD_SPELL_RESIST_AUTO_DETECT then
        set udg_PDD_amount = GetUnitSpellResistance(udg_PDD_target)*udg_PDD_amount
    else
        if ( IsUnitType(udg_PDD_target, UNIT_TYPE_ETHEREAL) and IsUnitEnemy(udg_PDD_target, GetOwningPlayer(udg_PDD_source)) and rawAmount < 0.0 ) then
            set udg_PDD_amount = udg_PDD_ETHEREAL_DAMAGE_FACTOR*udg_PDD_amount
        endif
    endif
   
    // Register spell damage reducing items like runed bracers
    if ( IsUnitType(udg_PDD_target, UNIT_TYPE_HERO) and UnitHasItemOfType(udg_PDD_target, udg_PDD_SPELL_DMG_REDUCTION_ITEM) > 0 ) and rawAmount < 0.0 then
        set udg_PDD_amount = (1 - udg_PDD_BRACERS_SPELL_DMG_RED)*udg_PDD_amount
    endif
   
    // Save health and damage variables
    if udg_PDD_damageType != udg_PDD_CODE then
        call UnitRemoveAbility(udg_PDD_target, udg_PDD_SET_MAX_LIFE)
    endif
    set udg_PDD_pureAmount = udg_PDD_amount
    set originalHealth = GetWidgetLife(udg_PDD_target)
    set oldTimerId = 0
   
    // Call damage handlers
	set udg_PDD_damageEventTrigger = 0.0
    set udg_PDD_damageEventTrigger = 1.0
    set udg_PDD_damageEventTrigger = 0.0

    // If the damage was modified, apply the rescue ability
    if udg_PDD_amount != udg_PDD_pureAmount then
        call UnitAddAbility(udg_PDD_target, udg_PDD_SET_MAX_LIFE)
        call SetWidgetLife(udg_PDD_target, GetWidgetLife(udg_PDD_target) + udg_PDD_pureAmount)
    endif
   
    // Check if a previous timer didn't yet expire
    set targetId = GetHandleId(udg_PDD_target)
    set oldHealth = LoadReal(udg_PDD_h, targetId, 0)
   
    // If this is the case, update the timer information
    if oldHealth != 0.0 then
        set oldTimerId = LoadInteger(udg_PDD_h, targetId, 3)
        set oldOriginalHealth = LoadReal(udg_PDD_h, targetId, 2)
        set oldAmount = LoadReal(udg_PDD_h, targetId, 1)
        set originalHealth = oldOriginalHealth - oldAmount
        call SaveReal(udg_PDD_h, oldTimerId, 4, oldOriginalHealth)
    endif

    // Call after damage event if damage was spell, modified, code or parallel
    if ( rawAmount < 0.0 or udg_PDD_pureAmount != udg_PDD_amount or oldTimerId != 0 or udg_PDD_allocatedAttacks > 0 ) then
        set time = CreateTimer()
        set id = GetHandleId(time)
       
        // Save handles for after damage event
        call SaveUnitHandle(udg_PDD_h, id, 0, udg_PDD_source)
        call SaveUnitHandle(udg_PDD_h, id, 1, udg_PDD_target)
        call SaveReal(udg_PDD_h, id, 2, udg_PDD_pureAmount)
        call SaveReal(udg_PDD_h, id, 3, udg_PDD_amount)
        call SaveReal(udg_PDD_h, id, 4, originalHealth)

        // Save this extra to manage parallel damage instances
        call SaveReal(udg_PDD_h, targetId, 0, GetWidgetLife(udg_PDD_target))
        call SaveReal(udg_PDD_h, targetId, 1, udg_PDD_amount)
        call SaveReal(udg_PDD_h, targetId, 2, originalHealth)
        call SaveInteger(udg_PDD_h, targetId, 3, id)

        // Avoid healing of negative spell damage
        if rawAmount < 0.0 then
            call DisableTrigger(udg_PDD_damageEvent)
            call DealFixDamage(udg_PDD_source, udg_PDD_target, -rawAmount)
            if ( originalHealth - udg_PDD_amount < udg_PDD_UNIT_MIN_LIFE ) then
                call UnitRemoveAbility(udg_PDD_target, udg_PDD_SET_MAX_LIFE)
                call DealFixDamage(udg_PDD_source, udg_PDD_target, udg_PDD_amount)
            endif
            call EnableTrigger(udg_PDD_damageEvent)
        endif
       
        // Guarantee unit exploding
        if originalHealth - udg_PDD_amount < udg_PDD_UNIT_MIN_LIFE then
            if rawAmount > 0.0 then
                call UnitRemoveAbility(udg_PDD_target, udg_PDD_SET_MAX_LIFE)
                call SetWidgetLife(udg_PDD_target, udg_PDD_UNIT_MIN_LIFE)
            endif
        endif
       
        // Start the after damage event
        call TimerStart(time, 0.0, false, function AfterDamage)
    endif

    // Handle allocated attacks from UnitDamageTargetEx
    if udg_PDD_totalAllocs == 0 then
        set udg_PDD_totalAllocs = udg_PDD_allocatedAttacks
    endif
    if udg_PDD_allocatedAttacks > 0 then
        set udg_PDD_allocatedAttacks = udg_PDD_allocatedAttacks - 1
        set udg_PDD_allocCounter = udg_PDD_allocCounter + 1
        call TriggerEvaluate(udg_PDD_runAllocatedAttacks)
    endif

    // Reset all required variables
    set udg_PDD_damageType = -1
    set udg_PDD_totalAllocs = 0
    set udg_PDD_allocCounter = -1
endfunction


////////////////////////////////////////////////////////////////////////////////////
//  Initialization
////////////////////////////////////////////////////////////////////////////////////

function RestoreTriggers takes nothing returns nothing
    local unit enumUnit = GetEnumUnit()

    // Re-register units that are alive
    if GetUnitTypeId(enumUnit) != 0 then
        call TriggerRegisterUnitEvent(udg_PDD_damageEvent, enumUnit, EVENT_UNIT_DAMAGED)
    endif
    set enumUnit = null
endfunction

function ClearMemory_Actions takes nothing returns nothing
    local group g = CreateGroup()
    local code c = function DamageEngine
   
    // Reset the damage event
    call GroupEnumUnitsInRect(g, GetWorldBounds(), null)
    call ResetTrigger(udg_PDD_damageEvent)
    call DestroyTrigger(udg_PDD_damageEvent)
    set udg_PDD_damageEvent = null
   
    // Rebuild it then
    set udg_PDD_damageEvent = CreateTrigger()
    call TriggerAddCondition(udg_PDD_damageEvent, Filter(c))
    call ForGroup(g, function RestoreTriggers)
   
    // Clean things up
    call DestroyGroup(g)
    set g = null
    set c = null
endfunction

function MapInit takes nothing returns nothing
    local unit enumUnit = GetEnumUnit()

    // Register units on map initialization
    call UnitAddAbility(enumUnit, udg_PDD_DAMAGE_TYPE_DETECTOR)
    call UnitMakeAbilityPermanent(enumUnit, true, udg_PDD_DAMAGE_TYPE_DETECTOR)
    call TriggerRegisterUnitEvent(udg_PDD_damageEvent, enumUnit, EVENT_UNIT_DAMAGED)
    set enumUnit = null
endfunction

function UnitEntersMap takes nothing returns nothing
    local unit triggerUnit = GetTriggerUnit()

    // Register units that enter the map
    if ( GetUnitAbilityLevel(triggerUnit, udg_PDD_DAMAGE_TYPE_DETECTOR) < 1 ) then
        call UnitAddAbility(triggerUnit, udg_PDD_DAMAGE_TYPE_DETECTOR)
        call UnitMakeAbilityPermanent(triggerUnit, true, udg_PDD_DAMAGE_TYPE_DETECTOR)
        call TriggerRegisterUnitEvent(udg_PDD_damageEvent, triggerUnit, EVENT_UNIT_DAMAGED)
    endif
    set triggerUnit = null
endfunction

function RunAllocatedAttacks takes nothing returns nothing
    local integer localAllocAttacks = udg_PDD_allocatedAttacks + 1

    // Calculate the correct sequence of allocated attacks
    set localAllocAttacks = localAllocAttacks - udg_PDD_totalAllocs + 1 + 2*udg_PDD_allocCounter
   
    // Deal code damage if the unit isn't exploding
    set udg_PDD_damageType = udg_PDD_CODE
    if GetUnitLife(LoadUnitHandle(udg_PDD_h, localAllocAttacks, 1)) >= udg_PDD_UNIT_MIN_LIFE then
        call UnitDamageTarget(LoadUnitHandle(udg_PDD_h, localAllocAttacks, 0), LoadUnitHandle(udg_PDD_h, localAllocAttacks, 1), LoadReal(udg_PDD_h, localAllocAttacks, 2), LoadBoolean(udg_PDD_h, localAllocAttacks, 3), LoadBoolean(udg_PDD_h, localAllocAttacks, 4), ConvertAttackType(LoadInteger(udg_PDD_h, localAllocAttacks, 5)), ConvertDamageType(LoadInteger(udg_PDD_h, localAllocAttacks, 6)), ConvertWeaponType(LoadInteger(udg_PDD_h, localAllocAttacks, 7)))
    else
        call FlushChildHashtable(udg_PDD_h, localAllocAttacks - 1)
    endif
   
    // Clean things up
    call FlushChildHashtable(udg_PDD_h, localAllocAttacks)
endfunction

function InitTrig_DamageEvent takes nothing returns nothing
    local group g = CreateGroup()
    local region r = CreateRegion()
    local trigger UnitEnters = CreateTrigger()
    local trigger ClearMemory = CreateTrigger()
    local code cDamageEngine = function DamageEngine
    local code cUnitEnters = function UnitEntersMap
    local code cClearMemory = function ClearMemory_Actions
    local code cRunAllocatedAttacks = function RunAllocatedAttacks
   
    // Initialize global variables
    set udg_PDD_h = InitHashtable()
    set udg_PDD_damageEvent = CreateTrigger()
    set udg_PDD_damageHandler = CreateTrigger()
    set udg_PDD_damageType = -1
    set udg_PDD_allocatedAttacks = 0
    set udg_PDD_runAllocatedAttacks = CreateTrigger()
   
    // Initialize global configurable constants
    call InitGlobalVariables()
   
    // Initialize global fixed constants
    set udg_PDD_PHYSICAL = 0
    set udg_PDD_SPELL = 1
    set udg_PDD_CODE = 2
    set udg_PDD_UNIT_MIN_LIFE = 0.406
    set udg_PDD_ATTACK_TYPE_UNIVERSAL = ConvertAttackType(7)
    set udg_PDD_totalAllocs = 0
    set udg_PDD_allocCounter = -1
    set udg_PDD_damageEventTrigger = 0.0
   
    // Register units on map initialization
    call TriggerRegisterVariableEvent(udg_PDD_damageHandler, "udg_PDD_damageEventTrigger", EQUAL, 1.0)
    call TriggerAddCondition(udg_PDD_damageEvent, Filter(cDamageEngine))  
    call GroupEnumUnitsInRect(g, GetWorldBounds(), null)
    call ForGroup(g, function MapInit)
   
    // Register units that enter the map
    call RegionAddRect(r, GetWorldBounds())
    call TriggerRegisterEnterRegion(UnitEnters, r, null)
    call TriggerAddCondition(UnitEnters, Filter(cUnitEnters))
   
    // Register trigger for allocated attacks
    call TriggerAddCondition(udg_PDD_runAllocatedAttacks, Filter(cRunAllocatedAttacks))
   
    // Clear memory leaks
    call TriggerRegisterTimerEvent(ClearMemory, udg_PDD_TRIGGER_CLEANUP_PERIOD, true)
    call TriggerAddCondition(ClearMemory, Filter(cClearMemory))

    // Clean things up
    call DestroyGroup(g)
    set UnitEnters = null
    set ClearMemory = null
    set cDamageEngine = null
    set cUnitEnters = null
    set cClearMemory = null
    set cRunAllocatedAttacks = null
    set g = null
    set r = null
endfunction
https://www.hiveworkshop.com/threads/how-to-detect-backstab.192320/
Kitabatake
Backstab
Events
Game - PDD_damageEventTrigger becomes Equal to 1.00
Conditions
Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
PDD_damageType Equal to PDD_PHYSICAL
Then - Actions
-------- Deal more damage on every melee attack from behind or flanks --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(PDD_target is A ground unit) Equal to True
(PDD_target is A structure) Equal to False
Or - Any (Conditions) are true
Conditions
(PDD_source has buff MISSING STRING BOac (Lvl.1 Command Aura)) Equal to True
(PDD_source has buff MISSING STRING BOac (Lvl.2 Command Aura)) Equal to True
(PDD_source has buff MISSING STRING BOac (Lvl.3 Command Aura)) Equal to True
Then - Actions
Set Variable Set TempBackstabPoint[1] = (Position of PDD_source)
Set Variable Set TempBackstabAngle[1] = (Facing of PDD_target)
Set Variable Set TempBackstabPoint[2] = (Position of PDD_target)
Set Variable Set TempBackstabAngle[2] = (Angle from TempBackstabPoint[1] to TempBackstabPoint[2])
Set Variable Set TempBackstabAngle[2] = ((TempBackstabAngle[2] - TempBackstabAngle[1]) + 180.00)
If (TempBackstabAngle[2] Greater than or equal to 360.00) then do (Set VariableSet TempBackstabAngle[2] = (TempBackstabAngle[2] - 360.00)) else do (Do nothing)
If (TempBackstabAngle[2] Less than 0.00) then do (Set VariableSet TempBackstabAngle[2] = (TempBackstabAngle[2] + 360.00)) else do (Do nothing)
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
TempBackstabAngle[2] Greater than or equal to 90.00
TempBackstabAngle[2] Less than or equal to 270.00
Then - Actions
-------- Target is facing away from attacker --------
Set Variable Set PDD_amount = ((1 + (0.10 x (Real((Level of Hide Temp Backstab Buff (Spell Book) for PDD_source))))) x PDD_amount)
Custom script: call RemoveLocation(udg_TempBackstabPoint[1])
Custom script: call RemoveLocation(udg_TempBackstabPoint[2])
Floating Text - Create floating text that reads Flanking Bonus Damage above PDD_source with Z offset 0 , using font size 8.00 , color ( 100.00 %, 0.00 %, 0.00 %), and 0 % transparency
Floating Text - Set the velocity of (Last created floating text) to 64 towards 90 degrees
Floating Text - Change (Last created floating text) : Disable permanence
Floating Text - Change the lifespan of (Last created floating text) to 3.00 seconds
Floating Text - Change the fading age of (Last created floating text) to 0.50 seconds
Else - Actions
-------- Target is not facing away from attacker --------
Else - Actions
Else - Actions
Backstab Aura Add
Events
Time - Every 1.00 seconds of game time
Conditions
Actions
Set Variable Set TempUnitGroup = (Units in Region_000 <gen> matching (((Matching unit) has buff MISSING STRING BOac (Lvl.1 Command Aura)) Equal to True))
Unit Group - Pick every unit in TempUnitGroup and do (Actions)
Loop - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
((Picked unit) has buff MISSING STRING BOac (Lvl.2 Command Aura)) Equal to False
((Picked unit) has buff MISSING STRING BOac (Lvl.3 Command Aura)) Equal to False
Then - Actions
Unit - Add Hide Temp Backstab Buff (Spell Book) to (Picked unit)
Unit - Set level of Hide Temp Backstab Buff (Spell Book) for (Picked unit) to 1
Else - Actions
Custom script: call DestroyGroup(udg_TempUnitGroup)
Set Variable Set TempUnitGroup = (Units in Region_000 <gen> matching (((Matching unit) has buff MISSING STRING BOac (Lvl.2 Command Aura)) Equal to True))
Unit Group - Pick every unit in TempUnitGroup and do (Actions)
Loop - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
((Picked unit) has buff MISSING STRING BOac (Lvl.3 Command Aura)) Equal to False
Then - Actions
Unit - Add Hide Temp Backstab Buff (Spell Book) to (Picked unit)
Unit - Set level of Hide Temp Backstab Buff (Spell Book) for (Picked unit) to 2
Else - Actions
Custom script: call DestroyGroup(udg_TempUnitGroup)
Set Variable Set TempUnitGroup = (Units in Region_000 <gen> matching (((Matching unit) has buff MISSING STRING BOac (Lvl.3 Command Aura)) Equal to True))
Unit Group - Pick every unit in TempUnitGroup and do (Actions)
Loop - Actions
Unit - Add Hide Temp Backstab Buff (Spell Book) to (Picked unit)
Unit - Set level of Hide Temp Backstab Buff (Spell Book) for (Picked unit) to 3
Custom script: call DestroyGroup(udg_TempUnitGroup)
Backstab Aura Remove
Events
Time - Every 1.00 seconds of game time
Conditions
Actions
Set Variable Set TempUnitGroup = (Units in Region_000 <gen> matching (((Matching unit) has buff MISSING STRING BOac (Lvl.1 Command Aura)) Equal to False))
Unit Group - Pick every unit in TempUnitGroup and do (Actions)
Loop - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
((Picked unit) has buff MISSING STRING BOac (Lvl.1 Command Aura)) Equal to False
((Picked unit) has buff MISSING STRING BOac (Lvl.2 Command Aura)) Equal to False
((Picked unit) has buff MISSING STRING BOac (Lvl.3 Command Aura)) Equal to False
Then - Actions
Unit - Remove Hide Temp Backstab Buff (Spell Book) from (Picked unit)
Else - Actions
Custom script: call DestroyGroup(udg_TempUnitGroup)
Set Variable Set TempUnitGroup = (Units in Region_000 <gen> matching (((Matching unit) has buff MISSING STRING BOac (Lvl.2 Command Aura)) Equal to False))
Unit Group - Pick every unit in TempUnitGroup and do (Actions)
Loop - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
((Picked unit) has buff MISSING STRING BOac (Lvl.1 Command Aura)) Equal to False
((Picked unit) has buff MISSING STRING BOac (Lvl.2 Command Aura)) Equal to False
((Picked unit) has buff MISSING STRING BOac (Lvl.3 Command Aura)) Equal to False
Then - Actions
Unit - Remove Hide Temp Backstab Buff (Spell Book) from (Picked unit)
Else - Actions
Custom script: call DestroyGroup(udg_TempUnitGroup)
Set Variable Set TempUnitGroup = (Units in Region_000 <gen> matching (((Matching unit) has buff MISSING STRING BOac (Lvl.3 Command Aura)) Equal to False))
Unit Group - Pick every unit in TempUnitGroup and do (Actions)
Loop - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
((Picked unit) has buff MISSING STRING BOac (Lvl.1 Command Aura)) Equal to False
((Picked unit) has buff MISSING STRING BOac (Lvl.2 Command Aura)) Equal to False
((Picked unit) has buff MISSING STRING BOac (Lvl.3 Command Aura)) Equal to False
Then - Actions
Unit - Remove Hide Temp Backstab Buff (Spell Book) from (Picked unit)
Else - Actions
Custom script: call DestroyGroup(udg_TempUnitGroup)
//TESH.scrollpos=273
//TESH.alwaysfold=0
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//  Wietlol's Effect Over Time System 2.3.2 17/07/2015
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//  Description:
//      This system is made to create and add effects that expire over time.
//      Once in a while, which is configurable using the interval variable, the event "EOT_Event_On_Interval" is called.
//      You can define your own actions on the On_Interval event.
//      This system can be used as a buff system and there is an implemented extension for damage over time.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//  How to install:
//      1. Copy or create all variables that are used in this map into your map.
//          1a. If you use vJASS then you can enable the EOT_vJASS_variables trigger and use that one.
//          1b. If you use GUI then you can use the EOT_GUI_variables trigger to automatically import them.
//      2. Copy the EOT_System trigger and paste it into your map.
//          2a. (optional) You can also copy the DOT_Extension trigger to make use of damage over time effects.
//      3. Copy all code from the header file and paste it into your map's header file.
//      4. Create some spells with EOTs.
//      5. Enjoy your Effect Over Time Spells.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//  How to use:
//      Create an EOT:
//      1. Create a trigger for your spell.
//      2. Make a "Custom script: call EOT_Set_Default_Variables()".
//      3. Set the EOT_Param_Source and EOT_Param_Target to the proper units.
//      4. Set EOT_Param_Type to a variable specific for that type of EOT.
//          For abilities, you can use the id of the ability (which is the same for every casting of that ability).
//          You cannot use the handle id of a unit for example but you can use the unit-type id.
//          When you want subtypes of an EOT, you can put those inside the EOT_Param_Subtype.
//      5. Set additional data for the EOT.
//          5a. Set EOT_Param_Duration and EOT_Param_Interval.
//              If the duration is not specified or is 0 or lower, the duration is infinite.
//              If the interval is not specified or is 0 or lower, the EOT will not have intervals.
//          5b. Set EOT_Param_Buff and EOT_Param_Buff_Holder.
//              If EOT_Param_Buff_Holder is not specified, this EOT will not display a buff.
//              If EOT_Param_Buff_Holder is specified, this EOT will have the buff "EOT_Param_Buff".
//          5c. Set EOT_Param_Special_Effect_Model and EOT_Param_Special_Effect_Point.
//              If EOT_Param_Special_Effect_Model is not specified, this EOT will not have a special effect.
//              If EOT_Param_Special_Effect_Point is not specifid, the attachment point "origin" will be used.
//          5d. Set EOT_Param_Abiliy and EOT_Param_Abiliy_Level.
//              If EOT_Param_Abiliy is not specified or EOT_Param_Abiliy_Level is set to 0 (1 by default), this EOT will not have an ability.
//              Be aware that the ability given is showed in the UI. If you do not want this, add the ability to a disabled spellbook.
//          5e. Set EOT_Param_Positive and EOT_Param_Can_Dispell.
//              These variables are used as buff type variables.
//              EOT_Param_Positive is false by default, meaning that the EOT has a negative attitude.
//              When the EOT_Trigger_Remove_EOTs is called, you can specify if you want to remove positive, negative, both or neither of them.
//              EOT_Param_Can_Dispell is true by default, meaning that the EOT can be dispelled.
//              If it is set to false, the EOT will not dispell unless you set EOT_Param_Force_Destroy to true before the dispell is called.
//          5f. Set EOT_Param_Is_Passive to true if the EOT must not be removed on death.
//              This is usefull for units with passive abilities.
//              You can destroy these EOTs only with EOT_Param_Destroy_Passive.
//      6. Call the EOT_Trigger_Create_EOT trigger.
//      7. Create additional effects.
//          Since you created an EOT, you also have an id.
//          With this id, you can save data in the hashtable using the EOT_Save_Value (Value being the value type) functions.
//      
//      Using the EOT_System's events:
//      1. Create a trigger.
//      2. Create an event of "Game - Value Of Real Variable" and set the variable to the event you want. Leave the value to 0.
//          For spells you can use:
//              - EOT_Event_An_EOT_Is_Created
//              - EOT_Event_An_EOT_Is_Destroyed
//              - EOT_Event_An_EOT_Is_Dispelled
//              - EOT_Event_An_EOT_Has_Expired
//              - EOT_Event_On_Interval
//          All other events are reserved for extensions and systems.
//      3. Now you have the data of your EOT in the Param variables.
//          You can stop the destruction or dispell of an EOT by setting EOT_Param_Destroy to false.
//          You can stop the expiring of an EOT by setting EOT_Param_Expire to false.
//      (For actions on certain EOTs, you can also choose to run a trigger on the interval instead of using the event.
//       this improves performance very much.)
//      
//      Accessing and modifying an EOT's data:
//      1. Set the EOT_Param_Target to the unit that has the EOT.
//      2. Set the EOT_Param_Type to the type of EOT that you want.
//      3. Make an If/Then/Else function.
//          3a. Create a condition of "Boolean Comparison -> Trigger - Evaluate Trigger Conditions".
//              Set the trigger to EOT_Trigger_Get_Data.
//      4. Now you know if the target has the EOT or not.
//          If the target has it, (which means that the condition is right,) the data of the EOT is set in the Param variables.
//      5. Now you can also save the data of the Param variables (which you can change between these two function) by calling
//          the EOT_Trigger_Save_Data trigger.
//      
//      The additional data has some reserved slots. The first 1.000 slots are reserved for extensions or other systems.
//      However when calling the EOT_Save_Value functions, the 1.000 are automatically added.
//      So when making spells, you can start with 0.
//      When making extensions or systems, you have to descend, starting at -1.
//      The extension DOT (Damage Over Time) uses the last 3 of them (-1, -2, -3, aka 999, 998, 997).
//      Extensions/Systems cannot use the same indexes as other extensions/systems.
//      
//      The same counts for the EOT cache.
//      The first 100 cache slot are reserved.
//      The extension DOT (Damage Over Time) does not use an EOT cache.
//      
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//  Feature list:
//      This system:
//      - allows you to create an effect over time on a unit.
//      - allows you to give a unit a buff as long as the eot lasts.
//      - allows you to give a unit an ability as long as the eot lasts.
//      - allows you to run a piece of code once in a while as long as the eot lasts.
//      - allows you to attach a special effect to an eot.
//      - allows you to change the parameters of the eot.
//      - allows you to get the data, change the data and save the data of every eot that is active.
//      - allows you to create your own extensions to make better use of the system.
//      - allows you to save the data of an eot in the cache. The first 100 are reserved for systems and extensions.
//          This can be used for either presets, already having the references to units, and creation/modification of other eot's inside an eot's function.
//      - allows you to save additional data to an eot.
//          The first 1000 are reserved for systems and extensions.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//  Variable explaination:
//////////////////////////
//      General:
//      - EOT_Trigger_Create_EOT            - trigger
//          This is the function that creates an eot on a unit.
//          
//      - EOT_Trigger_Destroy_EOT           - trigger
//          This is the function that destroys the specified eot on the targeted unit.
//          
//      - EOT_Trigger_Get_Data              - trigger
//          This is the function that retrieves all the data of the specified eot on the targeted unit.
//          
//      - EOT_Trigger_Save_Data             - trigger
//          This is the function that saves all the variables to the specified eot on the targeted unit.
//          
//      - EOT_Trigger_Remove_EOTs           - trigger
//          This is the function that removes all or filtered eots on the targeted unit.
//          
//      - EOT_Hashtable                     - hashtable
//          This is the hashtable that is used by the Effect Over Time System.
//          
//      - EOT_Index                         - integer
//          This integer is used as an indexing number in loops.
//          
//      - EOT_Amount                        - integer
//          This is the amount of EOTs that are active.
//          
//      - EOT_Unique_Id                     - integer
//          This is a unique number that increases for each EOT.
//          
//      - EOT_Param_Destroy                 - booleam
//          This boolean tells if the EOT must be destroyed.
//          
//      - EOT_Param_Expire                  - boolean
//          This boolean tells if the EOT is expired and if it has to be destroyed.
//          This one is additional to EOT_Destroy because expired EOTs might be able to keep going
//          on certain conditions while destroyed EOTs may not.
//          
//      - EOT_Param_Force_Destroy           - boolean
//          This boolean tells if the destruction of an EOT must go through Can_Dispell values.
//          It can also be used as an additional Destroy variable.
//          
//      - EOT_Param_Destroy_Passive         - boolean
//          This boolean tells if the Destroy function must remove a passive effect.
//          This is the only way to remove the passive effects.
//          
//////////////////////////
//      Events:
//      Events must be called with "Real value becomes equal to 0"
//      - EOT_Event_An_EOT_Is_Created       - real (event simulator)
//          This event is ran when an eot is created.
//          EOT_Event_Creation_Before and EOT_Event_Creation_After are reserved for other systems and extensions.
//          
//      - EOT_Event_An_EOT_Is_Destroyed     - real (event simulator)
//          This event is ran when an eot is destroyed.
//          If an EOT is destroyed in any possible way (expired, dispelled, bugs, etc.) then this event will see it.
//          EOT_Event_Destruction_Before and EOT_Event_Destruction_After are reserved for other systems and extensions.
//          
//      - EOT_Event_An_EOT_Is_Dispelled     - real (event simulator)
//          This event is ran when an eot is dispelled.
//          Dispelling can be done via Remove_EOTs function
//          or on the next interval by having their buff removed. (non-hidden only)
//          EOT_Event_Dispell_Before and EOT_Event_Dispell_After are reserved for other systems and extensions.
//          
//      - EOT_Event_An_EOT_Has_Expired      - real (event simulator)
//          This event is ran when an eot has properly expired.
//          EOT_Event_Expire_Before and EOT_Event_Expire_After are reserved for other systems and extensions.
//          
//      - EOT_Event_On_Interval             - real (event simulator)
//          This event is ran when the interval is activated.
//          EOT_Event_Interval_Before and EOT_Event_Interval_After are reserved for other systems and extensions.
//          
//      - EOT_Event_Get_Data                - real (event simulator)
//          This event is made for extensions to know when a trigger called the "Get Data" function.
//          
//      - EOT_Event_Save_Data               - real (event simulator)
//          This event is made for extensions to know when a trigger called the "Save Data" function.
//          
//      - EOT_Event_Null_Variables          - real (event simulator)
//          This event is made for extensions to know when a trigger called the "Null Variables" function.
//          
//      - EOT_Event_EOT_Changed_Target      - real (event simulator)
//          This event fires when an EOT is changing targets.
//          The target in the array under the index is the old target and the target in the param is the new target.
//          
//////////////////////////
//      Parameters:
//      - EOT_Array_...                     - ... array
//          These variables are the parameters of EOTs saved for each active EOT.
//          
//      - EOT_Param_Id                      - integer
//          This is a unique Id of the EOT.
//          This value can be used to save additional data to an EOT.
//          This is similar to a handle id... but then an EOT id.
//          
//      - EOT_Param_Source                  - unit
//          This is the source of the eot.
//          This unit gets the credit for the kills, or whatever the eot is doing.
//          
//      - EOT_Param_Target                  - unit
//          This is the unit on which the eot runs.
//          
//      - EOT_Param_Duration                - real
//          This is the duration of the eot.
//          Be aware that this is not the remaining duration.
//          
//      - EOT_Param_Remaining_Duration      - real
//          This is the remaining duration of the eot.
//          
//      - EOT_Param_Interval                - real
//          This is the duration between each call of the trigger of the eot.
//          Be aware that this is not the remaining interval.
//          
//      - EOT_Param_Remaining_Interval      - real
//          This is the remaining duration between each call of the trigger of the eot.
//          
//      - EOT_Param_Hidden                  - boolean
//          If the eot is hidden, it will not display a buff.
//          When removing all eots, you can filter out hidden eots.
//          
//      - EOT_Param_Buff                    - buff (integer in JASS)
//          This is the buff that the target has if the eot is not hidden.
//          
//      - EOT_Param_Buff_Holder             - ability (integer in JASS)
//          This is the ability that makes the buff for the target.
//          
//      - EOT_Param_Buff_Holder_Level       - integer
//          This is the level for the ability that makes the buff.
//          This can be used to show different buffs or use an effect that is on that ability.
//          
//      - EOT_Param_Ability                 - ability (integer in JASS)
//          This ability is given to the target and removed when the eot ends.
//          
//      - EOT_Param_Ability_Level           - integer
//          This is the level of the EOT_Param_Ability.
//          
//      - EOT_Param_Positive                - boolean
//          This determines if the effect is positive or negative.
//          This is used to filter out positive or negative effects.
//          This is also used by the Remove_EOTs to know if positive EOTs should be removed.
//          
//      - EOT_Param_Negative                - boolean
//          This is used by the Remove_EOTs to know if negative EOTs should be removed.
//          
//      - EOT_Param_Special_Effect          - special effect (effect in JASS)
//          This is a special effect that is attached to the target.
//          You should not make the effect yourself but rather define the model and attachment point.
//          
//      - EOT_Param_Special_Effect_Model    - string
//          This is the filepath of the model that is used to create the special effect.
//          
//      - EOT_Param_Special_Effect_Point    - string
//          This is the attachment point for the special effect.
//          
//      - EOT_Param_Type                    - integer
//          This variable is a simple integer that can be used as the type of EOT.
//          The easiest way to make this is to set it to an ability id which created the EOT.
//          
//      - EOT_Param_Subtype                 - integer
//          This variable is a simple integer that can be used to give one type multiple subtypes.
//          
//      - EOT_Param_Subtype2                - integer
//          This variable is a simple integer that can be used to give and EOT even better MUI-ness.
//          
//      - EOT_Param_Is_Paused               - integer
//          Paused EOTs will not expire or call the interval.
//          
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//  Changelog:
//      2.3.1 - 17/07/2015 - Fixed death bug and added OnPeriodTrigger
//          - Fixed a bug where an EOT was not removed when a unit died.
//          - Re-added the option to run a trigger on the periods.
//          - Removed AEM implementation.
//          
//      2.3 - 17/04/2015 - Better Events
//          - Added AEM Events implementation.
//          - Improved Death checks.
//          - Created EOT_Does_Exist().
//          
//      2.2.2 - 25/03/2015 - Ultimate MUI-ness
//          - Added Subtype2 as an additional type. This can be used as sourceid for example to have even better MUI-ness.
//          - Added the event "EOT_Event_EOT_Changed_Target".
//          - Added the paused functionality.
//          
//      2.2.1 - 01/03/2015 - Fixed dead unit crash.
//          - Fixed a bug where the game would crash when a dead unit would gain an EOT.
//          
//      2.2 - 20/02/2015 - Added Is_Passive and fixed a few bugs. 
//          - Changed the variable type of EOT_Type from real to integer.
//              This is because a real has a much lower maximum than an integer.
//              The maximum would be a little bit below the value of ability ids.
//              Subtypes can be declared in the new variable: EOT_Subtype.
//          - Fixed a bug where the Id would be changed to the highest current Id. When an eot would be destroyed.
//          - Added Is_Passive and Destroy_Passive.
//              The Is_Passive is used for passive abilities.
//              They can only be removed using a manual Destroy call while Destroy_Passive is turned on.
//          
//      2.1 - 13/02/2015 - Finished the system. All upcoming updates are fixes.
//          Code:
//          - Replaced redundant code with "EOT_Check_For_New_Target".
//          - Changed the name of "EOT_Null_Variables" to "EOT_Set_Default_Variables" which makes more sense.
//          - Added a disabled trigger with all GUI variables.
//          - Now has a better order of which event/check is called first in the looping action.
//          - Now you don't have to set the hidden parameter in the creation. Just leaving the buff open is enough.
//          - Removed some bugs where ids would be changed.
//          
//      2.0.1 - 10/02/2015 - Fixed event simulators.
//          Code:
//          - The events now run on 0 and are separated to remove non-calling bugs.
//          
//      2.0 - 10/02/2015 - Rewritten the system from timers to arrays.
//          
//          Documentation:
//          - Updated for new functions and variables.
//          Code:
//          - Rewritten the whole code.
//          - Ripped the code into triggers only.
//          - Added hashtable functions in the header.
//          - Added cache functions in the header.
//          - Damage transferred to an extension to remove a lot of empty values in the arrays.
//          Added Features:
//          - Now has a cache where you can save the current EOT in or load a saved EOT from.
//              This can be used as presets or when you want to create a new one during the interval.
//          - Now you can save additional data to an EOT.
//          - Events are now handled better to function with extensions properly and create
//          - You can now leave unnecessary data open. The variables are set to their standard values.
//          - You can now set the level of the buff holder.
//          - Added the Force_Destroy variable which allows you to break through the Can_Dispell value.
//          Bug Fixes:
//          - The EOT is not removed if you set a too high interval.
//          - The Special Effect is now recreated properly if the EOT changed targets, effect-model or attachment point.
//          - The EOT is now removed immediately when the buff is removed.
//          
//      1.2 - 27/01/2015 - Update of simplified system.
//          
//          Documentation:
//          - Added the complete documentation.
//          Code:
//          - Put all code of the system in one trigger with exception of the configuration and made it more readable.
//          - Completed the buff system.
//          Added Features:
//          - Added an ability that is active on the unit as long as the eot exists.
//          - Automatically removes or adds existing eots depending on a configurable, eot-dependant variable.
//          - Now allows the player to change the target of the effect over time.
//          Bug Fixes:
//          - Fixed a bug where an eot which would not last until the next interval would be removed at that moment
//            rather than when the duration expires.
//          
//      1.1 - 20/01/2015 - Update of reworked system.
//          
//          Added Features:
//          - Added the Get_Data and Save_Data functions.
//          Bug Fixes:
//          - Fixed a bug where an eot which was already active on the target would have been removed when the first expired.
//          
//      1.0 - First official release on the Hive.
//          
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//  Known bugs:
//      - The buffs of EOTs are aura buffs. This means that they are not dispelled by buff dispell abilities by default.
//          To be able to dispell the buffs you have to trigger all buff dispel abilities.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////





/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//  These functions are used by this system only.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Check if the EOT has a new target. If so transfer buff, ability and special effect to the new target.
function EOT_Check_For_New_Target takes integer index returns nothing
    //Check for new target.
    if udg_EOT_Param_Target != udg_EOT_Array_Target[index] then
        //remove and add ability
        call UnitRemoveAbility(udg_EOT_Array_Target[index], udg_EOT_Array_Ability[index])
        if udg_EOT_Param_Ability > 0 and udg_EOT_Param_Ability_Level > 0 then
            call UnitAddAbility(udg_EOT_Param_Target, udg_EOT_Param_Ability)
            call SetUnitAbilityLevel(udg_EOT_Param_Target, udg_EOT_Param_Ability, udg_EOT_Param_Ability_Level)
        endif
        
        //remove and add buff
        call UnitRemoveAbility(udg_EOT_Array_Target[index], udg_EOT_Array_Buff[index])
        if udg_EOT_Param_Buff_Holder > 0 and udg_EOT_Param_Buff_Holder_Level > 0 then
            call UnitAddAbility(udg_EOT_Param_Target, udg_EOT_Param_Buff_Holder)
            call SetUnitAbilityLevel(udg_EOT_Param_Target, udg_EOT_Param_Ability, udg_EOT_Param_Buff_Holder_Level)
            call UnitRemoveAbility(udg_EOT_Param_Target, udg_EOT_Param_Buff_Holder)
        endif
        
        //remove and add special effect.
        call DestroyEffect(udg_EOT_Param_Special_Effect)
        if udg_EOT_Param_Special_Effect_Model != "" then
            if udg_EOT_Param_Special_Effect_Point == "" then
                set udg_EOT_Param_Special_Effect_Point = "origin"
            endif
            set udg_EOT_Param_Special_Effect = AddSpecialEffectTarget(udg_EOT_Param_Special_Effect_Model, udg_EOT_Param_Target, udg_EOT_Param_Special_Effect_Point)
        endif
    endif
endfunction

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//  This code is the actions of this system.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//This is the loop for every 0.03 seconds of gametime.
function EOT_Interval takes nothing returns nothing
    local integer i
    set i = 0
    loop
        set udg_EOT_Index = i
        exitwhen udg_EOT_Index > udg_EOT_Amount
        
        //Set global variables.
        set udg_EOT_Param_Destroy = false
        set udg_EOT_Param_Expire = false
        set udg_EOT_Param_Force_Destroy = false
        set udg_EOT_Param_Id                    = udg_EOT_Array_Id[udg_EOT_Index]
        set udg_EOT_Param_Source                = udg_EOT_Array_Source[udg_EOT_Index]
        set udg_EOT_Param_Target                = udg_EOT_Array_Target[udg_EOT_Index]
        set udg_EOT_Param_Duration              = udg_EOT_Array_Duration[udg_EOT_Index]
        set udg_EOT_Param_Remaining_Duration    = udg_EOT_Array_Remaining_Duration[udg_EOT_Index]
        set udg_EOT_Param_Interval              = udg_EOT_Array_Interval[udg_EOT_Index]
        set udg_EOT_Param_Remaining_Interval    = udg_EOT_Array_Remaining_Interval[udg_EOT_Index]
        set udg_EOT_Param_Hidden                = udg_EOT_Array_Hidden[udg_EOT_Index]
        set udg_EOT_Param_Buff                  = udg_EOT_Array_Buff[udg_EOT_Index]
        set udg_EOT_Param_Buff_Holder           = udg_EOT_Array_Buff_Holder[udg_EOT_Index]
        set udg_EOT_Param_Buff_Holder_Level     = udg_EOT_Array_Buff_Holder_Level[udg_EOT_Index]
        set udg_EOT_Param_Ability               = udg_EOT_Array_Ability[udg_EOT_Index]
        set udg_EOT_Param_Ability_Level         = udg_EOT_Array_Ability_Level[udg_EOT_Index]
        set udg_EOT_Param_Type                  = udg_EOT_Array_Type[udg_EOT_Index]
        set udg_EOT_Param_Subtype               = udg_EOT_Array_Subtype[udg_EOT_Index]
        set udg_EOT_Param_Positive              = udg_EOT_Array_Positive[udg_EOT_Index]
        set udg_EOT_Param_Can_Dispell           = udg_EOT_Array_Can_Dispell[udg_EOT_Index]
        set udg_EOT_Param_Is_Passive            = udg_EOT_Array_Is_Passive[udg_EOT_Index]
        set udg_EOT_Param_Special_Effect        = udg_EOT_Array_Special_Effect[udg_EOT_Index]
        set udg_EOT_Param_Special_Effect_Model  = udg_EOT_Array_Special_Effect_Model[udg_EOT_Index]
        set udg_EOT_Param_Special_Effect_Point  = udg_EOT_Array_Special_Effect_Point[udg_EOT_Index]
        
        //Decrease remaining duration.
        set udg_EOT_Param_Remaining_Duration = udg_EOT_Param_Remaining_Duration - 0.03
        
        if IsUnitType(udg_EOT_Param_Target, UNIT_TYPE_DEAD) and GetUnitTypeId(udg_EOT_Param_Target) != 0 and udg_EOT_Param_Is_Passive then
            if udg_EOT_Param_Remaining_Duration <= 0. and udg_EOT_Param_Remaining_Duration > -1 then
                set udg_EOT_Param_Expire = true
                
                //Call the expire event.
                set udg_EOT_Event_Expire_Before = 1 //<<< don't use
                set udg_EOT_Event_Expire_Before = 0 //<<< use this
                set udg_EOT_Event_An_EOT_Has_Expired = 1 //<<< don't use
                set udg_EOT_Event_An_EOT_Has_Expired = 0 //<<< use this
                set udg_EOT_Event_Expire_After = 1 //<<< don't use
                set udg_EOT_Event_Expire_After = 0 //<<< use this
                
                call EOT_Check_For_New_Target(i)
            endif
        else
            set udg_EOT_Param_Remaining_Interval = udg_EOT_Param_Remaining_Interval - 0.03
            
            if GetUnitTypeId(udg_EOT_Param_Target) == 0 or (GetUnitAbilityLevel(udg_EOT_Param_Target, udg_EOT_Param_Buff) == 0 and not(udg_EOT_Param_Hidden)) or IsUnitType(udg_EOT_Param_Target, UNIT_TYPE_DEAD) then
                if GetUnitTypeId(udg_EOT_Param_Target) == 0 or IsUnitType(udg_EOT_Param_Target, UNIT_TYPE_DEAD) then
                    set udg_EOT_Param_Destroy_Passive = true
                    set udg_EOT_Param_Destroy = true
                    
                elseif not udg_EOT_Param_Can_Dispell  then
                    //This eot may not be dispelled.
                    call UnitAddAbility(udg_EOT_Param_Target, udg_EOT_Param_Buff_Holder)
                    //call SetUnitAbilityLevel(udg_EOT_Param_Target, udg_EOT_Param_Buff_Holder, udg_EOT_Param_Buff_Holder_Level) << removed because of bug with auras.
                    call UnitRemoveAbility(udg_EOT_Param_Target, udg_EOT_Param_Buff_Holder)
                else
                    set udg_EOT_Param_Destroy = true
                    
                    //Call the dispell event.
                    set udg_EOT_Event_Dispell_Before = 1 //<<< don't use
                    set udg_EOT_Event_Dispell_Before = 0 //<<< use this
                    set udg_EOT_Event_An_EOT_Is_Dispelled = 1 //<<< don't use
                    set udg_EOT_Event_An_EOT_Is_Dispelled = 0 //<<< use this
                    set udg_EOT_Event_Dispell_After = 1 //<<< don't use
                    set udg_EOT_Event_Dispell_After = 0 //<<< use this
                endif
                call EOT_Check_For_New_Target(i)
            endif
            
            if not(udg_EOT_Param_Destroy) then
                if udg_EOT_Param_Remaining_Interval <= 0. and udg_EOT_Param_Remaining_Interval > -1. and (udg_EOT_Param_Remaining_Interval <= udg_EOT_Param_Remaining_Duration or udg_EOT_Param_Duration == -1.) then
                    set udg_EOT_Param_Remaining_Interval = udg_EOT_Param_Remaining_Interval + udg_EOT_Param_Interval
                    
                    
                    set udg_EOT_Event_Interval_Before = 1 //<<< don't use
                    set udg_EOT_Event_Interval_Before = 0 //<<< use this
                    set udg_EOT_Event_On_Interval = 1 //<<< don't use
                    set udg_EOT_Event_On_Interval = 0 //<<< use this
                    set udg_EOT_Event_Interval_After = 1 //<<< don't use
                    set udg_EOT_Event_Interval_After = 0 //<<< use this
                    
                    //Check for new target.
                    call EOT_Check_For_New_Target(i)
                endif
            endif
        
            if not(udg_EOT_Param_Destroy) then
                //Check if EOT has expired.
                if udg_EOT_Param_Remaining_Duration <= 0. and udg_EOT_Param_Remaining_Duration > -1. then
                    set udg_EOT_Param_Expire = true
                    
                    //Call the expire event.
                    set udg_EOT_Event_Expire_Before = 1 //<<< don't use
                    set udg_EOT_Event_Expire_Before = 0 //<<< use this
                    set udg_EOT_Event_An_EOT_Has_Expired = 1 //<<< don't use
                    set udg_EOT_Event_An_EOT_Has_Expired = 0 //<<< use this
                    set udg_EOT_Event_Expire_After = 1 //<<< don't use
                    set udg_EOT_Event_Expire_After = 0 //<<< use this
                    
                    call EOT_Check_For_New_Target(i)
                endif
            endif
            
            //Update ability level.
            if udg_EOT_Param_Ability > 0 then
                call SetUnitAbilityLevel(udg_EOT_Param_Target, udg_EOT_Param_Ability, udg_EOT_Param_Ability_Level)
            endif
            
            //Update buff.
            if not(udg_EOT_Param_Hidden) then
                call UnitAddAbility(udg_EOT_Param_Target, udg_EOT_Param_Buff_Holder)
                //call SetUnitAbilityLevel(udg_EOT_Param_Target, udg_EOT_Param_Buff_Holder, udg_EOT_Param_Buff_Holder_Level) << removed because of bug with auras.
                call UnitRemoveAbility(udg_EOT_Param_Target, udg_EOT_Param_Buff_Holder)
            endif
        endif
        
        //Update new values.
        set udg_EOT_Array_Source[i]               = udg_EOT_Param_Source
        set udg_EOT_Array_Target[i]               = udg_EOT_Param_Target
        set udg_EOT_Array_Duration[i]             = udg_EOT_Param_Duration
        set udg_EOT_Array_Remaining_Duration[i]   = udg_EOT_Param_Remaining_Duration
        set udg_EOT_Array_Interval[i]             = udg_EOT_Param_Interval
        set udg_EOT_Array_Remaining_Interval[i]   = udg_EOT_Param_Remaining_Interval
        set udg_EOT_Array_Hidden[i]               = udg_EOT_Param_Hidden
        set udg_EOT_Array_Buff[i]                 = udg_EOT_Param_Buff
        set udg_EOT_Array_Buff_Holder[i]          = udg_EOT_Param_Buff_Holder
        set udg_EOT_Array_Buff_Holder_Level[i]    = udg_EOT_Param_Buff_Holder_Level
        set udg_EOT_Array_Ability[i]              = udg_EOT_Param_Ability
        set udg_EOT_Array_Ability_Level[i]        = udg_EOT_Param_Ability_Level
        set udg_EOT_Array_Type[i]                 = udg_EOT_Param_Type
        set udg_EOT_Array_Subtype[i]              = udg_EOT_Param_Subtype
        set udg_EOT_Array_Positive[i]             = udg_EOT_Param_Positive
        set udg_EOT_Array_Can_Dispell[i]          = udg_EOT_Param_Can_Dispell
        set udg_EOT_Array_Is_Passive[i]           = udg_EOT_Param_Is_Passive
        set udg_EOT_Array_Special_Effect[i]       = udg_EOT_Param_Special_Effect
        set udg_EOT_Array_Special_Effect_Model[i] = udg_EOT_Param_Special_Effect_Model
        set udg_EOT_Array_Special_Effect_Point[i] = udg_EOT_Param_Special_Effect_Point
        
        //Destroy.
        if udg_EOT_Param_Destroy or udg_EOT_Param_Expire or udg_EOT_Param_Force_Destroy then
            call TriggerExecute(udg_EOT_Trigger_Destroy_EOT)
            set i = i - 1
        endif
        
        //Next EOT.
        set i = i + 1
    endloop
    call EOT_Set_Default_Variables()
endfunction

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//  This code is the functions that this system has.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//This function checks if the EOT exists.
function EOT_Does_Exist takes nothing returns boolean
    set udg_EOT_Index = 0
    loop
        exitwhen udg_EOT_Index > udg_EOT_Amount
        if udg_EOT_Param_Target == udg_EOT_Array_Target[udg_EOT_Index] and udg_EOT_Param_Type == udg_EOT_Array_Type[udg_EOT_Index] and udg_EOT_Param_Subtype == udg_EOT_Array_Subtype[udg_EOT_Index] then
            return true
        endif
        set udg_EOT_Index = udg_EOT_Index + 1
    endloop
    
    return false
endfunction

//This function creates a new EOT.
function EOT_Create_EOT takes nothing returns nothing
    //Requires:
    //  - udg_EOT_Param_Source                  : unit
    //  - udg_EOT_Param_Target                  : unit
    //  - udg_EOT_Param_Type                    : integer
    //Optional:
    //  - udg_EOT_Param_Subtype                 : integer
    //  - udg_EOT_Param_Duration                : real
    //  - udg_EOT_Param_Interval                : real
    //  - udg_EOT_Param_Buff                    : integer (buff)
    //  - udg_EOT_Param_Buff_Holder             : integer (ability)
    //  - udg_EOT_Param_Buff_Holder_Level       : integer
    //  - udg_EOT_Param_Ability                 : integer (ability)
    //  - udg_EOT_Param_Ability_Level           : integer
    //  - udg_EOT_Param_Positive                : boolean
    //  - udg_EOT_Param_Can_Dispell             : boolean
    //  - udg_EOT_Param_Is_Passive              : boolean
    //  - udg_EOT_Param_Special_Effect_Model    : string
    //  - udg_EOT_Param_Special_Effect_Point    : string
    
    //If target is dead then don't do SHIT!
    if IsUnitType(udg_EOT_Param_Target, UNIT_TYPE_DEAD) and GetUnitTypeId(udg_EOT_Param_Target) != 0 then
        return
    endif
    
    //If the duration is 0 or lower then dset the duration to -1 (infinite).
    if udg_EOT_Param_Duration <= 0. then
        set udg_EOT_Param_Duration = -1.
    endif
    
    //Update the old EOT if that one existed.
    if EOT_Does_Exist() then
        set udg_EOT_Param_Remaining_Duration = udg_EOT_Param_Duration
        call TriggerExecute(udg_EOT_Trigger_Save_Data)
        return
    endif
    
    //Add the buff if applyable.
    if udg_EOT_Param_Buff_Holder > 0 and udg_EOT_Param_Buff_Holder_Level > 0 then
        set udg_EOT_Param_Hidden = false
        call UnitAddAbility(udg_EOT_Param_Target, udg_EOT_Param_Buff_Holder)
        //call SetUnitAbilityLevel(udg_EOT_Param_Target, udg_EOT_Param_Buff_Holder, udg_EOT_Param_Buff_Holder_Level) << removed because of bug with auras.
        call UnitRemoveAbility(udg_EOT_Param_Target, udg_EOT_Param_Buff_Holder)
    else
        set udg_EOT_Param_Hidden = true
    endif
    
    //Add the ability if applyable.
    if udg_EOT_Param_Ability > 0 and udg_EOT_Param_Ability_Level > 0 then
        call UnitAddAbility(udg_EOT_Param_Target, udg_EOT_Param_Ability)
        call SetUnitAbilityLevel(udg_EOT_Param_Target, udg_EOT_Param_Ability, udg_EOT_Param_Ability_Level)
    endif
    
    //Make a special effect.
    if udg_EOT_Param_Special_Effect_Model != "" then
        if udg_EOT_Param_Special_Effect_Point == "" or udg_EOT_Param_Special_Effect_Point == null then
            set udg_EOT_Param_Special_Effect_Point = "origin"
        endif
        set udg_EOT_Param_Special_Effect = AddSpecialEffectTarget(udg_EOT_Param_Special_Effect_Model, udg_EOT_Param_Target, udg_EOT_Param_Special_Effect_Point)
    endif
    
    set udg_EOT_Param_Remaining_Duration = udg_EOT_Param_Duration
    set udg_EOT_Param_Remaining_Interval = udg_EOT_Param_Interval
    
    set udg_EOT_Amount = udg_EOT_Amount + 1
    set udg_EOT_Unique_Id = udg_EOT_Unique_Id + 1
    set udg_EOT_Param_Id = udg_EOT_Unique_Id
    call SaveInteger(udg_EOT_Hashtable, udg_EOT_Param_Id, 0, udg_EOT_Amount)
    
    //Call the event.
    set udg_EOT_Event_Creation_Before = 1 //<<< don't use
    set udg_EOT_Event_Creation_Before = 0 //<<< use this
    set udg_EOT_Event_An_EOT_Is_Created = 1 //<<< don't use
    set udg_EOT_Event_An_EOT_Is_Created = 0 //<<< use this
    set udg_EOT_Event_Creation_After = 1 //<<< don't use
    set udg_EOT_Event_Creation_After = 0 //<<< use this
    
    set udg_EOT_Array_Id[udg_EOT_Amount]                        = udg_EOT_Param_Id
    set udg_EOT_Array_Source[udg_EOT_Amount]                    = udg_EOT_Param_Source
    set udg_EOT_Array_Target[udg_EOT_Amount]                    = udg_EOT_Param_Target
    set udg_EOT_Array_Duration[udg_EOT_Amount]                  = udg_EOT_Param_Duration
    set udg_EOT_Array_Remaining_Duration[udg_EOT_Amount]        = udg_EOT_Param_Remaining_Duration
    set udg_EOT_Array_Interval[udg_EOT_Amount]                  = udg_EOT_Param_Interval
    set udg_EOT_Array_Remaining_Interval[udg_EOT_Amount]        = udg_EOT_Param_Remaining_Interval
    set udg_EOT_Array_Hidden[udg_EOT_Amount]                    = udg_EOT_Param_Hidden
    set udg_EOT_Array_Buff[udg_EOT_Amount]                      = udg_EOT_Param_Buff
    set udg_EOT_Array_Buff_Holder[udg_EOT_Amount]               = udg_EOT_Param_Buff_Holder
    set udg_EOT_Array_Buff_Holder_Level[udg_EOT_Amount]         = udg_EOT_Param_Buff_Holder_Level
    set udg_EOT_Array_Ability[udg_EOT_Amount]                   = udg_EOT_Param_Ability
    set udg_EOT_Array_Ability_Level[udg_EOT_Amount]             = udg_EOT_Param_Ability_Level
    set udg_EOT_Array_Type[udg_EOT_Amount]                      = udg_EOT_Param_Type
    set udg_EOT_Array_Subtype[udg_EOT_Amount]                   = udg_EOT_Param_Subtype
    set udg_EOT_Array_Positive[udg_EOT_Amount]                  = udg_EOT_Param_Positive
    set udg_EOT_Array_Can_Dispell[udg_EOT_Amount]               = udg_EOT_Param_Can_Dispell
    set udg_EOT_Array_Is_Passive[udg_EOT_Amount]                = udg_EOT_Param_Is_Passive
    set udg_EOT_Array_Special_Effect[udg_EOT_Amount]            = udg_EOT_Param_Special_Effect
    set udg_EOT_Array_Special_Effect_Model[udg_EOT_Amount]      = udg_EOT_Param_Special_Effect_Model
    set udg_EOT_Array_Special_Effect_Point[udg_EOT_Amount]      = udg_EOT_Param_Special_Effect_Point
    
    //Start the timer if this is the only EOT.
    if udg_EOT_Amount == 0 then
        call TimerStart(udg_EOT_Timer, 0.03, true, function EOT_Interval)
    endif
    return
endfunction

//This function destroys an EOT.
function EOT_Destroy_EOT takes nothing returns boolean
    //Requires:
    //  - udg_EOT_Index : integer
    
    set udg_EOT_Param_Destroy = true
    
    //Call the destroy event.
    set udg_EOT_Event_Destruction_Before = 1 //<<< don't use
    set udg_EOT_Event_Destruction_Before = 0 //<<< use this
    set udg_EOT_Event_An_EOT_Is_Destroyed = 1 //<<< don't use
    set udg_EOT_Event_An_EOT_Is_Destroyed = 0 //<<< use this
    set udg_EOT_Event_Destruction_After = 1 //<<< don't use
    set udg_EOT_Event_Destruction_After = 0 //<<< use this
    
    //Destroy the EOT.
    if not(udg_EOT_Param_Is_Passive) or udg_EOT_Param_Destroy_Passive then
        if udg_EOT_Param_Destroy or udg_EOT_Param_Force_Destroy then
            call DestroyEffect(udg_EOT_Array_Special_Effect[udg_EOT_Index])
            call UnitRemoveAbility(udg_EOT_Array_Target[udg_EOT_Index], udg_EOT_Array_Buff_Holder[udg_EOT_Index])
            call UnitRemoveAbility(udg_EOT_Array_Target[udg_EOT_Index], udg_EOT_Array_Buff[udg_EOT_Index])
            call UnitRemoveAbility(udg_EOT_Array_Target[udg_EOT_Index], udg_EOT_Array_Ability[udg_EOT_Index])
            
            call FlushChildHashtable(udg_EOT_Hashtable, udg_EOT_Array_Id[udg_EOT_Index])
            set udg_EOT_Array_Id[udg_EOT_Index]                     = udg_EOT_Array_Id[udg_EOT_Amount]
            call SaveInteger(udg_EOT_Hashtable, udg_EOT_Array_Id[udg_EOT_Index], 0, udg_EOT_Index)
            set udg_EOT_Array_Source[udg_EOT_Index]                 = udg_EOT_Array_Source[udg_EOT_Amount]
            set udg_EOT_Array_Target[udg_EOT_Index]                 = udg_EOT_Array_Target[udg_EOT_Amount]
            set udg_EOT_Array_Duration[udg_EOT_Index]               = udg_EOT_Array_Duration[udg_EOT_Amount]
            set udg_EOT_Array_Remaining_Duration[udg_EOT_Index]     = udg_EOT_Array_Remaining_Duration[udg_EOT_Amount]
            set udg_EOT_Array_Interval[udg_EOT_Index]               = udg_EOT_Array_Interval[udg_EOT_Amount]
            set udg_EOT_Array_Remaining_Interval[udg_EOT_Index]     = udg_EOT_Array_Remaining_Interval[udg_EOT_Amount]
            set udg_EOT_Array_Hidden[udg_EOT_Index]                 = udg_EOT_Array_Hidden[udg_EOT_Amount]
            set udg_EOT_Array_Buff[udg_EOT_Index]                   = udg_EOT_Array_Buff[udg_EOT_Amount]
            set udg_EOT_Array_Buff_Holder[udg_EOT_Index]            = udg_EOT_Array_Buff_Holder[udg_EOT_Amount]
            set udg_EOT_Array_Buff_Holder_Level[udg_EOT_Index]      = udg_EOT_Array_Buff_Holder_Level[udg_EOT_Amount]
            set udg_EOT_Array_Ability[udg_EOT_Index]                = udg_EOT_Array_Ability[udg_EOT_Amount]
            set udg_EOT_Array_Ability_Level[udg_EOT_Index]          = udg_EOT_Array_Ability_Level[udg_EOT_Amount]
            set udg_EOT_Array_Type[udg_EOT_Index]                   = udg_EOT_Array_Type[udg_EOT_Amount]
            set udg_EOT_Array_Subtype[udg_EOT_Index]                = udg_EOT_Array_Subtype[udg_EOT_Amount]
            set udg_EOT_Array_Positive[udg_EOT_Index]               = udg_EOT_Array_Positive[udg_EOT_Amount]
            set udg_EOT_Array_Can_Dispell[udg_EOT_Index]            = udg_EOT_Array_Can_Dispell[udg_EOT_Amount]
            set udg_EOT_Array_Is_Passive[udg_EOT_Index]             = udg_EOT_Array_Is_Passive[udg_EOT_Amount]
            set udg_EOT_Array_Special_Effect[udg_EOT_Index]         = udg_EOT_Array_Special_Effect[udg_EOT_Amount]
            set udg_EOT_Array_Special_Effect_Model[udg_EOT_Index]   = udg_EOT_Array_Special_Effect_Model[udg_EOT_Amount]
            set udg_EOT_Array_Special_Effect_Point[udg_EOT_Index]   = udg_EOT_Array_Special_Effect_Point[udg_EOT_Amount]
            set udg_EOT_Array_Id[udg_EOT_Amount]                    = 0
            set udg_EOT_Array_Source[udg_EOT_Amount]                = null
            set udg_EOT_Array_Target[udg_EOT_Amount]                = null
            set udg_EOT_Array_Duration[udg_EOT_Amount]              = 0.
            set udg_EOT_Array_Remaining_Duration[udg_EOT_Amount]    = 0.
            set udg_EOT_Array_Interval[udg_EOT_Amount]              = 0.
            set udg_EOT_Array_Remaining_Interval[udg_EOT_Amount]    = 0.
            set udg_EOT_Array_Hidden[udg_EOT_Amount]                = false
            set udg_EOT_Array_Buff[udg_EOT_Amount]                  = 0
            set udg_EOT_Array_Buff_Holder[udg_EOT_Amount]           = 0
            set udg_EOT_Array_Buff_Holder_Level[udg_EOT_Amount]     = 0
            set udg_EOT_Array_Ability[udg_EOT_Amount]               = 0
            set udg_EOT_Array_Ability_Level[udg_EOT_Amount]         = 0
            set udg_EOT_Array_Type[udg_EOT_Amount]                  = 0
            set udg_EOT_Array_Subtype[udg_EOT_Amount]               = 0
            set udg_EOT_Array_Positive[udg_EOT_Amount]              = false
            set udg_EOT_Array_Can_Dispell[udg_EOT_Amount]           = false
            set udg_EOT_Array_Is_Passive[udg_EOT_Amount]            = false
            set udg_EOT_Array_Special_Effect[udg_EOT_Amount]        = null
            set udg_EOT_Array_Special_Effect_Model[udg_EOT_Amount]  = ""
            set udg_EOT_Array_Special_Effect_Point[udg_EOT_Amount]  = ""
            set udg_EOT_Amount = udg_EOT_Amount - 1
            
            if udg_EOT_Amount < 0 then
                call PauseTimer(udg_EOT_Timer)
            endif
            
            set udg_EOT_Param_Destroy = false
            set udg_EOT_Param_Force_Destroy = false
            set udg_EOT_Param_Destroy_Passive = false
            return true
        endif
    endif
    
    set udg_EOT_Param_Destroy = false
	set udg_EOT_Param_Force_Destroy = false
    set udg_EOT_Param_Destroy_Passive = false
    return false
endfunction

//This function retrieves the data of an EOT and set the Param variables to that data.
function EOT_Get_Data takes nothing returns boolean
    //Requires:
    //  - udg_EOT_Param_Target  : unit
    //  - udg_EOT_Param_Type    : integer
    //  - udg_EOT_Param_Subtype : integer
    
    set udg_EOT_Index = 0
    loop
        exitwhen udg_EOT_Index > udg_EOT_Amount
        if udg_EOT_Param_Target == udg_EOT_Array_Target[udg_EOT_Index] and udg_EOT_Param_Type == udg_EOT_Array_Type[udg_EOT_Index] and udg_EOT_Param_Subtype == udg_EOT_Array_Subtype[udg_EOT_Index] then
            set udg_EOT_Param_Id                    = udg_EOT_Array_Id[udg_EOT_Index]
            set udg_EOT_Param_Source                = udg_EOT_Array_Source[udg_EOT_Index]
            set udg_EOT_Param_Duration              = udg_EOT_Array_Duration[udg_EOT_Index]
            set udg_EOT_Param_Remaining_Duration    = udg_EOT_Array_Remaining_Duration[udg_EOT_Index]
            set udg_EOT_Param_Interval              = udg_EOT_Array_Interval[udg_EOT_Index]
            set udg_EOT_Param_Remaining_Interval    = udg_EOT_Array_Remaining_Interval[udg_EOT_Index]
            set udg_EOT_Param_Hidden                = udg_EOT_Array_Hidden[udg_EOT_Index]
            set udg_EOT_Param_Buff                  = udg_EOT_Array_Buff[udg_EOT_Index]
            set udg_EOT_Param_Buff_Holder           = udg_EOT_Array_Buff_Holder[udg_EOT_Index]
            set udg_EOT_Param_Buff_Holder_Level     = udg_EOT_Array_Buff_Holder_Level[udg_EOT_Index]
            set udg_EOT_Param_Ability               = udg_EOT_Array_Ability[udg_EOT_Index]
            set udg_EOT_Param_Ability_Level         = udg_EOT_Array_Ability_Level[udg_EOT_Index]
            set udg_EOT_Param_Positive              = udg_EOT_Array_Positive[udg_EOT_Index]
            set udg_EOT_Param_Can_Dispell           = udg_EOT_Array_Can_Dispell[udg_EOT_Index]
            set udg_EOT_Param_Is_Passive            = udg_EOT_Array_Is_Passive[udg_EOT_Index]
            set udg_EOT_Param_Special_Effect        = udg_EOT_Array_Special_Effect[udg_EOT_Index]
            set udg_EOT_Param_Special_Effect_Model  = udg_EOT_Array_Special_Effect_Model[udg_EOT_Index]
            set udg_EOT_Param_Special_Effect_Point  = udg_EOT_Array_Special_Effect_Point[udg_EOT_Index]
            
            set udg_EOT_Event_Get_Data = 1 //<<< don't use
            set udg_EOT_Event_Get_Data = 0 //<<< use this
            
            return true
        endif
        set udg_EOT_Index = udg_EOT_Index + 1
    endloop
    
    return false
endfunction

//This function saves the data stored in the Param variables to the EOT.
function EOT_Save_Data takes nothing returns nothing
    //Requires:
    //  - udg_EOT_Param_Id  : integer
    
    //If target is dead then don't do SHIT!
    if IsUnitType(udg_EOT_Param_Target, UNIT_TYPE_DEAD) and GetUnitTypeId(udg_EOT_Param_Target) != 0 then
        return
    endif
    
    set udg_EOT_Index = LoadInteger(udg_EOT_Hashtable, udg_EOT_Param_Id, 0)
	
    //Check for new target.
    call EOT_Check_For_New_Target(udg_EOT_Index)
    
    set udg_EOT_Array_Source[udg_EOT_Index]                 = udg_EOT_Param_Source
    set udg_EOT_Array_Duration[udg_EOT_Index]               = udg_EOT_Param_Duration
    set udg_EOT_Array_Remaining_Duration[udg_EOT_Index]     = udg_EOT_Param_Remaining_Duration
    set udg_EOT_Array_Interval[udg_EOT_Index]               = udg_EOT_Param_Interval
    set udg_EOT_Array_Remaining_Interval[udg_EOT_Index]     = udg_EOT_Param_Remaining_Interval
    set udg_EOT_Array_Hidden[udg_EOT_Index]                 = udg_EOT_Param_Hidden
    set udg_EOT_Array_Buff[udg_EOT_Index]                   = udg_EOT_Param_Buff
    set udg_EOT_Array_Buff_Holder[udg_EOT_Index]            = udg_EOT_Param_Buff_Holder
    set udg_EOT_Array_Buff_Holder_Level[udg_EOT_Index]      = udg_EOT_Param_Buff_Holder_Level
    set udg_EOT_Array_Ability[udg_EOT_Index]                = udg_EOT_Param_Ability
    set udg_EOT_Array_Ability_Level[udg_EOT_Index]          = udg_EOT_Param_Ability_Level
    set udg_EOT_Array_Type[udg_EOT_Index]                   = udg_EOT_Param_Type
    set udg_EOT_Array_Subtype[udg_EOT_Index]                = udg_EOT_Param_Subtype
    set udg_EOT_Array_Positive[udg_EOT_Index]               = udg_EOT_Param_Positive
    set udg_EOT_Array_Can_Dispell[udg_EOT_Index]            = udg_EOT_Param_Can_Dispell
    set udg_EOT_Array_Is_Passive[udg_EOT_Index]             = udg_EOT_Param_Is_Passive
    set udg_EOT_Array_Special_Effect[udg_EOT_Index]         = udg_EOT_Param_Special_Effect
    set udg_EOT_Array_Special_Effect_Model[udg_EOT_Index]   = udg_EOT_Param_Special_Effect_Model
    set udg_EOT_Array_Special_Effect_Point[udg_EOT_Index]   = udg_EOT_Param_Special_Effect_Point
    
    set udg_EOT_Event_Save_Data = 1 //<<< don't use
    set udg_EOT_Event_Save_Data = 0 //<<< use this
endfunction

//This function removes EOTs that are filtered by the Hidden, Positive and Negative variables.
function EOT_Remove_EOTs takes nothing returns nothing
    //Requires:
    //  - udg_EOT_Param_Target          : unit
    //  - udg_EOT_Param_Hidden          : boolean
    //  - udg_EOT_Param_Positive        : boolean
    //  - udg_EOT_Param_Negative        : boolean
    //Optional:
    //  - udg_EOT_Param_Force_Destroy   : boolean
    
    local unit target = udg_EOT_Param_Target
    local boolean hidden = udg_EOT_Param_Hidden
    local boolean positive = udg_EOT_Param_Positive
    local boolean negative = udg_EOT_Param_Negative
    local integer i = 0
    
    loop
        exitwhen i > udg_EOT_Amount
        
        set udg_EOT_Param_Target = target
        set udg_EOT_Param_Ability = udg_EOT_Array_Ability[i]
        if TriggerEvaluate(udg_EOT_Trigger_Get_Data) then
            if not(udg_EOT_Param_Is_Passive) and (udg_EOT_Param_Can_Dispell or udg_EOT_Param_Force_Destroy) then
                if udg_EOT_Param_Hidden == hidden then
                    if (udg_EOT_Param_Positive and positive) or (not(udg_EOT_Param_Positive) and negative) then
                        
                        //Call the dispell event.
                        set udg_EOT_Event_Dispell_Before = 1 //<<< don't use
                        set udg_EOT_Event_Dispell_Before = 0 //<<< use this
                        set udg_EOT_Event_An_EOT_Is_Dispelled = 1 //<<< don't use
                        set udg_EOT_Event_An_EOT_Is_Dispelled = 0 //<<< use this
                        set udg_EOT_Event_Dispell_After = 1 //<<< don't use
                        set udg_EOT_Event_Dispell_After = 0 //<<< use this
                        call TriggerExecute(udg_EOT_Trigger_Destroy_EOT)
                        set i = i - 1
                    endif
                endif
            endif
        endif
        
        set i = i + 1
    endloop
    
    set udg_EOT_Param_Force_Destroy = false
    set target = null
endfunction

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//  This code is the initialization of the system and it's functions.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//This is the initial function.
function InitTrig_EOT_System takes nothing returns nothing
    //Create the global variables.
    set udg_EOT_Hashtable = InitHashtable()
    set udg_EOT_Amount = -1
    set udg_EOT_Unique_Id = -1
    call EOT_Set_Default_Variables()
    
    //Create the interval timer.
    set udg_EOT_Timer = CreateTimer()
    
    //Create the "Create_EOT" function.
    //This function does not have to return a boolean.
    set udg_EOT_Trigger_Create_EOT = CreateTrigger()
    call TriggerAddAction(udg_EOT_Trigger_Create_EOT, function EOT_Create_EOT)
    
    //Create the "Destroy_EOT" function.
    //Returns true if destroyed and false if the EOT cannot be found.
    set udg_EOT_Trigger_Destroy_EOT = CreateTrigger()
    call TriggerAddCondition(udg_EOT_Trigger_Destroy_EOT, Filter(function EOT_Destroy_EOT))
    call TriggerAddAction(udg_EOT_Trigger_Destroy_EOT, function EOT_Destroy_EOT)
    
    //Create the "Get_Data" function.
    set udg_EOT_Trigger_Get_Data = CreateTrigger()
    call TriggerAddCondition(udg_EOT_Trigger_Get_Data, Filter(function EOT_Get_Data))
    call TriggerAddAction(udg_EOT_Trigger_Get_Data, function EOT_Get_Data)
    
	//Create the "Save_Data" function.
    //This function does not have to return a boolean.
    set udg_EOT_Trigger_Save_Data = CreateTrigger()
    call TriggerAddAction(udg_EOT_Trigger_Save_Data, function EOT_Save_Data)
    
    //Create the "Remove_EOTs" function.
    //This function does not have to return a boolean.
    set udg_EOT_Trigger_Remove_EOTs = CreateTrigger()
    call TriggerAddAction(udg_EOT_Trigger_Remove_EOTs, function EOT_Remove_EOTs)
endfunction


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//  EOT System end
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TESH.scrollpos=0
//TESH.alwaysfold=0

function DOT_Deal_Damage takes nothing returns boolean
    if udg_DOT_Damage == 0. then
        return false
    endif
    
    call UnitDamageTarget(udg_EOT_Param_Source, udg_EOT_Param_Target, udg_DOT_Damage, true, false, udg_DOT_Attack_Type, udg_DOT_Damage_Type, WEAPON_TYPE_WHOKNOWS)
    
    return false
endfunction

function DOT_Save_Data takes nothing returns boolean
    call EOT_Save_Real(-1, udg_DOT_Damage)
    call EOT_Save_Integer(-2, ConvertAttackTypeReverse(udg_DOT_Attack_Type))
    call EOT_Save_Integer(-3, ConvertDamageTypeReverse(udg_DOT_Damage_Type))
    
    return false
endfunction

function DOT_Get_Data takes nothing returns boolean
    
    set udg_DOT_Damage = EOT_Load_Real(-1)
    set udg_DOT_Attack_Type = ConvertAttackType(EOT_Load_Integer(-2))
    set udg_DOT_Damage_Type = ConvertDamageType(EOT_Load_Integer(-3))
    
    return false
endfunction

function DOT_Reset_Data takes nothing returns boolean
    
    set udg_DOT_Damage = 0.
    set udg_DOT_Attack_Type = ConvertAttackType(0)
    set udg_DOT_Damage_Type = ConvertDamageType(0)
    
    return false
endfunction


//===========================================================================
function InitTrig_DOT_Extension takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterVariableEvent(t, "udg_EOT_Event_Interval_After", EQUAL, 0)
    call TriggerAddCondition(t, Filter(function DOT_Deal_Damage))
    
    set t = CreateTrigger()
    call TriggerRegisterVariableEvent(t, "udg_EOT_Event_Creation_Before", EQUAL, 0)
    call TriggerRegisterVariableEvent(t, "udg_EOT_Event_Save_Data", EQUAL, 0)
    call TriggerAddCondition(t, Filter(function DOT_Save_Data))
    
    set t = CreateTrigger()
    call TriggerRegisterVariableEvent(t, "udg_EOT_Event_Interval_Before", EQUAL, 0)
    call TriggerRegisterVariableEvent(t, "udg_EOT_Event_Get_Data", EQUAL, 0)
    call TriggerAddCondition(t, Filter(function DOT_Get_Data))
    
    set t = CreateTrigger()
    call TriggerRegisterVariableEvent(t, "udg_EOT_Event_Null_Variables", EQUAL, 0)
    call TriggerAddCondition(t, Filter(function DOT_Reset_Data))
    
    set t = null
endfunction
Dispel Magic
Events
Unit - A unit Starts the effect of an ability
Conditions
Or - Any (Conditions) are true
Conditions
(Ability being cast) Equal to Dispel Magic
(Ability being cast) Equal to Dispel Magic (Neutral Hostile)
Actions
Set Variable Set TempLocation = (Target point of ability being cast)
Custom script: set bj_wantDestroyGroup = true
Unit Group - Pick every unit in (Units within 230.00 of TempLocation.) and do (Actions)
Loop - Actions
Unit - Remove Negative buffs from (Picked unit)
Unit - Remove Positive buffs from (Picked unit)
Custom script: call RemoveLocation(udg_TempLocation)
Spell Steal
Events
Unit - A unit Starts the effect of an ability
Conditions
Or - Any (Conditions) are true
Conditions
(Ability being cast) Equal to Spell Steal
Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
((Target unit of ability being cast) belongs to an ally of (Owner of (Triggering unit)).) Equal to True
Then - Actions
Unit - Remove Negative buffs from (Picked unit)
Else - Actions
Unit - Remove Positive buffs from (Picked unit)
Purge
Events
Unit - A unit Starts the effect of an ability
Conditions
Or - Any (Conditions) are true
Conditions
(Ability being cast) Equal to Purge
(Ability being cast) Equal to Purge
(Ability being cast) Equal to Purge (Neutral Hostile)
Actions
Set Variable Set TempUnit = (Target unit of ability being cast)
Unit - Remove Negative buffs from TempUnit
Unit - Remove Positive buffs from TempUnit
Disenchant
Events
Unit - A unit Starts the effect of an ability
Conditions
(Ability being cast) Equal to Disenchant
Actions
Set Variable Set TempLocation = (Target point of ability being cast)
Custom script: set bj_wantDestroyGroup = true
Unit Group - Pick every unit in (Units within 280.00 of TempLocation.) and do (Actions)
Loop - Actions
Unit - Remove Negative buffs from (Picked unit)
Unit - Remove Positive buffs from (Picked unit)
Custom script: call RemoveLocation(udg_TempLocation)
Disenchant Old
Events
Unit - A unit Starts the effect of an ability
Conditions
(Ability being cast) Equal to Disenchant (Old)
Actions
Set Variable Set TempLocation = (Target point of ability being cast)
Custom script: set bj_wantDestroyGroup = true
Unit Group - Pick every unit in (Units within 230.00 of TempLocation.) and do (Actions)
Loop - Actions
Unit - Remove Negative buffs from (Picked unit)
Unit - Remove Positive buffs from (Picked unit)
Custom script: call RemoveLocation(udg_TempLocation)
Anti Magic Shell
Events
Unit - A unit Starts the effect of an ability
Conditions
Or - Any (Conditions) are true
Conditions
(Ability being cast) Equal to Anti-magic Shell
(Ability being cast) Equal to Anti-magic Shell (Magic Resistance)
(Ability being cast) Equal to Anti-magic Shell (Neutral Hostile)
Actions
Set Variable Set TempUnit = (Target unit of ability being cast)
Unit - Remove Negative buffs from TempUnit
Unit - Remove Positive buffs from TempUnit
Devour Magic
Events
Unit - A unit Starts the effect of an ability
Conditions
(Ability being cast) Equal to Devour Magic
Actions
Set Variable Set TempLocation = (Target point of ability being cast)
Custom script: set bj_wantDestroyGroup = true
Unit Group - Pick every unit in (Units within 230.00 of TempLocation.) and do (Actions)
Loop - Actions
Unit - Remove Negative buffs from (Picked unit)
Unit - Remove Positive buffs from (Picked unit)
Custom script: call RemoveLocation(udg_TempLocation)
Devour Magic Neutral Hostile
Events
Unit - A unit Starts the effect of an ability
Conditions
(Ability being cast) Equal to Devour Magic (Neutral Hostile)
Actions
Set Variable Set TempLocation = (Target point of ability being cast)
Custom script: set bj_wantDestroyGroup = true
Unit Group - Pick every unit in (Units within 280.00 of TempLocation.) and do (Actions)
Loop - Actions
Unit - Remove Negative buffs from (Picked unit)
Unit - Remove Positive buffs from (Picked unit)
Custom script: call RemoveLocation(udg_TempLocation)
Detonate
Events
Unit - A unit Starts the effect of an ability
Conditions
Or - Any (Conditions) are true
Conditions
(Ability being cast) Equal to Detonate
Actions
Set Variable Set TempLocation = (Target point of ability being cast)
Custom script: set bj_wantDestroyGroup = true
Unit Group - Pick every unit in (Units within 330.00 of TempLocation.) and do (Actions)
Loop - Actions
Unit - Remove Negative buffs from (Picked unit)
Unit - Remove Positive buffs from (Picked unit)
Custom script: call RemoveLocation(udg_TempLocation)
Abolish Magic
Events
Unit - A unit Starts the effect of an ability
Conditions
Or - Any (Conditions) are true
Conditions
(Ability being cast) Equal to Abolish Magic
(Ability being cast) Equal to Abolish Magic
(Ability being cast) Equal to Abolish Magic (Neutral Hostile)
(Ability being cast) Equal to Abolish Magic (Neutral Hostile, second position)
Actions
Set Variable Set TempUnit = (Target unit of ability being cast)
Unit - Remove Negative buffs from TempUnit
Unit - Remove Positive buffs from TempUnit


Ray of Enfeeblement
Events
Game - PDD_damageEventTrigger becomes Equal to 1.00
Conditions
Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
Or - Any (Conditions) are true
Conditions
PDD_damageType Equal to PDD_SPELL
Then - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Level of Ray of Enfeeblement (Acid Bomb) for PDD_source) Greater than or equal to 1
(PDD_target is A ground unit) Equal to True
(PDD_target is A structure) Equal to False
Then - Actions
Special Effect - Create a special effect attached to the origin (Unexpected type: 'attachpoint') of PDD_target using Arcane Nova.mdx
Special Effect - Destroy (Last created special effect)
-------- The event should be made by a DDS. --------
-------- make sure that there are no unwanted variables --------
Custom script: call EOT_Set_Default_Variables()
-------- set target and type --------
Set Variable Set TempCasterUnit = PDD_source
Set Variable Set EOT_Param_Target = PDD_target
Set Variable Set TempAbility = "A00N"
Custom script: set udg_TempInteger = udg_TempAbility
Set Variable Set EOT_Param_Type = TempInteger
-------- check if the target has an eot of the same type --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Evaluate EOT_Trigger_Get_Data conditions) Equal to True
Then - Actions
-------- if it has, increase the level of the ability and reset the duration --------
Set Variable Set EOT_Param_Remaining_Duration = (15.00 + EOT_Param_Remaining_Duration)
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Level of Ray of Enfeeblement (Acid Bomb) for TempCasterUnit) Greater than EOT_Param_Ability_Level
Then - Actions
Set Variable Set EOT_Param_Ability_Level = (EOT_Param_Ability_Level + 1)
Trigger - Run EOT_Trigger_Save_Data (ignoring conditions)
Else - Actions
Else - Actions
-------- if not, then create the EOT --------
Set Variable Set EOT_Param_Source = TempCasterUnit
Set Variable Set EOT_Param_Duration = "30.00"
Set Variable Set EOT_Param_Ability = "A00Q"
Set Variable Set EOT_Param_Ability_Level = (Level of Ray of Enfeeblement (Acid Bomb) for TempCasterUnit)
Set Variable Set EOT_Param_Buff = "B005"
Set Variable Set EOT_Param_Buff_Holder = "A00R"
Set Variable Set EOT_Param_Special_Effect_Model = "Disarm Purple.mdl"
Set Variable Set EOT_Param_Special_Effect_Point = "overhead"
Set Variable Set TempAbility = "A00N"
Custom script: set udg_TempInteger = udg_TempAbility
Set Variable Set EOT_Param_Type = TempInteger
Set Variable Set EOT_Param_Positive = "false"
Set Variable Set EOT_Param_Can_Dispell = "false"
Trigger - Run EOT_Trigger_Create_EOT (ignoring conditions)
Else - Actions
Else - Actions
Shield Smash
Events
Unit - A unit Starts the effect of an ability
Conditions
(Ability being cast) Equal to Shield Smash (Storm Bolt)
Actions
-------- make sure that there are no unwanted variables --------
Custom script: call EOT_Set_Default_Variables()
-------- set target and type --------
Set Variable Set TempCasterUnit = (Casting unit)
Set Variable Set EOT_Param_Target = (Casting unit)
Set Variable Set TempAbility = "A00C"
Custom script: set udg_TempInteger = udg_TempAbility
Set Variable Set EOT_Param_Type = TempInteger
-------- check if the target has an eot of the same type --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Evaluate EOT_Trigger_Get_Data conditions) Equal to True
Then - Actions
-------- if it has, increase the level of the ability and reset the duration --------
Set Variable Set EOT_Param_Remaining_Duration = (15.00 + EOT_Param_Remaining_Duration)
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Level of Shield Smash (Storm Bolt) for TempCasterUnit) Greater than EOT_Param_Ability_Level
Then - Actions
Set Variable Set EOT_Param_Ability_Level = (EOT_Param_Ability_Level + 1)
Trigger - Run EOT_Trigger_Save_Data (ignoring conditions)
Else - Actions
Else - Actions
-------- if not, then create the EOT --------
Set Variable Set EOT_Param_Source = TempCasterUnit
Set Variable Set EOT_Param_Ability = "A00I"
Set Variable Set EOT_Param_Ability_Level = (Level of Shield Smash (Storm Bolt) for TempCasterUnit)
Set Variable Set EOT_Param_Duration = "15.00"
Set Variable Set EOT_Param_Buff = "B003"
Set Variable Set EOT_Param_Buff_Holder = "A00J"
Set Variable Set EOT_Param_Special_Effect_Model = "dummy.mdl"
Set Variable Set EOT_Param_Special_Effect_Point = "overhead"
Set Variable Set TempAbility = "A00C"
Custom script: set udg_TempInteger = udg_TempAbility
Set Variable Set EOT_Param_Type = TempInteger
Set Variable Set EOT_Param_Positive = "true"
Set Variable Set EOT_Param_Can_Dispell = "false"
Trigger - Run EOT_Trigger_Create_EOT (ignoring conditions)
Delete the Unit Indexer trigger below if you already have Unit Indexer in your map.
This trigger works in two key phases:

1) During map initialization, enumerate all units of all players to give them an index.
2) Adds a second event to itself to index new units as they enter the map.

As a unit enters the map, check for any old units that may have been removed at some point in order to free their index.
Unit Indexer
Events
Map initialization
Conditions
Actions
Custom script: call ExecuteFunc("InitializeUnitIndexer")
Custom script: endfunction
-------- --------
-------- This is the most important function - it provides an index for units as they enter the map --------
-------- --------
Custom script: function IndexUnit takes nothing returns boolean
Custom script: local integer pdex = udg_UDex
-------- --------
-------- You can use the boolean UnitIndexerEnabled to protect some of your undesirable units from being indexed --------
-------- - Example: --------
-------- -- Set UnitIndexerEnabled = False --------
-------- -- Unit - Create 1 Dummy for (Triggering player) at TempLoc facing 0.00 degrees --------
-------- -- Set UnitIndexerEnabled = True --------
-------- --------
-------- You can also customize the following block - if conditions are false the (Matching unit) won't be indexed. --------
-------- --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
UnitIndexerEnabled Equal to True
Then - Actions
-------- --------
-------- Generate a unique integer index for this unit --------
-------- --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
UDexRecycle Equal to 0
Then - Actions
Set Variable Set UDex = (UDexGen + 1)
Set Variable Set UDexGen = UDex
Else - Actions
Set Variable Set UDex = UDexRecycle
Set Variable Set UDexRecycle = UDexNext[UDex]
-------- --------
-------- Link index to unit, unit to index --------
-------- --------
Set Variable Set UDexUnits[UDex] = (Matching unit)
Unit - Set the custom value of UDexUnits[UDex] to UDex
-------- --------
-------- Use a doubly-linked list to store all active indexes --------
-------- --------
Set Variable Set UDexPrev[UDexNext[0]] = UDex
Set Variable Set UDexNext[UDex] = UDexNext[0]
Set Variable Set UDexNext[0] = UDex
-------- --------
-------- Fire index event for UDex --------
-------- --------
Set Variable Set UnitIndexEvent = "0.00"
Set Variable Set UnitIndexEvent = "1.00"
Set Variable Set UnitIndexEvent = "0.00"
Custom script: set udg_UDex = pdex
Else - Actions
Custom script: return false
Custom script: endfunction
-------- --------
-------- The next function is called each time a unit enters the map --------
-------- --------
Custom script: function IndexNewUnit takes nothing returns boolean
Custom script: local integer pdex = udg_UDex
Custom script: local integer ndex
-------- --------
-------- Recycle indices of units no longer in-play every (15) units created --------
-------- --------
Set Variable Set UDexWasted = (UDexWasted + 1)
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
UDexWasted Equal to 15
Then - Actions
Set Variable Set UDexWasted = "0"
Set Variable Set UDex = UDexNext[0]
Custom script: loop
Custom script: exitwhen udg_UDex == 0
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Custom value of UDexUnits[UDex]) Equal to 0
Then - Actions
-------- --------
-------- Remove index from linked list --------
-------- --------
Custom script: set ndex = udg_UDexNext[udg_UDex]
Custom script: set udg_UDexNext[udg_UDexPrev[udg_UDex]] = ndex
Custom script: set udg_UDexPrev[ndex] = udg_UDexPrev[udg_UDex]
Set Variable Set UDexPrev[UDex] = "0"
-------- --------
-------- Fire deindex event for UDex --------
-------- --------
Set Variable Set UnitIndexEvent = "2.00"
Set Variable Set UnitIndexEvent = "0.00"
-------- --------
-------- Recycle the index for later use --------
-------- --------
Set Variable Set UDexUnits[UDex] = No unit
Set Variable Set UDexNext[UDex] = UDexRecycle
Set Variable Set UDexRecycle = UDex
Custom script: set udg_UDex = ndex
Else - Actions
Set Variable Set UDex = UDexNext[UDex]
Custom script: endloop
Custom script: set udg_UDex = pdex
Else - Actions
-------- --------
-------- Handle the entering unit (Matching unit) --------
-------- --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Custom value of (Matching unit)) Equal to 0
Then - Actions
Custom script: call IndexUnit()
Else - Actions
Custom script: return false
Custom script: endfunction
-------- --------
-------- The next function initializes the core of the system --------
-------- --------
Custom script: function InitializeUnitIndexer takes nothing returns nothing
Custom script: local integer i = 0
Custom script: local region re = CreateRegion()
Custom script: local rect r = GetWorldBounds()
Set Variable Set UnitIndexerEnabled = "true"
Custom script: call RegionAddRect(re, r)
Custom script: call TriggerRegisterEnterRegion(CreateTrigger(), re, Filter(function IndexNewUnit))
Custom script: call RemoveRect(r)
Custom script: set re = null
Custom script: set r = null
Custom script: loop
Custom script: call GroupEnumUnitsOfPlayer(bj_lastCreatedGroup, Player(i), Filter(function IndexUnit))
Custom script: set i = i + 1
Custom script: exitwhen i == 16
Custom script: endloop
-------- --------
-------- This is the "Unit Indexer Initialized" event, use it instead of "Map Initialization" for best results --------
-------- --------
Set Variable Set UnitIndexEvent = "3.00"
Set Variable Set UnitIndexEvent = "0.00"
Knockback 2D version 4.2.3.1

Flying units now display special effect art attached to their "origin". Simplified the pathing check for flying units to only check for air unit pathability.

For the full list of changes, please review the Knockback 2D Spell resource on HiveWorkshop.com
Knockback 2D Config
Events
Game - UnitIndexEvent becomes Equal to 3.00
Conditions
Actions
-------- --------
-------- Configure things below --------
-------- --------
-------- Set the timeout to be used throughout the system --------
-------- --------
Set Variable Set K2DTimeout = (1.00 / 60.00)
-------- --------
-------- Robust Pathing at 0 is only safe for collision sizes 16 and lower, but requires only one SetItemPosition check per timeout. --------
-------- -------- 1 checks collision vertically and horizontally to momentum. Uses an extra 4 SetItemPosition checks pet timeout. --------
-------- -------- 2 checks collision diagonally with momentum. Uses a total of 9 SetItemPosition checks per timeout. --------
-------- In any case, if the unit only has size 16 or lower collision, only one SetItemPosition check will be used for it. --------
-------- If RobustPathing is set to 2 and the unit has 36 or less collision, it will only use the normal check of 5 SetItemPosition calls --------
-------- The only reason to use robustness above 1 is for visual continuity - it features potentially-less glitchy movement. --------
-------- --------
Set Variable Set Knockback2DRobustPathing = "2"
-------- --------
-------- Keep the friction between 0.00 and 1.00, At 0.00, friction keeps the unit at the same speed for the knockback --------
-------- 1.00 friction will be an evenly-distributed deceleration which sees the unit slow to a complete stop --------
-------- Friction outside of these bounds gives the knockback a boomerang-effect, so you are welcome to experiment. --------
-------- --------
Set Variable Set Knockback2DDefaultFriction = "1.00"
Set Variable Set Knockback2DFriction = Knockback2DDefaultFriction
-------- --------
-------- Determine the default bouncing behavior of units. You can set this before knocking a unit back. --------
-------- --------
Set Variable Set Knockback2DDefaultBounce = "true"
Set Variable Set Knockback2DBounces = Knockback2DDefaultBounce
-------- --------
-------- Determine the default mechanics of whether a unit should be unable to move while knocked back --------
-------- --------
Set Variable Set Knockback2DDefaultPause = "false"
Set Variable Set Knockback2DPause = Knockback2DDefaultPause
-------- --------
-------- Determine if surrounding trees should be killed by default or not --------
-------- --------
Set Variable Set Knockback2DDefaultKillTrees = "true"
Set Variable Set Knockback2DKillTrees = Knockback2DDefaultKillTrees
-------- --------
-------- If so, how wide should the radius be? 128.00 should be the minimum if you use pathing robustness greater than 0. --------
-------- The minimum should be 64 if you use a robustness of 0. --------
-------- --------
Set Variable Set Knockback2DDefaultDestRadius = "128.00"
Set Variable Set Knockback2DDestRadius = Knockback2DDefaultDestRadius
-------- --------
-------- The "attack" option below will destroy any valid debris, from trees to barrels to creep homes. --------
-------- If you just want to destroy trees, change the string to: harvest --------
-------- --------
Set Variable Set Knockback2DTreeOrDebris = "attack"
-------- --------
-------- 0.50 gravity will have equal ascend and decline rate, 1.00 is instant descend, 0.67 is twice as fast, 0.75 is three times as fast. --------
-------- --------
Set Variable Set Knockback2DDefaultGravity = "0.71"
Set Variable Set Knockback2DGravity = Knockback2DDefaultGravity
-------- --------
-------- Change the following to the default type of looping FX you want to have if you use Knockback Effects --------
-------- --------
Set Variable Set Knockback2DDefaultFX = "Abilities\Weapons\AncientProtectorMissile\AncientProtectorMissile.mdl"
Set Variable Set Knockback2DLoopFX = Knockback2DDefaultFX
-------- --------
-------- How frequently should the effects appear per unit? This can also be customized per-knockback --------
-------- --------
Set Variable Set Knockback2DDefaultFXRate = "0.10"
Set Variable Set Knockback2DFXRate = Knockback2DDefaultFXRate
-------- --------
-------- Create an item to help verify pathing throughout the game --------
-------- --------
Set Variable Set CenterPoint = (Point(K2DX, K2DY))
Item - Create Slippers of Agility +3 at CenterPoint
Set Variable Set K2DItem = (Last created item)
-------- --------
-------- Create a harvest-capable unit to check if debris can be killed --------
-------- --------
Set Variable Set UnitIndexerEnabled = "false"
Unit - Create 1 . Ghoul for Neutral Passive at CenterPoint facing 0.00 degrees
Set Variable Set K2DDebrisKiller = (Last created unit)
-------- --------
-------- End Configuration --------
-------- --------
Set Variable Set UnitIndexerEnabled = "true"
Custom script: call RemoveLocation(udg_CenterPoint)
Game - Preload Knockback2DDefaultFX
Item - Hide K2DItem
Unit - Hide K2DDebrisKiller
Unit - Pause K2DDebrisKiller
Custom script: call UnitAddAbility(udg_K2DDebrisKiller, 'Aloc')
Set Variable Set Radians_Turn = (Radians(360.00))
Set Variable Set Radians_QuarterTurn = (Radians(90.00))
Set Variable Set Radians_QuarterPi = (Radians(45.00))
Set Variable Set K2DRegion = (Entire map)
Set Variable Set K2DMaxX = (Max X of K2DRegion)
Set Variable Set K2DMaxY = (Max Y of K2DRegion)
Set Variable Set K2DMinX = (Min X of K2DRegion)
Set Variable Set K2DMinY = (Min Y of K2DRegion)
Set Variable Set K2DMaxDestRadius = (Knockback2DDefaultDestRadius x 2.00)
Custom script: call SetRect(udg_K2DRegion, 0.00, 0.00, udg_K2DMaxDestRadius, udg_K2DMaxDestRadius)
Set Variable Set K2DItemsFound = "false"
Set Variable Set K2DItemOffset = "false"
Knockback 2D Destroy
Events
Game - UnitIndexEvent becomes Equal to 2.00
Conditions
IsUnitBeingKnockedBack[UDex] Equal to True
Actions
-------- --------
-------- This trigger destroys any knockback; you can execute it yourself by first setting UDex to the custom value --------
-------- --------
Set Variable Set IsUnitBeingKnockedBack[UDex] = "false"
Set Variable Set K2DNext[K2DPrev[UDex]] = K2DNext[UDex]
Set Variable Set K2DPrev[K2DNext[UDex]] = K2DPrev[UDex]
Set Variable Set K2DPrev[UDex] = "0"
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
K2DNext[0] Equal to 0
Then - Actions
Countdown Timer - Pause K2DTimer
Else - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
K2DHeight[UDex] Not equal to 0.00
Then - Actions
Animation - Change Knockback2DUnit flying height to (Default flying height of Knockback2DUnit) at 0.00
Else - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
K2DFreeze[UDex] Not equal to True
(K2DImpact[UDex] is on) Equal to True
Then - Actions
Trigger - Run K2DImpact[UDex] (checking conditions)
Else - Actions
Set Variable Set K2DOverride[UDex] = "false"
Set Variable Set K2DSource[UDex] = No unit
You can run this trigger, checking conditions if you want to play it safe.
Knockback 2D
Events
Conditions
(Default movement speed of Knockback2DUnit) Not equal to 0.00
K2DOverride[(Custom value of Knockback2DUnit)] Equal to False
Actions
Custom script: local integer pdex = udg_UDex
Set Variable Set UDex = (Custom value of Knockback2DUnit)
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
IsUnitBeingKnockedBack[UDex] Equal to True
Then - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
Knockback2DOverride Equal to False
Then - Actions
Set Variable Set K2DAngle[UDex] = (Degrees(K2DAngle[UDex]))
Set Variable Set Knockback2DAngle = ((Knockback2DAngle + K2DAngle[UDex]) x 0.50)
Set Variable Set Knockback2DDistance = ((K2DDistanceLeft[UDex] + Knockback2DDistance) x 0.50)
Set Variable Set Knockback2DTime = ((K2DTimeLeft[UDex] + Knockback2DTime) x 0.50)
Else - Actions
Trigger - Run Knockback_2D_Destroy <gen> (ignoring conditions)
Else - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
K2DNext[0] Equal to 0
Then - Actions
Custom script: call ExecuteFunc("StartKnockback2DTimer")
Else - Actions
Set Variable Set IsUnitBeingKnockedBack[UDex] = "true"
Set Variable Set K2DPrev[K2DNext[0]] = UDex
Set Variable Set K2DNext[UDex] = K2DNext[0]
Set Variable Set K2DNext[0] = UDex
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
Knockback2DHeight Not equal to 0.00
Then - Actions
Set Variable Set K2DHeight[UDex] = Knockback2DHeight
Custom script: if UnitAddAbility(udg_Knockback2DUnit, 'Amrf') then
Custom script: call UnitRemoveAbility(udg_Knockback2DUnit, 'Amrf')
Custom script: endif
Animation - Change Knockback2DUnit flying height to ((Default flying height of Knockback2DUnit) + Knockback2DHeight) at ((Knockback2DHeight - (Default flying height of Knockback2DUnit)) / (Knockback2DGravity x Knockback2DTime))
Set Variable Set K2DHeightThreshold[UDex] = ((1 - Knockback2DGravity) x Knockback2DTime)
Set Variable Set Knockback2DHeight = "0.00"
Else - Actions
Set Variable Set K2DHeight[UDex] = "0.00"
Custom script: set udg_K2DX = GetUnitX(udg_Knockback2DUnit)
Custom script: set udg_K2DY = GetUnitY(udg_Knockback2DUnit)
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
Knockback2DPause Equal to True
Then - Actions
Set Variable Set K2DLastX[UDex] = K2DX
Set Variable Set K2DLastY[UDex] = K2DY
Else - Actions
Set Variable Set K2DAngle[UDex] = (Radians(Knockback2DAngle))
Set Variable Set K2DCos[UDex] = (Cos(Knockback2DAngle))
Set Variable Set K2DSin[UDex] = (Sin(Knockback2DAngle))
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Knockback2DUnit is A flying unit) Equal to True
Then - Actions
Set Variable Set K2DFlying[UDex] = "true"
Else - Actions
Set Variable Set K2DFlying[UDex] = "false"
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
Knockback2DRobustPathing Greater than 0
Then - Actions
-------- --------
-------- Handle the pathing checker based on the unit's collision size --------
-------- --------
Custom script: if not IsUnitInRangeXY(udg_Knockback2DUnit, udg_K2DX + 17, udg_K2DY, 0) then
Set Variable Set K2DRadius[UDex] = "0"
Custom script: else
Custom script: if not IsUnitInRangeXY(udg_Knockback2DUnit, udg_K2DX + 25, udg_K2DY, 0) then
Set Variable Set K2DRadius[UDex] = "8"
Custom script: elseif not IsUnitInRangeXY(udg_Knockback2DUnit, udg_K2DX + 33, udg_K2DY, 0) then
Set Variable Set K2DRadius[UDex] = "16"
Custom script: elseif not IsUnitInRangeXY(udg_Knockback2DUnit, udg_K2DX + 49, udg_K2DY, 0) then
Set Variable Set K2DRadius[UDex] = "32"
Custom script: else
Set Variable Set K2DRadius[UDex] = "48"
Custom script: endif
Set Variable Set Knockback2DAngle = ((Knockback2DAngle + 90.00) mod 360.00)
Set Variable Set K2DCosH[UDex] = (Cos(Knockback2DAngle))
Set Variable Set K2DSinH[UDex] = (Sin(Knockback2DAngle))
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
Knockback2DRobustPathing Equal to 2
K2DRadius[UDex] Greater than 16
Then - Actions
Set Variable Set Knockback2DAngle = ((Knockback2DAngle + 45.00) mod 360.00)
Set Variable Set K2DCosD1[UDex] = (Cos(Knockback2DAngle))
Set Variable Set K2DSinD1[UDex] = (Sin(Knockback2DAngle))
Set Variable Set Knockback2DAngle = ((Knockback2DAngle + 90.00) mod 360.00)
Set Variable Set K2DCosD2[UDex] = (Cos(Knockback2DAngle))
Set Variable Set K2DSinD2[UDex] = (Sin(Knockback2DAngle))
Else - Actions
Custom script: endif
Else - Actions
Set Variable Set K2DDistanceLeft[UDex] = Knockback2DDistance
Set Variable Set Knockback2DDistance = (((1.00 + Knockback2DFriction) x Knockback2DDistance) / Knockback2DTime)
Set Variable Set K2DFriction[UDex] = ((Knockback2DDistance / Knockback2DTime) x ((1.00 - (1 - Knockback2DFriction)) x (K2DTimeout x K2DTimeout)))
Set Variable Set K2DVelocity[UDex] = (Knockback2DDistance x K2DTimeout)
-------- --------
Set Variable Set K2DKillTrees[UDex] = Knockback2DKillTrees
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
Knockback2DKillTrees Equal to True
Then - Actions
-------- Square the radius so we don't have to use SquareRoot when comparing distance. --------
Set Variable Set K2DDestRadius[UDex] = (Knockback2DDestRadius x Knockback2DDestRadius)
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Knockback2DDestRadius x 2.00) Greater than K2DMaxDestRadius
Then - Actions
-------- Update the size of the enumerating rect to compensate for the desired extra radius. --------
Set Variable Set K2DMaxDestRadius = (Knockback2DDestRadius x 2.00)
Custom script: call SetRect(udg_K2DRegion, 0.00, 0.00, udg_K2DMaxDestRadius, udg_K2DMaxDestRadius)
Else - Actions
Set Variable Set Knockback2DDestRadius = Knockback2DDefaultDestRadius
Else - Actions
-------- --------
Set Variable Set K2DAmphibious[UDex] = Knockback2DAmphibious
Set Variable Set K2DBounce[UDex] = Knockback2DBounces
Set Variable Set K2DCollision[UDex] = Knockback2DCollision
Set Variable Set K2DFreeze[UDex] = "false"
Set Variable Set K2DFXModel[UDex] = Knockback2DLoopFX
Set Variable Set K2DFXRate[UDex] = Knockback2DFXRate
Set Variable Set K2DFXTimeLeft[UDex] = Knockback2DFXRate
Set Variable Set K2DImpact[UDex] = Knockback2DOnImpact
Set Variable Set K2DOverride[UDex] = Knockback2DOverride
Set Variable Set K2DPause[UDex] = Knockback2DPause
Set Variable Set K2DSimple[UDex] = Knockback2DSimple
Set Variable Set K2DSource[UDex] = Knockback2DSource
Set Variable Set K2DTimeLeft[UDex] = Knockback2DTime
Set Variable Set K2DUnbiasedCollision[UDex] = Knockback2DUnbiasedCollision
Set Variable Set Knockback2DAmphibious = "false"
Set Variable Set Knockback2DBounces = Knockback2DDefaultBounce
Set Variable Set Knockback2DCollision = "0.00"
Set Variable Set Knockback2DFriction = Knockback2DDefaultFriction
Set Variable Set Knockback2DFXRate = Knockback2DDefaultFXRate
Set Variable Set Knockback2DGravity = Knockback2DDefaultGravity
Set Variable Set Knockback2DKillTrees = Knockback2DDefaultKillTrees
Set Variable Set Knockback2DLoopFX = Knockback2DDefaultFX
Custom script: set udg_Knockback2DOnImpact = null
Set Variable Set Knockback2DOverride = "false"
Set Variable Set Knockback2DPause = Knockback2DDefaultPause
Set Variable Set Knockback2DSimple = "false"
Set Variable Set Knockback2DSource = No unit
Set Variable Set Knockback2DUnbiasedCollision = "false"
Custom script: set udg_UDex = pdex
//TESH.scrollpos=0
//TESH.alwaysfold=0
function K2DItemCheckXY takes real x, real y returns boolean
    call SetItemPosition(udg_K2DItem, x, y)
    return GetWidgetX(udg_K2DItem) == x and GetWidgetY(udg_K2DItem) == y
endfunction

function K2DItemCheckAxis takes real x, real y returns boolean
    local real x2 = x*udg_K2DRadius[udg_UDex]
    local real y2 = y*udg_K2DRadius[udg_UDex]
    set x = udg_K2DX + x2
    set y = udg_K2DY + y2
    if K2DItemCheckXY(x, y) and not IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY) then
        set x = udg_K2DX - x2
        set y = udg_K2DY - y2
        return K2DItemCheckXY(x, y) and not IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY)
    endif
    return false
endfunction

function K2DItemCheck takes nothing returns boolean
    local boolean result = K2DItemCheckXY(udg_K2DX, udg_K2DY)
    
    //Only perform additional pathing checks if the unit has a larger collision.
    if result and udg_Knockback2DRobustPathing > 0 and udg_K2DRadius[udg_UDex] > 0 then

        //Check horizontal axis of unit to make sure nothing is going to collide
        set result = K2DItemCheckAxis(udg_K2DCosH[udg_UDex], udg_K2DSinH[udg_UDex])
        
        //Check vertical axis of unit to ensure nothing will collide
        set result = result and K2DItemCheckAxis(udg_K2DCos[udg_UDex], udg_K2DSin[udg_UDex])
        
        if result and udg_Knockback2DRobustPathing == 2 and udg_K2DRadius[udg_UDex] > 16 then

            //Check diagonal axis of unit if more thorough pathing is desired
            set result = K2DItemCheckAxis(udg_K2DCosD1[udg_UDex], udg_K2DSinD1[udg_UDex])
            set result = result and K2DItemCheckAxis(udg_K2DCosD2[udg_UDex], udg_K2DSinD2[udg_UDex])
        endif
    endif
    
    //Reset item so it won't interfere with the map
    call SetItemPosition(udg_K2DItem, udg_K2DMaxX, udg_K2DMaxY)
    call SetItemVisible(udg_K2DItem, false)
    
    return result
endfunction

function K2DItemFilter takes nothing returns boolean
    //Check for visible items, temporarily hide them and add them to the filter.
    if IsItemVisible(GetFilterItem()) then
        call SetItemVisible(GetFilterItem(), false)
        return true
    endif
    return false
endfunction
function K2DItemCode takes nothing returns nothing
    //Perform the item-pathing check only once, then unhide those filtered items
    if not udg_K2DItemsFound then
        set udg_K2DItemsFound = true
        set udg_K2DItemOffset = K2DItemCheck()
    endif
    call SetItemVisible(GetEnumItem(), true)
endfunction

function K2DKillDest takes nothing returns nothing
    local real x
    local real y
    //Handle destruction of debris
    set bj_destRandomCurrentPick = GetEnumDestructable()
    if GetWidgetLife(bj_destRandomCurrentPick) > 0.405 and IssueTargetOrder(udg_K2DDebrisKiller, udg_Knockback2DTreeOrDebris, bj_destRandomCurrentPick) then
        set x = GetWidgetX(bj_destRandomCurrentPick) - udg_K2DX
        set y = GetWidgetY(bj_destRandomCurrentPick) - udg_K2DY
        if x*x + y*y <= udg_K2DDestRadius[udg_UDex] then
            call KillDestructable(bj_destRandomCurrentPick)
        endif
    endif
endfunction

function K2DEnumDests takes nothing returns nothing
    call MoveRectTo(udg_K2DRegion, udg_K2DX, udg_K2DY)
    if udg_K2DKillTrees[udg_UDex] then
        call SetUnitX(udg_K2DDebrisKiller, udg_K2DX)
        call SetUnitY(udg_K2DDebrisKiller, udg_K2DY)
        call EnumDestructablesInRect(udg_K2DRegion, null, function K2DKillDest)
    endif
endfunction

function Knockback2DCheckXY takes real x, real y returns boolean
    set udg_K2DX = x + udg_K2DVelocity[udg_UDex]*udg_K2DCos[udg_UDex]
    set udg_K2DY = y + udg_K2DVelocity[udg_UDex]*udg_K2DSin[udg_UDex]
    if udg_K2DSimple[udg_UDex] then
        //A "pull" effect or a missile system does not require complex pathing.
        if udg_K2DX <= udg_K2DMaxX and udg_K2DX >= udg_K2DMinX and udg_K2DY <= udg_K2DMaxY and udg_K2DY >= udg_K2DMinY then
            call K2DEnumDests()
            return true
        endif
        return false
    elseif udg_K2DFlying[udg_UDex] then
        return not IsTerrainPathable(udg_K2DX, udg_K2DY, PATHING_TYPE_FLYABILITY)
    elseif not IsTerrainPathable(udg_K2DX, udg_K2DY, PATHING_TYPE_WALKABILITY) then
        call K2DEnumDests()
        set udg_K2DItemOffset = false
        call EnumItemsInRect(udg_K2DRegion, Filter(function K2DItemFilter), function K2DItemCode)
        if udg_K2DItemsFound then
            //If items were found, the check was already performed.
            set udg_K2DItemsFound = false
        else
            //Otherwise, perform the check right now.
            set udg_K2DItemOffset = K2DItemCheck()
        endif
        return udg_K2DItemOffset
    endif
    return udg_K2DAmphibious[udg_UDex] and not IsTerrainPathable(udg_K2DX, udg_K2DY, PATHING_TYPE_FLOATABILITY)
endfunction

function Knockback2DApplyAngle takes real angle returns nothing
    set angle = ModuloReal(angle, udg_Radians_Turn)
    set udg_K2DCos[udg_UDex] = Cos(angle)
    set udg_K2DSin[udg_UDex] = Sin(angle)
    set udg_K2DAngle[udg_UDex] = angle
    if udg_Knockback2DRobustPathing > 0 then
        set angle = ModuloReal(angle + udg_Radians_QuarterTurn, udg_Radians_Turn)
        set udg_K2DCosH[udg_UDex] = Cos(angle)
        set udg_K2DSinH[udg_UDex] = Sin(angle)
        if udg_Knockback2DRobustPathing == 2 and udg_K2DRadius[udg_UDex] > 16 then
            set angle = ModuloReal(angle + udg_Radians_QuarterPi, udg_Radians_Turn)
            set udg_K2DCosD1[udg_UDex] = Cos(angle)
            set udg_K2DSinD1[udg_UDex] = Sin(angle)
            set angle = ModuloReal(angle + udg_Radians_QuarterTurn, udg_Radians_Turn)
            set udg_K2DCosD2[udg_UDex] = Cos(angle)
            set udg_K2DSinD2[udg_UDex] = Sin(angle)
        endif
    endif
endfunction

function Knockback2DLooper takes nothing returns nothing
    local integer i = 0
    local unit u
    local real x
    local real y
    
    call PauseUnit(udg_K2DDebrisKiller, false)
    
    loop
        set i = udg_K2DNext[i]
        exitwhen i == 0
        set udg_UDex = i
        set udg_K2DTimeLeft[i] = udg_K2DTimeLeft[i] - udg_K2DTimeout
        set udg_K2DDistanceLeft[i] = udg_K2DDistanceLeft[i] - udg_K2DVelocity[i]
        set u = udg_UDexUnits[i]
        
        if udg_K2DTimeLeft[i] > 0.00 then
            if udg_K2DTimeLeft[i] < udg_K2DHeightThreshold[i] and udg_K2DHeightThreshold[i] != 0.00 then
                call SetUnitFlyHeight(u, GetUnitDefaultFlyHeight(u), GetUnitFlyHeight(u) - GetUnitDefaultFlyHeight(u)/udg_K2DHeightThreshold[i])
                set udg_K2DHeightThreshold[i] = 0.00
            endif
            if udg_K2DPause[i] then
                set x = udg_K2DLastX[i]
                set y = udg_K2DLastY[i]
            else
                set x = GetUnitX(u)
                set y = GetUnitY(u)
            endif
            
            if not Knockback2DCheckXY(x, y) then
                if not udg_K2DFreeze[i] and IsTriggerEnabled(udg_K2DImpact[i]) and TriggerEvaluate(udg_K2DImpact[i]) then
                    call TriggerExecute(udg_K2DImpact[i])
                endif
                if udg_K2DBounce[i] then
                    call Knockback2DApplyAngle(udg_Radians_Turn - udg_K2DAngle[i])
                    if not Knockback2DCheckXY(x, y) then
                        call Knockback2DApplyAngle(udg_K2DAngle[i] + bj_PI)
                        if not Knockback2DCheckXY(x, y) then
                            call Knockback2DApplyAngle(udg_Radians_Turn - udg_K2DAngle[i])
                            set udg_K2DX = x
                            set udg_K2DY = y
                        endif
                    endif
                else
                    set udg_K2DX = x
                    set udg_K2DY = y
                    set udg_K2DFreeze[i] = true
                endif
            endif
            call SetUnitX(u, udg_K2DX)
            call SetUnitY(u, udg_K2DY)
            set udg_K2DLastX[i] = udg_K2DX
            set udg_K2DLastY[i] = udg_K2DY
            if udg_K2DFXModel[i] != "" then
                set udg_K2DFXTimeLeft[i] = udg_K2DFXTimeLeft[i] - udg_K2DTimeout
                if udg_K2DFXTimeLeft[i] <= 0.00 then
                    set udg_K2DFXTimeLeft[i] = udg_K2DFXRate[i]
                    if udg_K2DFlying[i] then
                        call DestroyEffect(AddSpecialEffectTarget(udg_K2DFXModel[i], u, "origin"))
                    else
                        call DestroyEffect(AddSpecialEffect(udg_K2DFXModel[i], udg_K2DX, udg_K2DY))
                    endif
                endif
            endif
            if udg_K2DCollision[i] >= 0.00 then
                set udg_Knockback2DSource = u
                call GroupEnumUnitsInRange(bj_lastCreatedGroup, udg_K2DX, udg_K2DY, 200.00, null)
                call GroupRemoveUnit(bj_lastCreatedGroup, u)
                loop
                    set udg_Knockback2DUnit = FirstOfGroup(bj_lastCreatedGroup)
                    exitwhen udg_Knockback2DUnit == null
                    call GroupRemoveUnit(bj_lastCreatedGroup, udg_Knockback2DUnit)
                    
                    if IsUnitInRange(udg_Knockback2DUnit, u, udg_K2DCollision[i]) and udg_K2DFlying[i] == IsUnitType(udg_Knockback2DUnit, UNIT_TYPE_FLYING) and (not IsUnitType(udg_Knockback2DUnit, UNIT_TYPE_STRUCTURE)) and not IsUnitType(udg_Knockback2DUnit, UNIT_TYPE_DEAD) and (udg_K2DUnbiasedCollision[i] or IsUnitAlly(udg_Knockback2DUnit, GetOwningPlayer(u))) and TriggerEvaluate(gg_trg_Knockback_2D) then
                        set udg_Knockback2DAngle = bj_RADTODEG * Atan2(GetUnitY(udg_Knockback2DUnit) - udg_K2DY, GetUnitX(udg_Knockback2DUnit) - udg_K2DX)
                        set udg_Knockback2DDistance = udg_K2DDistanceLeft[i]
                        set udg_Knockback2DBounces = udg_K2DBounce[i]
                        set udg_Knockback2DCollision = udg_K2DCollision[i]
                        if udg_K2DHeight[i] != 0.00 then
                            set udg_Knockback2DHeight = GetUnitFlyHeight(u) - GetUnitDefaultFlyHeight(u)
                        endif
                        set udg_Knockback2DLoopFX = udg_K2DFXModel[i]
                        set udg_Knockback2DTime = udg_K2DTimeLeft[i]
                        set udg_Knockback2DUnbiasedCollision = udg_K2DUnbiasedCollision[i]
                        call TriggerExecute(gg_trg_Knockback_2D)
                        set udg_Knockback2DSource = u //in case of a recursive knockback
                    endif
                endloop
            endif
            set udg_K2DVelocity[i] = udg_K2DVelocity[i] - udg_K2DFriction[i]
        else
            call TriggerExecute(gg_trg_Knockback_2D_Destroy)
        endif
    endloop
    set u = null
    
    //Disable dummy after the loop finishes so it doesn't interfere with the map
    call PauseUnit(udg_K2DDebrisKiller, true)
endfunction

//===========================================================================
function StartKnockback2DTimer takes nothing returns nothing
    call TimerStart(udg_K2DTimer, udg_K2DTimeout, true, function Knockback2DLooper)
endfunction
function InitTrig_Knockback_2D_System takes nothing returns nothing
endfunction
For this demo, I want units to never take damage. There doesn't need to be any damage taken, anyway, since it's only about the knockback.
On Damage
Events
Game - PDD_damageEventTrigger becomes Equal to 1.00
Conditions
Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
Or - Any (Conditions) are true
Conditions
Tauren_Shockwave[(Custom value of PDD_source)] Equal to True
Tauren_WarStomp[(Custom value of PDD_source)] Equal to True
Then - Actions
Set Variable Set CenterPoint = (Position of PDD_source)
Set Variable Set TargetPoint = (Position of PDD_target)
Set Variable Set Knockback2DAngle = (Angle from CenterPoint to TargetPoint)
Custom script: call RemoveLocation(udg_CenterPoint)
Custom script: call RemoveLocation(udg_TargetPoint)
Set Variable Set Knockback2DTime = "0.50"
Set Variable Set Knockback2DDistance = "75.00"
Set Variable Set Knockback2DUnit = PDD_target
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
Tauren_WarStomp[(Custom value of PDD_source)] Equal to True
Then - Actions
-------- For War Stomp, add a height factor --------
Set Variable Set Knockback2DHeight = "250.00"
Set Variable Set Knockback2DDistance = "100.00"
Else - Actions
Set Variable Set Knockback2DDistance = "300.00"
Trigger - Run Knockback_2D <gen> (ignoring conditions)
Else - Actions
-------- Deleting the next line will re-enable damage in the map --------
Set Variable Set DamageEventAmount = "0.00"
For this demo, I want units to never take damage. There doesn't need to be any damage taken, anyway, since it's only about the knockback.
On Damage Copy
Events
Game - PDD_damageEventTrigger becomes Equal to 1.00
Conditions
Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
IsDamageSpell Equal to False
(Owner of DamageEventSource) Equal to Player 1 (Red)
Then - Actions
-------- --------
-------- There are four required variables when issuing a knockback --------
-------- --------
-------- 1. Knockback2DAngle -------- this is the direction angle the unit is knocked back (in degrees) --------
-------- 2. Knockback2DTime -------- this is how long the unit will be knocked back (in seconds) --------
-------- 3. Knockback2DDistance -------- this is how far the unit will be knocked back --------
-------- 4. Knockback2DUnit -------- this is the unit being knocked back --------
-------- --------
-------- When all four variables are set, you can run the Knockback 2D trigger, ignoring conditions --------
-------- --------
Set Variable Set CenterPoint = (Position of PDD_source)
Set Variable Set TargetPoint = (Position of PDD_target)
Set Variable Set Knockback2DAngle = (Angle from CenterPoint to TargetPoint)
Custom script: call RemoveLocation(udg_CenterPoint)
Custom script: call RemoveLocation(udg_TargetPoint)
Set Variable Set Knockback2DTime = "0.90"
Set Variable Set Knockback2DDistance = "500.00"
Set Variable Set Knockback2DUnit = PDD_target
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Owner of PDD_source) Not equal to (Owner of PDD_target)
Then - Actions
-------- --------
-------- There are optional variables you can consider when issuing a knockback --------
-------- If they are not set, "0.00, false, null" or their default states assigned in the Knockback 2D Config trigger will be used --------
-------- --------
-------- Knockback2DAmphibious -------- Allows the unit to pass over deep water, but it is more performance-intensive --------
-------- -------- If you aren't ToolOrDie from TheHiveWorkshop, you probably won't use this --------
-------- Knockback2DBounces -------- if the unit will bounce off of walls or remain stunned there. --------
-------- --------
-------- Knockback2DCollision -------- You can specify the collision radius of units to be adjacently knocked back if you want --------
-------- -------- A value of 0 will require the units' collision sizes to overlap to knock back --------
-------- -------- A value greater than 0 will allow that much space between the units to still permit the knockback --------
-------- -------- A value less than 0 will disable collision checking altogether. --------
-------- --------
-------- Knockback2DDestRadius -------- If debris is to be killed, how far away must it be? --------
-------- Knockback2DFriction -------- How quickly the unit will slow down from its initial speed. --------
-------- Knockback2DFX -------- What kind of special effect will occasionally be played on the ground of the unit --------
-------- Knockback2DFXRate -------- How often should the effect appear? --------
-------- Knockback2DGravity -------- If you want to specify a custom gravity for each knockback, you can --------
-------- Knockback2DHeight -------- How high you want the unit to go during the knockback --------
-------- Knockback2DKillTrees -------- If you want surrounding trees to die, this is for you --------
-------- Knockback2DOnImpact -------- this trigger is run when the unit hits a wall or structure. --------
-------- -------- If it is bouncing, it can hit multiple walls and fire this trigger multiple times --------
-------- -------- The trigger will not run if it is off, so you can use this if you only want it to run on the first bounce --------
-------- Knockback2DOverride -------- Set this to true to prevent future knockbacks from interrupting this one --------
-------- Knockback2DPause -------- confines the unit to its knockback velocity (no running to change course) --------
-------- Knockback2DSimple -------- Only checks to make sure unit movement is within the map bounds --------
-------- Knockback2DSource -------- If you need to store this unit to deal damage on-impact or within the timer loop --------
-------- Knockback2DUnbiasedCollision -------- Should adjacent knockbacks consider alliances or be neutral? --------
-------- --------
Set Variable Set Knockback2DAmphibious = "true"
Set Variable Set Knockback2DBounces = "false"
Set Variable Set Knockback2DCollision = "16.00"
Set Variable Set Knockback2DDestRadius = "128.00"
Set Variable Set Knockback2DGravity = "0.67"
Set Variable Set Knockback2DHeight = "137.00"
Set Variable Set Knockback2DKillTrees = "false"
Set Variable Set Knockback2DOnImpact = On_Impact <gen>
Set Variable Set Knockback2DOverride = "true"
Set Variable Set Knockback2DPause = "true"
Set Variable Set Knockback2DSimple = "true"
Set Variable Set Knockback2DSource = PDD_source
Set Variable Set Knockback2DUnbiasedCollision = "false"
Else - Actions
-------- Allied units shouldn't allow collision with each other, but for the sake of the demo let's make it interesting --------
Set Variable Set Knockback2DCollision = "32.00"
-------- Also make it so that enemies will bounce with these experiments --------
Set Variable Set Knockback2DUnbiasedCollision = "true"
Set Variable Set Knockback2DLoopFX = "Abilities\Weapons\FaerieDragonMissile\FaerieDragonMissile.mdl"
Set Variable Set Knockback2DFXRate = "0.20"
-------- --------
-------- When all variables are set, run the Knockback 2D trigger, checking conditions if you want to be safe --------
-------- --------
Trigger - Run Knockback_2D <gen> (checking conditions)
Else - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
Or - Any (Conditions) are true
Conditions
Tauren_Shockwave[(Custom value of PDD_source)] Equal to True
Tauren_WarStomp[(Custom value of PDD_source)] Equal to True
Then - Actions
Set Variable Set CenterPoint = (Position of PDD_source)
Set Variable Set TargetPoint = (Position of PDD_target)
Set Variable Set Knockback2DAngle = (Angle from CenterPoint to TargetPoint)
Custom script: call RemoveLocation(udg_CenterPoint)
Custom script: call RemoveLocation(udg_TargetPoint)
Set Variable Set Knockback2DTime = "0.50"
Set Variable Set Knockback2DDistance = "75.00"
Set Variable Set Knockback2DUnit = PDD_target
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
Tauren_WarStomp[(Custom value of PDD_source)] Equal to True
Then - Actions
-------- For War Stomp, add a height factor --------
Set Variable Set Knockback2DHeight = "250.00"
Set Variable Set Knockback2DDistance = "100.00"
Else - Actions
Set Variable Set Knockback2DDistance = "300.00"
Trigger - Run Knockback_2D <gen> (ignoring conditions)
Else - Actions
-------- Deleting the next line will re-enable damage in the map --------
Set Variable Set DamageEventAmount = "0.00"
On Impact
Events
Conditions
Actions
Special Effect - Create a special effect attached to the origin (Unexpected type: 'attachpoint') of UDexUnits[UDex] using Objects\Spawnmodels\Undead\ImpaleTargetDust\ImpaleTargetDust.mdl
Special Effect - Destroy (Last created special effect)
On Spell Cast
Events
Unit - A unit owned by Player 1 (Red) . Starts the effect of an ability
Unit - A unit Starts the effect of an ability
Conditions
Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Ability being cast) Equal to Dummy War Stomp (War Stomp)
Then - Actions
Set Variable Set Tauren_WarStomp[(Custom value of (Triggering unit))] = "true"
Else - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
Or - Any (Conditions) are true
Conditions
(Ability being cast) Equal to Shield Smash (Storm Bolt)
(Ability being cast) Equal to
Then - Actions
Set Variable Set Tauren_Shockwave[(Custom value of (Triggering unit))] = "true"
Else - Actions
On Spell Stop
Events
Unit - A unit owned by Player 1 (Red) . Stops casting an ability
Unit - A unit Stops casting an ability
Conditions
Actions
Unit - Reset ability cooldowns for (Triggering unit) .
Unit - Set mana of (Triggering unit) to 100 %
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
Or - Any (Conditions) are true
Conditions
(Ability being cast) Equal to Shield Smash (Storm Bolt)
(Ability being cast) Equal to
Then - Actions
-------- In case the unit had other damaging spells, we don't want those spells to trigger an unwanted knockback --------
Set Variable Set Tauren_Shockwave[(Custom value of (Triggering unit))] = "false"
Else - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Ability being cast) Equal to Dummy War Stomp (War Stomp)
Then - Actions
-------- Same goes for here --------
Set Variable Set Tauren_WarStomp[(Custom value of (Triggering unit))] = "false"
Else - Actions
Test
Events
Unit - A unit owned by Player 1 (Red) . Is issued an order targeting a point
Unit - A unit owned by Player 1 (Red) . Is issued an order targeting an object
Conditions
Actions
Unit - Add Ghost (Visible) to (Triggering unit)
Custom script: call UnitAddAbility(GetTriggerUnit(), 'Aloc')
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Target unit of issued order) Not equal to No unit
Then - Actions
Set Variable Set TargetPoint = (Position of (Target unit of issued order))
Else - Actions
Set Variable Set TargetPoint = (Target point of issued order)
Custom script: call GroupEnumUnitsInRangeOfLoc(udg_LeaklessGroup, udg_TargetPoint, 128.00, null)
Unit Group - Pick every unit in LeaklessGroup and do (Actions)
Loop - Actions
Unit - Add Ghost (Visible) to (Picked unit)
Unit - Hide (Picked unit)
Unit - Move (Triggering unit) instantly to TargetPoint
Unit - Remove Ghost (Visible) from (Triggering unit)
Custom script: call RemoveLocation(udg_TargetPoint)
Set Variable Set TargetPoint = (Position of (Triggering unit))
Special Effect - Create a special effect at TargetPoint using Abilities\Spells\NightElf\Blink\BlinkTarget.mdl
Special Effect - Destroy (Last created special effect)
Custom script: call RemoveLocation(udg_TargetPoint)
Wait 0.00 seconds
Unit Group - Pick every unit in LeaklessGroup and do (Actions)
Loop - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Picked unit) Not equal to (Triggering unit)
Then - Actions
Unit - Remove Ghost (Visible) from (Picked unit)
Else - Actions
Unit - Unhide (Picked unit)
CREDITS:

Vexorian for the handle timer function, Captain Griffen for the timer attach function
http://www.wc3c.net/showthread.php?t=89072

Silvenon for the Knockback function
http://www.hiveworkshop.com/forums/jass-functions-413/knockback-unit-35545/
So, This is my first vJASS spell. It's quite a simple spell (and also banal, not original at all), but it was useful as training for me
Since i made it highly customizable, i thought it was a good idea to share it with you, hoping it'll be useful to someone.


Importing this spell is not hard, You need:

- A Dummy unit for the ending part (cast the stunning spell)
- A Dummy unit for the pathchecker function (could be the same kind of unit of the other Dummy, just make sure it's invulnerable and has No model)
- A Windwalk spell with duration set at 0 (in order to make it permanent), this spell is needed for the pathchecker function
- A spell based on Thunderbolt for the stunning part
You can find all theese spells and units and their settings in the object editor, so you can just copy/paste them
You also need to change the spells and units IDs according to the ones in your map (they are in the config Trigger)
Finally you can just copy all the triggers, except thoose in the Test folder

All the options you need to modify are in the Config Trigger. For More Customization options i divided the execution of the Charge (ChargeExec trigger) in various methods that can be easily customized (in particular you can modify the Charge Acceleration through the function in ChargeExec trigger). Plus you may want to check the Knockback spell since it's not made by me.

Just a warning:
If you are going to use this on a model not based on the blademaster, then you will need to change the index of the walk animation (the one in SetUnitAnimationByIndex) in the ChargeInit trigger, also the slam animation of the other model (if present) may not be suitable with the Charge spell (it may look weird while moving, like for example the Tauren slam animation), so you would like to change the AlmostCharge method in ChargeExec to whatever you want.
//TESH.scrollpos=0
//TESH.alwaysfold=0
// **************************************************************************
// ** **
// ** Mathematical Functions **
// ** ————————————— **
// ** **
// ** Functions used instead of BJs to calculate some values **
// ** **
// ** By: Majin **
// ** 
// ** **
// **************************************************************************

library Math
    function GetDistance takes real ax, real ay, real bx, real by returns real
        return SquareRoot((bx-ax)*(bx-ax)+(by-ay)*(by-ay))
    endfunction
    
    function PolarProjectionx takes real ax, real dist, real angle returns real
        return ax + dist * Cos(angle)
    endfunction
    
    function PolarProjectiony takes real ay, real dist, real angle returns real
        return ay + dist * Sin(angle)
    endfunction

    function GetAngle takes real ax, real ay, real bx, real by returns real
        return Atan2(by-ay, bx-ax)
    endfunction    
    
    function RAbs takes real a returns real
        if (a >= 0) then
            return a
        else
            return -a
        endif
    endfunction
    
    function AntiLeak takes nothing returns boolean
        return true
    endfunction

endlibrary
//TESH.scrollpos=18
//TESH.alwaysfold=0
//Functions used to handle timers. Credits to Vexorian and Captain Griffen
//Check http://www.wc3c.net/showthread.php?t=89072 for more informations
library HandleTimers

    globals
        private timer array timers
        private integer N = 0
    endglobals

    function NewTimer takes nothing returns timer
        if (N==0) then
            return CreateTimer()
        endif
        set N=N-1
        return timers[N]
    endfunction

    function ReleaseTimer takes timer t returns nothing
        call PauseTimer(t)
        if (N==8191) then
            debug call BJDebugMsg("Warning: Timer stack is full, destroying timer!!")
            //stack is full, the map already has much more troubles than the chance of bug
            call DestroyTimer(t)
        else
            set timers[N]=t
            set N=N+1
        endif    
    endfunction

    function TimerAttach takes timer t, real time, real value, code func returns nothing
        call TimerStart(t, value, false, null)
        call PauseTimer(t)
        call TimerStart(t, time, false, func)
    endfunction

// ONLY call on an expired timer.
    function GetTimerInt takes timer t returns integer
        return R2I(TimerGetRemaining(t) + 0.5)
    endfunction
endlibrary    
//TESH.scrollpos=0
//TESH.alwaysfold=0
// **************************************************************************
// ** **
// ** Check Pathability Function **
// ** ————————————— **
// ** **
// ** A Function that checks if a unit can walk over a certain area **
// ** (Ignores other units but not buildings, trees and other obstacles) **
// ** **
// ** By: Majin **
// ** 
// ** **
// **************************************************************************

library Walkable initializer init requires ChargeConfig, Math
    globals
        unit pathchecker
        rect pathrect
        filterfunc truefilter
    endglobals
    
    function HideItems takes nothing returns nothing
        call SetItemVisible(GetEnumItem(), false)    
    endfunction
    
    function UnHideItems takes nothing returns nothing
        call SetItemVisible(GetEnumItem(), true)    
    endfunction
    
    function IsPointWalkable takes real x, real y returns boolean
        local boolean b
        call SetUnitPosition(pathchecker,x,y)
        set b=((GetUnitX(pathchecker)-x)*(GetUnitX(pathchecker)-x)+((GetUnitY(pathchecker)-y)*(GetUnitY(pathchecker)-y))<=1)
        if (b==false) then
            call MoveRectTo(pathrect, x, y)
            call EnumItemsInRect(pathrect,truefilter,function HideItems)
            call SetUnitPosition(pathchecker,x,y)
            set b=((GetUnitX(pathchecker)-x)*(GetUnitX(pathchecker)-x)+((GetUnitY(pathchecker)-y)*(GetUnitY(pathchecker)-y))<=1) 
            call EnumItemsInRect(pathrect,truefilter,function UnHideItems)
        endif
        return b
    endfunction

    function init takes nothing returns nothing
        local real x = GetRectMinX(bj_mapInitialPlayableArea)
        local real y = GetRectMinY(bj_mapInitialPlayableArea)
        set pathrect=Rect(x,y,x+200.00,y+200.00)
        set pathchecker=CreateUnit( Player(PLAYER_NEUTRAL_PASSIVE), PATHCHECKERID, 0, 0, 0)
        set truefilter=Filter(function AntiLeak)
        call UnitAddAbility(pathchecker, SPELLPATHID)
        call IssueImmediateOrder( pathchecker, "windwalk" )
    endfunction
endlibrary
//TESH.scrollpos=194
//TESH.alwaysfold=0
library Knockback initializer Init requires HandleTimers, Walkable

// **************************************************************************
// ** **
// ** Knockback(Ex) **
// ** ————————————— **
// ** **
// ** A function made for efficient knockbacking **
// ** **
// ** By: Silvenon **
// ** **
// **************************************************************************

//=======================================//
//Credits to PitzerMike for this function//
//=======================================//

private function TreeFilter takes nothing returns boolean
    local destructable d = GetFilterDestructable()
    local boolean i = IsDestructableInvulnerable(d)
    local unit u = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), DUMMYID, GetWidgetX(d), GetWidgetY(d), 0)
    local boolean result = false

    call UnitAddAbility(u, 'Ahrl')

    if i then
        call SetDestructableInvulnerable(d, false)
    endif

    set result = IssueTargetOrder(u, "harvest", d)
    call RemoveUnit(u)

    if i then
      call SetDestructableInvulnerable(d, true)
    endif

    set u = null
    set d = null
    return result
endfunction

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

globals
    private timer Tim = CreateTimer()
    private integer Total = 0
    private boolexpr Cond = null

    private integer array Ar
    private boolean array BoolAr

    private real MAX_X
    private real MAX_Y
    private real MIN_X
    private real MIN_Y
endglobals

private constant function Interval takes nothing returns real
    return 0.04
endfunction

private function KillTree takes nothing returns nothing
    if BoolAr[0] then
        call KillDestructable(GetEnumDestructable())
    else
        set BoolAr[1] = true
    endif
endfunction

public struct Data
    unit u
    real d1
    real d2

    real sin
    real cos

    real r

    string s = ""
    effect e = null

    static method create takes unit u, integer q, real d, real a, real r, integer t, string s, string p returns Data
        local Data dat = Data.allocate()

        set dat.u = u
        set dat.d1 = 2 * d / (q + 1)
        set dat.d2 = dat.d1 / q

        set dat.sin = Sin(a)
        set dat.cos = Cos(a)

        set dat.r = r

        if s != "" and s != null then
            if t == 2 then
                if p != "" and p != null then
                    set dat.e = AddSpecialEffectTarget(s, u, p)
                else
                    set dat.e = AddSpecialEffectTarget(s, u, "chest")
                endif
            elseif t == 1 then
                set dat.s = s
            endif
        endif

        call SetUnitPosition(u, GetUnitX(u), GetUnitY(u))
        call PauseUnit(u, true)

        if Total == 0 then
            call TimerStart(Tim, Interval(), true, function Data.Execute)
        endif

        set Total = Total + 1
        set Ar[Total - 1] = dat

        return dat
    endmethod

    static method Execute takes nothing returns nothing
        local Data dat
        local integer i = 0
        local real x
        local real y
        local rect r
        local real rad

        loop
            exitwhen i >= Total
            set dat = Ar[i]

            if dat.s != "" and dat.s != null then
                set x = GetUnitX(dat.u)
                set y = GetUnitY(dat.u)

                call DestroyEffect(AddSpecialEffect(dat.s, x, y))

                set x = x + dat.d1 * dat.cos
                set y = y + dat.d1 * dat.sin
            else
                set x = GetUnitX(dat.u) + dat.d1 * dat.cos
                set y = GetUnitY(dat.u) + dat.d1 * dat.sin
            endif

            if dat.r != 0 then
                set BoolAr[0] = dat.r > 0

                set rad = dat.r

                if not BoolAr[0] then
                    set rad = rad * (-1)
                endif

                set r = Rect(x - rad, y - rad, x + rad, y + rad)

                call EnumDestructablesInRect(r, Cond, function KillTree)
                call RemoveRect(r)

                set r = null
            endif

            if (x < MAX_X and y < MAX_Y and x > MIN_X and y > MIN_Y) and not BoolAr[1] and (IsPointWalkable(x, y)) then
                call SetUnitX(dat.u, x)
                call SetUnitY(dat.u, y)
            endif

            set dat.d1 = dat.d1 - dat.d2

            if dat.d1 <= 0 or (x > MAX_X or y > MAX_Y or x < MIN_X or y < MIN_Y) or BoolAr[1] or not(IsPointWalkable(x, y)) then
                set Ar[i] = Ar[Total - 1]
                set Total = Total - 1

                call dat.destroy()
            endif

            set i = i + 1
        endloop

        if Total == 0 then
            call PauseTimer(Tim)
        endif
    endmethod

method onDestroy takes nothing returns nothing
        if .e != null then
            call DestroyEffect(.e)
        endif

        call PauseUnit(.u, false)

        set BoolAr[0] = false
        set BoolAr[1] = false
    endmethod
endstruct

function KnockbackEx takes unit u, real d, real a, real w, real r, integer t, string s, string p returns nothing
    call Data.create(u, R2I(w / Interval()), d, a, r, t, s, p)
endfunction

function Knockback takes unit u, real d, real a, real w returns nothing
    call Data.create(u, R2I(w / Interval()), d, a, 0, 0, "", "")
endfunction

private function Init takes nothing returns nothing
    set Cond = Filter(function TreeFilter)

    set BoolAr[0] = false
    set BoolAr[1] = false

    set MAX_X = GetRectMaxX(bj_mapInitialPlayableArea) - 64
    set MAX_Y = GetRectMaxY(bj_mapInitialPlayableArea) - 64
    set MIN_X = GetRectMinX(bj_mapInitialPlayableArea) + 64
    set MIN_Y = GetRectMinY(bj_mapInitialPlayableArea) + 64
endfunction

endlibrary
//TESH.scrollpos=22
//TESH.alwaysfold=0
// **************************************************************************
// ** **
// ** Charge **
// ** ————————————— **
// ** **
// ** A simple Charge Spell **
// ** **
// ** By: Majin **
// ** 
// ** **
// **************************************************************************

library ChargeConfig

    globals
    //CHECK THE CHARGEEXEC TRIGGER FOR MORE OPTIONS
    //ID CONFIGURATIONS FOR SPELLS AND DUMMY UNITS
    //ID of the Charge spell 
        constant integer SPELLID = 'A017'

    //ID of the dummy unit used for the attack at the end of the charge. Set this to 0 for no unit
        constant integer DUMMYID = 'h00D'
        
    //ID of the spell to be casted by the dummy unit once the charge is complete (Has to be a spell with
    //a Target). Set this to 0 for no spell. The Spell effect depends on the level of the Charge Spell
    //So it's advisable to set the number of levels of this spell at the same value of the level of the
    //Charge Spell
        constant integer DUMMYSPELLID = 'A015'
        
    //Order String for the spell to be casted by the dummy unit
        constant string SPELLORDERID = "thunderbolt"

    //SPECIAL EFFECTS CONFIGURATION
    //You can set this to a non existand model (or change the code of the spell) if you don't want that
    //effect

    //Special Effect attached on the unit (in this example it will look like a red trail)
        constant string ATTACHEDEFFECT = "Abilities\\Weapons\\PhoenixMissile\\Phoenix_Missile_mini.mdl"
        
    //Special Effect created by the unit while walking
        constant string WALKEFFECT = "Objects\\Spawnmodels\\Undead\\ImpaleTargetDust\\ImpaleTargetDust.mdl"

    //Special Effect used at the end of the Charge
        constant string ENDINGEFFECT = "Abilities\\Spells\\Orc\\WarStomp\\WarStompCaster.mdl"

    //NUMERICAL SETTINGS

    //Charge Starting Speed
        constant real STARTSPEED = 20.00

    //Max Speed that can be reached by the Caster unit while charging
        constant real MAXSPEED = 100.00

    //Damage Dealt at the end of the Charge (0 for no damage). DEPENDS ON LEVEL
        constant real CHARGEDAMAGE = 125.00
        
    //Minimum Distance at where a unit can Charge (0 for no min distance)
    //Make sure the dummy spell has a longer distance than this
        constant real MINDISTANCE = 400.00

    //Maximum Distance at where a unit can Charge (0 for no max distance)
    //This is mainly used to interrupt the charge if the target unit gets teleported somewhere else 
    //Make sure the dummy spell has a distance equal or less than this number
        constant real MAXDISTANCE = 1200.00
        
    //KNOCKBACK SETTINGS
    //Theese settings refer to the Knock trigger which is not made by me but by Silvenon. If you want
    //to know more about this script, got to 
    //http://www.hiveworkshop.com/forums/jass-functions-413/knockback-unit-35545/
    //Special Effect created by the knockback
        constant string KNOCKEFFECT = "Objects\\Spawnmodels\\Undead\\ImpaleTargetDust\\ImpaleTargetDust.mdl"

    //The Distance of the Knockback effect. DEPENDS ON LEVEL
        constant real KNOCKDISTANCE = 50.00
        
    //The Duration of the Knockback effect
        constant real KNOCKDURATION = 1.5
        
    //Tree Destroying effect
    //If you want trees destroyed behind your target while he's knocked back, then set this to true
    //Otherwise set this to false. See the Knock Trigger for more configuration options
        constant boolean KNOCKTREECHECK = true

    //Knockback Effect
    //This is the effect played on the Knocked Back Unit. If you set this to 0 then no effect will be played
    //If you set this to 1 then the effect set on the KnockEffect() function is played as a periodic effect
    //If you set this to 2 then the effect will be attached on the unit and destroyed once the knocback ends
        constant integer KNOCKPLAYEFFECT = 1
        
    //Attachement point of the effect played during the knockback. Default is "chest"
        constant string KNOCKATTACH = "Foot"
        
    //You may want to check the ChargeExec trigger for more Configuration Options

    //PATCCHECKER SETTINGS
    //ID of the dummy unit used for the path checker function (has to be an invulnerable locusted unit with No model)
        constant integer PATHCHECKERID = 'h00D'
     
    //ID of the permanent windwalk spell used for the path checker function
        constant integer SPELLPATHID = 'A016'
    endglobals
    
    function KnockTree takes nothing returns real
        if (KNOCKTREECHECK==true) then
            return 150.00
        endif
            return 0.00
    endfunction
endlibrary
//TESH.scrollpos=269
//TESH.alwaysfold=0
// **************************************************************************
// ** **
// ** Charge **
// ** ————————————— **
// ** **
// ** A simple Charge Spell **
// ** **
// ** By: Majin **
// ** 
// ** **
// **************************************************************************

library ChargeExec requires Knockback

    struct ChargeLoop
        private real ChargeTargetx
        private real ChargeTargety
        private real ChargeEndx
        private real ChargeEndy
        private real ChargeLocx
        private real ChargeLocy
        private real ChargeNextx
        private real ChargeNexty
        private unit ChargeTarget
        private unit ChargeCaster
        private real ChargeAngle
        private real ChargeDistance
        private effect ChargeEffect
        private timer ChargeTimer
        private boolean ChargeCond = false
        private integer SpellLvl
        
        //START OF CONFIGURATION METHODS
        
        //With this method you can set the "acceleration rate" (Physicists  Forgive me) of the charge.
        //You can use any kind of numeric function (for example this.ChargeDistance * 2.00 will double
        //The speed at every loop)
        private method ChangeDistance takes nothing returns real
            return this.ChargeDistance + 1.00
        endmethod
        //END OF CONFIGURATION METHODS
        
        //START OF CUSTOMIZABLE METHODS
        
        //This method sets the conditions when to activate the AlmostCharge method. In particular
        //You may be interested in changing the distance at where the condition is true. 
        //In this Example it will be activated when the Caster is 16x times the Charge Speed Far away
        //From the target
        private method AlmostChargeCond takes nothing returns boolean
            return ((GetDistance(this.ChargeLocx, this.ChargeLocy, this.ChargeEndx,  this.ChargeEndy) < ( this.ChargeDistance * 16.00 )) and this.ChargeCond == false)
        endmethod
        
        //Actions to take when the Charge is almost completed. In this example the caster will play
        //The slam animation (Being a Blademaster, it will jump in the air while attacking)
        private method AlmostCharge takes nothing returns nothing
            set this.ChargeCond = true
            call SetUnitTimeScale( this.ChargeCaster, 2.00 )
            call SetUnitAnimation( this.ChargeCaster, "attack" )
            call QueueUnitAnimation( this.ChargeCaster, "stand")
        endmethod
        
        //Actions to take when the Caster reaches its target and the charge is completed. 
        //In this example the target unit will be stunned and you will see a Thunderclap effect on the ground
        private method CompleteCharge takes nothing returns nothing
            local effect tempEffect
            local unit dummy
            local real angle=GetAngle(this.ChargeLocx, this.ChargeLocy, this.ChargeEndx, this.ChargeEndy)
            
            set this.ChargeLocx = this.ChargeNextx
            set this.ChargeLocy = this.ChargeNexty
            set this.ChargeNextx = PolarProjectionx(this.ChargeLocx, this.ChargeDistance, this.ChargeAngle)
            set this.ChargeNexty = PolarProjectiony(this.ChargeLocy, this.ChargeDistance, this.ChargeAngle)
            
            call DestroyEffect(AddSpecialEffect( WALKEFFECT, this.ChargeLocx, this.ChargeLocy ))
            
            call SetUnitX( this.ChargeCaster, this.ChargeEndx )
            call SetUnitY( this.ChargeCaster, this.ChargeEndy )
            
            set dummy = CreateUnit( GetOwningPlayer(this.ChargeCaster), DUMMYID, this.ChargeLocx, this.ChargeLocy, 0 )
            call UnitAddAbility( dummy, DUMMYSPELLID )
            call SetUnitAbilityLevel(dummy, DUMMYSPELLID, this.SpellLvl)
            call IssueTargetOrder( dummy, SPELLORDERID, this.ChargeTarget )
            call UnitApplyTimedLife( dummy, 'BTLF', 1.00)
            
            call DestroyEffect(AddSpecialEffect( ENDINGEFFECT, this.ChargeLocx, this.ChargeLocy ))
            
            call UnitDamageTarget( this.ChargeCaster, this.ChargeTarget, CHARGEDAMAGE*this.SpellLvl, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_UNIVERSAL, WEAPON_TYPE_WHOKNOWS )
            call PauseUnit( this.ChargeCaster, false )
            //This is the Knockback effect, see the Knock Trigger for more customization options
            call KnockbackEx(this.ChargeTarget, KNOCKDISTANCE*this.SpellLvl, angle, KNOCKDURATION, KnockTree(), KNOCKPLAYEFFECT, KNOCKEFFECT, KNOCKATTACH)
            call IssueTargetOrder( this.ChargeCaster, "attack", this.ChargeTarget )
            
            set dummy = null
        endmethod

        //What to do during the charge, the unit is moved, an effect is placed on the ground and
        //the charging speed is increased
        private method ContinueCharge takes nothing returns nothing
            call DestroyEffect(AddSpecialEffect( WALKEFFECT, this.ChargeLocx, this.ChargeLocy ))
            
            call SetUnitX(this.ChargeCaster, this.ChargeNextx)
            call SetUnitY(this.ChargeCaster, this.ChargeNexty)
            
            call SetUnitFacing(this.ChargeCaster, bj_RADTODEG * GetAngle(this.ChargeNextx, this.ChargeNexty, this.ChargeTargetx, this.ChargeTargety))
            
            set this.ChargeLocx = this.ChargeNextx
            set this.ChargeLocy = this.ChargeNexty
            set this.ChargeNextx = PolarProjectionx(this.ChargeLocx, this.ChargeDistance, this.ChargeAngle)
            set this.ChargeNexty = PolarProjectiony(this.ChargeLocy, this.ChargeDistance, this.ChargeAngle)
                        
            if (this.ChargeDistance <= MAXSPEED) then
                set this.ChargeDistance = this.ChangeDistance()
            endif
        endmethod
        
        //END OF CUSTOMIZABLE METHODS
        
        //START OF OTHER METHODS
        //This is the main method executed during the charge
        public static method ChargeActions takes nothing returns nothing
            local ChargeLoop l=GetTimerInt(GetExpiredTimer())
            
            set l.ChargeTargetx = GetUnitX(l.ChargeTarget)
            set l.ChargeTargety = GetUnitY(l.ChargeTarget)
            set l.ChargeEndx = PolarProjectionx(l.ChargeTargetx, 100.00, GetAngle(l.ChargeTargetx, l.ChargeTargety, l.ChargeLocx, l.ChargeLocy))
            set l.ChargeEndy = PolarProjectiony(l.ChargeTargety, 100.00, GetAngle(l.ChargeTargetx, l.ChargeTargety, l.ChargeLocx, l.ChargeLocy))
            
            set l.ChargeAngle = GetAngle(l.ChargeLocx, l.ChargeLocy, l.ChargeEndx, l.ChargeEndy)
            if ( l.AlmostChargeCond() ) then
            //What to do when the caster is about to reach the target
                call l.AlmostCharge()
            endif
            //If the Target gets too far away (by teleportation, for example) then stops the Charge
            if ( GetDistance(l.ChargeLocx, l.ChargeLocy, l.ChargeEndx, l.ChargeEndy) >= MAXDISTANCE and (MAXDISTANCE != 0.00) ) then
                call l.StopCharge()
            endif
            if ( l.ChargeConditions() ) then
            //If the unit hasn't reached the target yet, then execute this
                call l.ContinueCharge()
                call TimerAttach(l.ChargeTimer,0.03,l,function ChargeLoop.ChargeActions)
            else
                if ( l.ChargeCompleted() ) then
            //What to do if the charge is succesfully completed
                    call l.CompleteCharge()
                endif
                call l.StopCharge()
            endif
        endmethod
        
        //Actions to take once the Charge is being stopped (either because it wasn't possible to complete
        //the charge or because the caster reached its target)
        private method StopCharge takes nothing returns nothing
            set this.ChargeCond = false
            call SetUnitPathing(this.ChargeCaster, true)
            call PauseUnit(this.ChargeCaster, false)
            call SetUnitAnimation(this.ChargeCaster, "stand")
            call SetUnitTimeScale(this.ChargeCaster, 1.00)
            call DestroyEffect(this.ChargeEffect)
            call this.destroy()
        endmethod
        
        private method ChargeCompleted takes nothing returns boolean
            if ((GetDistance(this.ChargeLocx, this.ChargeLocy, this.ChargeEndx, this.ChargeEndy) <= this.ChargeDistance*1.10)  and IsPointWalkable(this.ChargeNextx, this.ChargeNexty)) then
                if ((IsTerrainPathable(this.ChargeNextx, this.ChargeNexty, PATHING_TYPE_WALKABILITY) == false ) and ( (GetUnitState(this.ChargeTarget, UNIT_STATE_LIFE)<=0) == false )) then
                    if(((GetUnitState(this.ChargeCaster, UNIT_STATE_LIFE) <= 0) == false)) then
                        return true
                    endif
                endif
            endif
                return false
        endmethod

        private method ChargeConditions takes nothing returns boolean
            if ((GetDistance(this.ChargeLocx, this.ChargeLocy, this.ChargeEndx, this.ChargeEndy) > this.ChargeDistance*1.10)  and IsPointWalkable(this.ChargeNextx, this.ChargeNexty)) then
                if ((IsTerrainPathable(this.ChargeNextx, this.ChargeNexty, PATHING_TYPE_WALKABILITY) == false ) and ( (GetUnitState(this.ChargeTarget, UNIT_STATE_LIFE)<=0) == false )) then 
                    if(((GetUnitState(this.ChargeCaster, UNIT_STATE_LIFE) <= 0) == false)) then
                        return true
                    endif
                endif
            endif
                return false
        endmethod
        
        private method onDestroy takes nothing returns nothing
            call ReleaseTimer(this.ChargeTimer)
            set this.ChargeTarget = null
            set this.ChargeCaster = null
            set this.ChargeEffect = null
        endmethod
        
        static method create takes real pChargeTargetx, real pChargeTargety, real pChargeEndx, real pChargeEndy, real pChargeLocx, real pChargeLocy, real pChargeNextx, real pChargeNexty, unit pChargeTarget, unit pChargeCaster, real pChargeAngle, real pChargeDistance, effect pChargeEffect, timer pChargeTimer returns ChargeLoop
            local ChargeLoop l = ChargeLoop.allocate()
            set l.ChargeTargetx = pChargeTargetx
            set l.ChargeTargety = pChargeTargety
            set l.ChargeEndx = pChargeEndx
            set l.ChargeEndy = pChargeEndy
            set l.ChargeLocx = pChargeLocx
            set l.ChargeLocy = pChargeLocy
            set l.ChargeNextx = pChargeNextx
            set l.ChargeNexty = pChargeNexty
            set l.ChargeTarget = pChargeTarget
            set l.ChargeCaster = pChargeCaster
            set l.ChargeAngle = pChargeAngle
            set l.ChargeDistance = pChargeDistance
            set l.ChargeEffect = pChargeEffect
            set l.ChargeTimer = pChargeTimer
            set l.SpellLvl = GetUnitAbilityLevel(l.ChargeCaster, SPELLID) 
            return l
        endmethod
        
        //END OF OTHER METHODS
    endstruct
endlibrary

//TRIGGER OF THE CHARGE SPELL
scope Charge initializer InitTrig
    private function Conditions takes nothing returns boolean
        return GetSpellAbilityId() == SPELLID
    endfunction

    private function CheckActions takes nothing returns nothing
        local real ChargeLocx = GetUnitX(GetTriggerUnit())
        local real ChargeLocy = GetUnitY(GetTriggerUnit())
        local real ChargeEndx = GetUnitX(GetSpellTargetUnit())
        local real ChargeEndy = GetUnitY(GetSpellTargetUnit())
        local sound s
        
        if ( GetDistance(ChargeLocx, ChargeLocy, ChargeEndx, ChargeEndy) <= (MINDISTANCE) ) then
            call DisplayTextToPlayer( GetOwningPlayer(GetTriggerUnit()), 0, 0, "|cffFFCC00Target is too close!|r" )
            set s = CreateSound("Sound\\Interface\\Error.wav", false, false, true, 12700, 12700, "")
            call StartSound(s)
            call KillSoundWhenDone(s)
            set s = null
            call IssueImmediateOrder( GetTriggerUnit(), "stop" )
        endif
    endfunction
    
    private function InitActions takes nothing returns nothing
        local timer ChargeTimer = NewTimer()
        local effect ChargeEffect
        local unit ChargeCaster = GetTriggerUnit()
        local unit ChargeTarget = GetSpellTargetUnit()
        local real ChargeDistance = STARTSPEED
        local real ChargeLocx = GetUnitX(ChargeCaster)
        local real ChargeLocy = GetUnitY(ChargeCaster)
        local real ChargeTargetx = GetUnitX(ChargeTarget)
        local real ChargeTargety = GetUnitY(ChargeTarget)
        local real ChargeEndx = PolarProjectionx(ChargeTargetx, 100.00, GetAngle(ChargeTargetx, ChargeTargety, ChargeLocx, ChargeLocy))
        local real ChargeEndy = PolarProjectiony(ChargeTargety, 100.00, GetAngle(ChargeTargetx, ChargeTargety, ChargeLocx, ChargeLocy))
        local real ChargeAngle = GetAngle(ChargeLocx, ChargeLocy, ChargeEndx, ChargeEndy)
        local real ChargeNextx = PolarProjectionx(ChargeLocx, ChargeDistance, ChargeAngle)
        local real ChargeNexty = PolarProjectiony(ChargeLocy, ChargeDistance, ChargeAngle)
        local ChargeLoop stru
        
        set ChargeEffect = AddSpecialEffectTarget(ATTACHEDEFFECT, ChargeCaster, "chest" )
        
        set stru = ChargeLoop.create(ChargeTargetx, ChargeTargety, ChargeEndx, ChargeEndy, ChargeLocx, ChargeLocy, ChargeNextx, ChargeNexty, ChargeTarget, ChargeCaster, ChargeAngle, ChargeDistance, ChargeEffect, ChargeTimer)
        call SetUnitPathing(ChargeCaster, false)
        call SetUnitTimeScale(ChargeCaster, 3)
        call IssueImmediateOrder(ChargeCaster, "stop" )
        call PauseUnit(ChargeCaster, true)
        call SetUnitAnimationByIndex(ChargeCaster,1)
        call TimerAttach(ChargeTimer,0,stru,function ChargeLoop.ChargeActions)
        
        set ChargeTimer = null
        set ChargeEffect = null
        set ChargeCaster = null
        set ChargeTarget = null
    endfunction

    private function InitTrig takes nothing returns nothing
        local trigger ChargeCheck = CreateTrigger()
        local trigger ChargeInit = CreateTrigger()
        local filterfunc f = Filter(function AntiLeak)
        local integer i = 0
        loop
            exitwhen i == 16
            call TriggerRegisterPlayerUnitEvent(ChargeCheck,Player(i),EVENT_PLAYER_UNIT_SPELL_CAST,truefilter)
            call TriggerRegisterPlayerUnitEvent(ChargeInit,Player(i),EVENT_PLAYER_UNIT_SPELL_EFFECT,truefilter)
            set i = i + 1
        endloop
        call TriggerAddCondition(ChargeCheck, Condition(function Conditions))
        call TriggerAddAction(ChargeCheck, function CheckActions)
        call TriggerAddCondition(ChargeInit, Condition(function Conditions))
        call TriggerAddAction(ChargeInit, function InitActions)
        set ChargeCheck = null
        set ChargeInit = null
        set f = null
    endfunction
endscope

----------------------------------------------------------------------------Paladon presents----------------------------------------------------------------------------



Jump n´ Dash System v.0.90


1-What this system allows you to make:
This system allows you easily create spells with jump effects. You can attach the jump effect to whatever, whenever you want.
You can easily specify speed, range, effects, and other values.
The specified values only apply for the spell you specified them, so other spells using the system are completely autonomic and their values are free selectable.

2-How to imort the system into your map?
The system consists of the two triggers 'Jump System 1' and 'Jump System 2' as well as every variable with the 'JD_' and the 'JDA_' prefix.
You don´t need any of the custom units, spells, buffs, items or whatever. The custom object editor data is created for the sample spells only.
Just copy the both named triggers into your map as well as the variables.
It´s recommendable to check the box 'Automatically create unknown variables while pasting trigger data' located at File->Presettings->General.

3-How to attach finally a das or a jump?
To attach the imported system to a spell, create a new spell and apply the actions of the 'Actions to apply' trigger for every unit which shall receive the wished effect.
That´s all you need.

I recommend you to check the sample.

Please give me credits for the system if you use it in your map or own spell ;)

Jump System 1
Events
Conditions
Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
JD_Integers[1] Equal to 0
Then - Actions
Trigger - Turn on Jump_System_2 <gen>
Else - Actions
Set Variable Set JD_Integers[1] = (JD_Integers[1] + 1)
Set Variable Set JD_Integers[2] = (JD_Integers[2] + 1)
Set Variable Set JD_TempPoint[1] = (Position of JDA_Unit)
Set Variable Set JD_Distances[JD_Integers[2]] = (Distance between JD_TempPoint[1] and JDA_TargetPoint)
Set Variable Set JD_ReachedDistance[JD_Integers[2]] = "0.00"
Set Variable Set JD_SpeedUnits[JD_Integers[2]] = JDA_Speed
Set Variable Set JD_Unit[JD_Integers[2]] = JDA_Unit
Set Variable Set JD_Angle[JD_Integers[2]] = (Angle from JD_TempPoint[1] to JDA_TargetPoint)
Set Variable Set JD_Effect[JD_Integers[2]] = JDA_SpecialEffect
Set Variable Set JD_Animations[JD_Integers[2]] = JDA_Animation
Set Variable Set JD_TreesDestroy[JD_Integers[2]] = JDA_DestroyTrees_Dash
Set Variable Set JD_HighSettings[JD_Integers[2]] = (JDA_JumpHigh_Distance x JD_Distances[JD_Integers[2]])
Unit - Turn collision for JDA_Unit Off .
Animation - Change JDA_Unit 's animation speed to (JDA_AnimationSpeed x 100.00) % of its original speed
Animation - Play JDA_Unit 's JDA_Animation animation
Unit Group - Add JDA_Unit to JD_Group
Unit - Add Storm Crow Form to JDA_Unit
Unit - Remove Storm Crow Form from JDA_Unit
Custom script: call RemoveLocation (udg_JD_TempPoint[1])
Custom script: call RemoveLocation (udg_JDA_TargetPoint)
Jump System 2
Events
Time - Every 0.02 seconds of game time
Conditions
Actions
For each (Integer JD_Integers[3] ) from 1 to JD_Integers[2] , do (Actions)
Loop - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(JD_Unit[JD_Integers[3]] is in JD_Group.) Equal to True
Then - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
JD_ReachedDistance[JD_Integers[3]] Less than JD_Distances[JD_Integers[3]]
Then - Actions
Animation - Queue JD_Unit[JD_Integers[3]] 's JD_Animations[JD_Integers[3]] animation
Set Variable Set JD_TempPoint[1] = (Position of JD_Unit[JD_Integers[3]])
Set Variable Set JD_TempPoint[2] = (JD_TempPoint[1] offset by JD_SpeedUnits[JD_Integers[3]] towards JD_Angle[JD_Integers[3]] degrees.)
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
JD_TreesDestroy[JD_Integers[3]] Equal to True
Then - Actions
Destructible - Pick every destructible within 150.00 of JD_TempPoint[2] and do (Kill (Picked destructible))
Else - Actions
Unit - Move JD_Unit[JD_Integers[3]] instantly to JD_TempPoint[2]
Set Variable Set JD_ReachedDistance[JD_Integers[3]] = (JD_ReachedDistance[JD_Integers[3]] + JD_SpeedUnits[JD_Integers[3]])
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Random integer number between 1 and 5) Equal to 1
Then - Actions
Special Effect - Create a special effect attached to the chest (Unexpected type: 'attachpoint') of JD_Unit[JD_Integers[3]] using JD_Effect[JD_Integers[3]]
Special Effect - Destroy (Last created special effect)
Else - Actions
Set Variable Set JD_RealTimer[JD_Integers[3]] = (JD_RealTimer[JD_Integers[3]] + (180.00 / (JD_Distances[JD_Integers[3]] / JD_SpeedUnits[JD_Integers[3]])))
Set Variable Set JD_JumpHigh[JD_Integers[3]] = ((Sin(JD_RealTimer[JD_Integers[3]])) x JD_HighSettings[JD_Integers[3]])
Animation - Change JD_Unit[JD_Integers[3]] flying height to JD_JumpHigh[JD_Integers[3]] at 1000000000.00
Custom script: call RemoveLocation (udg_JD_TempPoint[1])
Custom script: call RemoveLocation (udg_JD_TempPoint[2])
Else - Actions
Unit - Turn collision for JD_Unit[JD_Integers[3]] On .
Unit Group - Remove JD_Unit[JD_Integers[3]] from JD_Group .
Animation - Change JD_Unit[JD_Integers[3]] 's animation speed to 100.00 % of its original speed
Animation - Reset JD_Unit[JD_Integers[3]] 's animation
Set Variable Set JD_RealTimer[JD_Integers[3]] = "0.00"
Set Variable Set JD_Integers[1] = (JD_Integers[1] - 1)
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
JD_Integers[1] Equal to 0
Then - Actions
Set Variable Set JD_Integers[2] = "0"
Set Variable Set JD_JumpEndEvent = "1.00"
Set Variable Set JD_JumpEndEvent = "0.00"
Trigger - Turn off (This trigger)
Else - Actions
Else - Actions
Actions to apply
Events
Conditions
Actions
-------- This are the actions to apply in your spell to use an effect of this system. --------
-------- --------
Set Variable Set JDA_JumpHigh_Distance = "1.00"
-------- This variable returns the base value of the high of the jump. --------
-------- The Jump´s high is calculated by the distance jumped and by this value. --------
-------- The higher this value is, the higher is the jump. I recommend to leave it at 1.00 . --------
-------- --------
Set Variable Set JDA_DestroyTrees_Dash = "true"
-------- !Don´t pay attention to this variable if you have choosen the Jump effect! --------
-------- This variable returns whether the hero should destroy trees while dashing. --------
-------- Set this variable toTrue to destroy trees in the dashing unit´s way. --------
-------- --------
Set Variable Set JDA_TargetPoint = (Target point of ability being cast)
-------- This returns where the target position of the Jump/Dash should be. --------
-------- --------
Set Variable Set JDA_Unit = (Triggering unit)
-------- This returns the unit which shall jump/dash. --------
-------- --------
Set Variable Set JDA_Speed = "10.00"
-------- This returns the speed of the jump/dash. --------
-------- --------
Set Variable Set JDA_SpecialEffect = "Abilities\Weapons\FaerieDragonMissile\FaerieDragonMissile.mdl"
-------- This returns the path for the used special effect. --------
-------- --------
Set Variable Set JDA_Animation = "slam"
-------- This returns the animation of the unit jumping/dashing. --------
-------- --------
Set Variable Set JDA_AnimationSpeed = "0.60"
-------- This returns the animation speed of the jumping/dashing unit. --------
-------- --------
Trigger - Run Jump_System_1 <gen> (checking conditions)
-------- After setting all needed variables, this calls the system to execute the choosen effects on the choosen unit/units. --------
-------- --------
Sample Spell Jump
Events
Unit - A unit Starts the effect of an ability
Conditions
(Ability being cast) Equal to Tower Ruins Upgrade (Critical Strike)
Actions
Set Variable Set JDA_JumpHigh_Distance = (0.33 x (Real((Level of (Ability being cast) for (Triggering unit)))))
Set Variable Set JDA_DestroyTrees_Dash = "false"
Set Variable Set JDA_Collusion = "false"
Set Variable Set JDA_TargetPoint = (Target point of ability being cast)
Set Variable Set JDA_Unit = (Triggering unit)
Set Variable Set JDA_Speed = "15.00"
Set Variable Set JDA_SpecialEffect = "Abilities\Weapons\FaerieDragonMissile\FaerieDragonMissile.mdl"
Set Variable Set JDA_Animation = "walk"
Set Variable Set JDA_AnimationSpeed = "0.60"
Trigger - Run Jump_System_1 <gen> (checking conditions)
Meteoric Smash
Jump Slam
Events
Unit - A unit Starts the effect of an ability
Conditions
(Ability being cast) Equal to Meteoric Smash (Breath of Fire)
Actions
Animation - Play TempCaster 's spell throw animation
Set Variable Set TempPlayerUnit[(Player number of (Owner of (Casting unit)))] = (Casting unit)
Set Variable Set JDA_JumpHigh_Distance = (10.00 + 0.00)
Set Variable Set JDA_DestroyTrees_Dash = "false"
Set Variable Set JDA_Collusion = "false"
Set Variable Set JDA_TargetPoint = (Target point of ability being cast)
Set Variable Set JDA_Unit = (Triggering unit)
Set Variable Set JDA_Speed = "10.00"
Set Variable Set JDA_Animation = "walk"
Set Variable Set JDA_AnimationSpeed = "15.00"
Trigger - Run Jump_System_1 <gen> (checking conditions)
https://www.hiveworkshop.com/threads/jump-and-damage-upon-landing.224877/
JDA_JumpEndEvent added by Lender
Jump Slam End
Events
Game - JD_JumpEndEvent becomes Equal to 1.00
Conditions
(Owner of JDA_Unit) Equal to (Owner of TempPlayerUnit[(Player number of (Owner of JDA_Unit))])
Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Unit-type of TempPlayerUnit[(Player number of (Owner of JDA_Unit))]) Equal to Bandit Lord (Dark Knight)
Then - Actions
Set Variable Set TempCaster = TempPlayerUnit[(Player number of (Owner of JDA_Unit))]
Set Variable Set TempOwner = (Owner of TempPlayerUnit[(Player number of (Owner of JDA_Unit))])
Set Variable Set TempPoint = (Position of TempCaster)
Special Effect - Create a special effect at TempPoint using Abilities\Spells\Orc\WarStomp\WarStompCaster.mdl
Special Effect - Destroy (Last created special effect)
Unit - Create 1 . Dummy (Footman) for TempOwner at TempPoint facing Default building facing degrees
Set Variable Set TempDummyUnit = (Last created unit)
Unit - Add Dummy War Stomp (War Stomp) to TempDummyUnit
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Level of Black Flag (Critical Strike) for TempPlayerUnit[(Player number of (Owner of JDA_Unit))]) Greater than 0
Then - Actions
Unit - Add Black Flag (Critical Strike) to TempDummyUnit
Unit - Set level of Black Flag (Critical Strike) for TempDummyUnit to (Level of Black Flag (Critical Strike) for TempPlayerUnit[(Player number of (Owner of JDA_Unit))])
Else - Actions
Unit - Set level of Dummy War Stomp (War Stomp) for TempDummyUnit to (Level of Meteoric Smash (Breath of Fire) for TempPlayerUnit[(Player number of (Owner of JDA_Unit))])
Unit - Add a 1.00 second Generic expiration timer to TempDummyUnit
Unit - Order TempDummyUnit to Orc Tauren Chieftain - War Stomp .
Custom script: call RemoveLocation(udg_TempPoint)
Set Variable Set TempPlayerUnit[(Player number of (Owner of JDA_Unit))] = No unit
Else - Actions
Top