1. Are you planning to upload your awesome spell or system to Hive? Please review the rules here.
    Dismiss Notice
  2. Find your way through the deepest dungeon in the 18th Mini Mapping Contest Poll.
    Dismiss Notice
  3. A brave new world lies beyond the seven seas. Join the 34th Modeling Contest today!
    Dismiss Notice
  4. Check out the Staff job openings thread.
    Dismiss Notice
Dismiss Notice
Hive 3 Remoosed BETA - NOW LIVE. Go check it out at BETA Hive Workshop! Post your feedback in this new forum BETA Feedback.
Dismiss Notice
60,000 passwords have been reset on July 8, 2019. If you cannot login, read this.

Trigger Viewer

Eternal Evil.w3x
Variables
Damage Engine
Requirement
Unit Indexer
---------------------------
Damage Engine Config
Damage Engine
Eternal Evil
EE Config
EE Cast
EE Damage
EE Loop
Testmap
Revive
Hero Return
Enter map-specific custom script code below. This text will be included in the map script after variables are declared and before any trigger code.

		
Name Type Is Array Initial Value
AfterDamageEvent real No
AOEDamageEvent real No
ClearDamageEvent trigger No
DAMAGE_FACTOR_BRACERS real No
DAMAGE_FACTOR_ELUNES real No
DAMAGE_FACTOR_ETHEREAL real No
DamageBlockingAbility abilcode No
DamageEvent real No
DamageEventAmount real No
DamageEventAOE integer No
DamageEventAOEGroup group No
DamageEventLevel integer No
DamageEventOverride boolean No
DamageEventPrevAmt real No
DamageEventSource unit No
DamageEventsWasted integer No
DamageEventTarget unit No
DamageEventTrigger trigger No
DamageEventType integer No
DamageModifierEvent real No
DamageTypeBlocked integer No
DamageTypeCriticalStrike integer No
DamageTypeExplosive integer No
DamageTypeHeal integer No
DamageTypeReduced integer No
DmgEvBracers itemcode No
DmgEvRecursionN integer No
DmgEvRunning boolean No
DmgEvStarted boolean No
DmgEvTimer timer No
DmgEvTrig trigger No
EE_Ability abilcode No
EE_Active boolean Yes
EE_Attach string No
EE_Caster unit No
EE_Counter integer No
EE_CustomValue integer No
EE_Duration real Yes
EE_Effect effect Yes
EE_FinalHeal real Yes
EE_Group group No
EE_Level integer Yes
EE_MinimumHealth real Yes
EE_PercentageOfDamage real Yes
EE_PreserveHeal boolean No
EE_SFX string No
EE_Timeout real No
EE_Timer real Yes
EnhancedDamageTarget unit No
HideDamageFrom boolean Yes
IsDamageSpell boolean No
LastDamageHP real No
LastDmgPrevAmount real Yes
LastDmgPrevType integer Yes
LastDmgSource unit Yes
LastDmgTarget unit Yes
LastDmgValue real Yes
LastDmgWasSpell boolean Yes
NextDamageOverride boolean No
NextDamageType integer No
SpellDamageAbility abilcode No
TempLoc location No
TempUnit unit No
UDex integer No
UDexGen integer No
UDexNext integer Yes
UDexPrev integer Yes
UDexRecycle integer No
UDexUnits unit Yes
UDexWasted integer No
UnitDamageRegistered boolean Yes
UnitIndexerEnabled boolean No
UnitIndexEvent real No
UnitIndexLock integer Yes
Delete Unit Indexer if you already have it or the latest Unit Event in your map.
Unit Indexer gives you an array-safe (1-8190) custom value for units, eliminating the need for hashtables to store unit-specific data.
Just use "Set MyArrayData[(Custom value of Unit)] = (Some data)".
--------
If you want to get the unit assigned to an index (reverse lookup) use "UDexUnits[(Index)]".
--------
If you want to detect when an index is created or when it is released, use "UnitIndexEvent Equal to 1.00" (created) or "UnitIndexEvent Equal to 2.00" (released). The index being created/released is called "UDex".
--------
You can enable/disable Unit Indexer to protect some of your undesirable units from being indexed like this:

Trigger - Turn off Unit Indexer <gen>
Unit - Create 1 Dummy for (Triggering player) at TempPoint facing 0.00 degrees
Trigger - Turn on Unit Indexer <gen>
--------
If you want to use a Map Initialization trigger that uses custom value of units, to make sure that UnitIndexer initializes first, use the event "UnitIndexEvent Equal to 3.00". Otherwise the custom value of units may be zero.
--------
Advanced:
--------
If you want to lock the index of a unit, use "Set UnitIndexLock[(Index)] = (UnitIndexLock[(Index)] + 1)". This will prevent the index from being recycled. If you want to unlock it and allow it to be recycled, run the Unit Indexer <gen> trigger.

Note: Make sure if you add a lock that you will eventually remove the lock, otherwise the index will never be recycled.
Unit Indexer
  Events
    Map initialization
  Conditions
  Actions
    Custom script: call ExecuteFunc("InitializeUnitIndexer")
    Custom script: endfunction
    Custom script:
    Custom script: function ClearUnitIndex takes nothing returns nothing
    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
        Set VariableSet UnitIndexLock[UDex] = (UnitIndexLock[UDex] - 1)
        If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          If - Conditions
            UnitIndexLock[UDex] Equal to 0
          Then - Actions
            Set VariableSet UDexNext[UDexPrev[UDex]] = UDexNext[UDex]
            Set VariableSet UDexPrev[UDexNext[UDex]] = UDexPrev[UDex]
            Set VariableSet UDexPrev[UDex] = 0
            Set VariableSet UnitIndexEvent = 0.00
            Set VariableSet UnitIndexEvent = 2.00
            Set VariableSet UnitIndexEvent = 0.00
            Set VariableSet UDexUnits[UDex] = No unit
            Set VariableSet UDexNext[UDex] = UDexRecycle
            Set VariableSet UDexRecycle = UDex
          Else - Actions
      Else - Actions
    Custom script: endfunction
    Custom script:
    Custom script: function IndexUnit takes nothing returns boolean
    Custom script: local integer pdex = udg_UDex
    Custom script: local integer ndex
    -------- - --------
    -------- You can 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
        (Custom value of (Matching unit)) Equal to 0
      Then - Actions
        Set VariableSet UDexWasted = (UDexWasted + 1)
        If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          If - Conditions
            UDexWasted Equal to 32
          Then - Actions
            Set VariableSet UDexWasted = 0
            Set VariableSet UDex = UDexNext[0]
            Custom script: loop
            Custom script: exitwhen udg_UDex == 0
            Custom script: set ndex = udg_UDexNext[udg_UDex]
            Custom script: call ClearUnitIndex()
            Custom script: set udg_UDex = ndex
            Custom script: endloop
          Else - Actions
        If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          If - Conditions
            UDexRecycle Equal to 0
          Then - Actions
            Set VariableSet UDex = (UDexGen + 1)
            Set VariableSet UDexGen = UDex
          Else - Actions
            Set VariableSet UDex = UDexRecycle
            Set VariableSet UDexRecycle = UDexNext[UDex]
        Set VariableSet UDexUnits[UDex] = (Matching unit)
        Unit - Set the custom value of UDexUnits[UDex] to UDex
        Set VariableSet UDexPrev[UDexNext[0]] = UDex
        Set VariableSet UDexNext[UDex] = UDexNext[0]
        Set VariableSet UDexNext[0] = UDex
        Set VariableSet UnitIndexLock[UDex] = 1
        Set VariableSet UnitIndexEvent = 0.00
        Set VariableSet UnitIndexEvent = 1.00
        Set VariableSet UnitIndexEvent = 0.00
        Custom script: set udg_UDex = pdex
      Else - Actions
    Custom script: return false
    Custom script: endfunction
    Custom script:
    Custom script: function InitializeUnitIndexer takes nothing returns nothing
    Custom script: local integer i = 16
    Custom script: local boolexpr b = Filter(function IndexUnit)
    Custom script: local region re = CreateRegion()
    Custom script: local trigger t = GetTriggeringTrigger()
    Custom script: local rect r = GetWorldBounds()
    Custom script: call RegionAddRect(re, r)
    Custom script: call TriggerRegisterEnterRegion(t, re, b)
    Custom script: call TriggerClearActions(t)
    Custom script: call TriggerAddAction(t, function ClearUnitIndex)
    Set VariableSet UnitIndexerEnabled = True
    Custom script: loop
    Custom script: set i = i - 1
    Custom script: call GroupEnumUnitsOfPlayer(bj_lastCreatedGroup, Player(i), b)
    Custom script: exitwhen i == 0
    Custom script: endloop
    Custom script: call RemoveRect(r)
    Custom script: set re = null
    Custom script: set r = null
    Custom script: set t = null
    Custom script: set b = null
    Set VariableSet UnitIndexEvent = 3.00
    Set VariableSet UnitIndexEvent = 0.00
Damage Engine Config
  Events
  Conditions
    (UDexUnits[UDex] is A structure) Equal to False
  Actions
    -------- - --------
    -------- This trigger's conditions let you filter out units you don't want detection for. --------
    -------- NOTE: By default, units with Locust will not pass the check. --------
    -------- TIP: The unit is called UDexUnits[UDex] and its custom value is UDex --------
    -------- - --------
    -------- Copy the Cheat Death Ability from Object Editor into your map and set the following variable respectively: --------
    -------- - --------
    Set VariableSet DamageBlockingAbility = Cheat Death Ability (+500,000)
    -------- - --------
    -------- Copy the Detect Spell Damage Ability from Object Editor into your map and set the following variable respectively: --------
    -------- - --------
    Set VariableSet SpellDamageAbility = Detect Spell Damage
    -------- - --------
    -------- You can add extra classifications here if you want to differentiate between your triggered damage --------
    -------- Use DamageTypeExplosive (or any negative value damage type) if you want a unit killed by that damage to explode --------
    -------- - --------
    Set VariableSet DamageTypeExplosive = -1
    Set VariableSet DamageTypeCriticalStrike = 1
    Set VariableSet DamageTypeHeal = 2
    Set VariableSet DamageTypeReduced = 3
    Set VariableSet DamageTypeBlocked = 4
    -------- - --------
    -------- Leave the next Set statement disabled if you modified the Spell Damage Reduction item ability to 1.67 reduction --------
    -------- Otherwise, if you removed that ability from Runed Bracers, you'll need to enable this line: --------
    -------- - --------
    Set VariableSet DmgEvBracers = Runed Bracers
    -------- - --------
    -------- Set the damage multiplication factor (1.00 being unmodified, increasing in damage over 1.00 and at 0 damage with 0.00) --------
    -------- NOTE. With the default values, Runed Bracers is reduces 33%, Elune's Grace reduces 20% and Ethereal increases 67% --------
    -------- - --------
    Set VariableSet DAMAGE_FACTOR_BRACERS = 0.67
    Set VariableSet DAMAGE_FACTOR_ELUNES = 0.80
    Set VariableSet DAMAGE_FACTOR_ETHEREAL = 1.67
    -------- - --------
    -------- Added 25 July 2017 to allow detection of things like Bash or Pulverize or AOE spread --------
    -------- - --------
    Set VariableSet DamageEventAOE = 1
    Set VariableSet DamageEventLevel = 1
    -------- - --------
    -------- Do not enable any of the following lines as they are simply variable declarations to make copying easier --------
    -------- - --------
    Set VariableSet AfterDamageEvent = (DamageEvent + (AOEDamageEvent + DamageModifierEvent))
    Set VariableSet ClearDamageEvent = (This trigger)
    Set VariableSet DamageEventAmount = DamageEventPrevAmt
    Set VariableSet DamageEventOverride = NextDamageOverride
    Set VariableSet DamageEventSource = DamageEventTarget
    Set VariableSet DamageEventTrigger = DmgEvTrig
    Set VariableSet DamageEventType = (LastDmgPrevType[0] + NextDamageType)
    Set VariableSet DamageEventsWasted = DmgEvRecursionN
    Set VariableSet DmgEvRunning = DmgEvStarted
    Set VariableSet IsDamageSpell = LastDmgWasSpell[0]
    Set VariableSet LastDamageHP = (Elapsed time for DmgEvTimer)
    Set VariableSet LastDmgPrevAmount[0] = LastDmgValue[0]
    Set VariableSet LastDmgSource[0] = LastDmgTarget[0]
    Set VariableSet HideDamageFrom[0] = False
    Set VariableSet UnitDamageRegistered[0] = False
    Unit Group - Add EnhancedDamageTarget to DamageEventAOEGroup
//TESH.scrollpos=0
//TESH.alwaysfold=0
//===========================================================================
// Damage Engine lets you detect, amplify, block or nullify damage. It even
// lets you detect if the damage was physical or from a spell. Just reference
// DamageEventAmount/Source/Target or the boolean IsDamageSpell, to get the
// necessary damage event data.
//
// - Detect damage: use the event "DamageEvent Equal to 1.00"
// - To change damage before it's dealt: use the event "DamageModifierEvent Equal to 1.00"
// - Detect damage after it was applied, use the event "AfterDamageEvent Equal to 1.00"
// - Detect spell damage: use the condition "IsDamageSpell Equal to True"
// - Detect zero-damage: use the event "DamageEvent Equal to 2.00" (an AfterDamageEvent will not fire for this)
//
// You can specify the DamageEventType before dealing triggered damage. To prevent an already-improbable error, I recommend running the trigger "ClearDamageEvent (Checking Conditions)" after dealing triggered damage from within a damage event:
// - Set NextDamageType = DamageTypeWhatever
// - Unit - Cause...
// - Trigger - Run ClearDamageEvent (Checking Conditions)
//
// You can modify the DamageEventAmount and the DamageEventType from a "DamageModifierEvent Equal to 1.00" trigger.
// - If the amount is modified to negative, it will count as a heal.
// - If the amount is set to 0, no damage will be dealt.
//
// If you need to reference the original in-game damage, use the variable "DamageEventPrevAmt".
//
//===========================================================================
// Programming note about "integer i" and "udg_DmgEvRecursionN": integer i
// ranges from -1 upwards. "udg_DmgEvRecursionN" ranges from 0 upwards.
// "integer i" is always 1 less than "udg_DmgEvRecursionN"
//
function DmgEvResetVars takes nothing returns nothing
    local integer i = udg_DmgEvRecursionN - 2
    set udg_DmgEvRecursionN = i + 1
    if i >= 0 then
        set udg_DamageEventPrevAmt  = udg_LastDmgPrevAmount[i]
        set udg_DamageEventAmount   = udg_LastDmgValue[i]
        set udg_DamageEventSource   = udg_LastDmgSource[i]
        set udg_DamageEventTarget   = udg_LastDmgTarget[i]
        set udg_IsDamageSpell       = udg_LastDmgWasSpell[i]
        set udg_DamageEventType     = udg_LastDmgPrevType[i]
    endif
endfunction

function CheckDamagedLifeEvent takes boolean clear returns nothing
    if clear then
        set udg_NextDamageOverride = false
        set udg_NextDamageType = 0
    endif
    if udg_DmgEvTrig != null then
        call DestroyTrigger(udg_DmgEvTrig)
        set udg_DmgEvTrig = null
        if udg_IsDamageSpell then
            call SetWidgetLife(udg_DamageEventTarget, RMaxBJ(udg_LastDamageHP, 0.41))
            if udg_LastDamageHP <= 0.405 then
                if udg_DamageEventType < 0 then
                    call SetUnitExploded(udg_DamageEventTarget, true)
                endif
                //Kill the unit
                call DisableTrigger(udg_DamageEventTrigger)
                call UnitDamageTarget(udg_DamageEventSource, udg_DamageEventTarget, -999, false, false, null, DAMAGE_TYPE_UNIVERSAL, null)
                call EnableTrigger(udg_DamageEventTrigger)
            endif
        elseif GetUnitAbilityLevel(udg_DamageEventTarget, udg_DamageBlockingAbility) > 0 then
            call UnitRemoveAbility(udg_DamageEventTarget, udg_DamageBlockingAbility)
            call SetWidgetLife(udg_DamageEventTarget, udg_LastDamageHP)
        endif
        if udg_DamageEventAmount != 0.00 and not udg_HideDamageFrom[GetUnitUserData(udg_DamageEventSource)] then
            set udg_AfterDamageEvent = 0.00
            set udg_AfterDamageEvent = 1.00
            set udg_AfterDamageEvent = 0.00
        endif
        call DmgEvResetVars()
    endif
endfunction
   
function DmgEvOnAOEEnd takes nothing returns nothing
    if udg_DamageEventAOE > 1 then
        set udg_AOEDamageEvent = 0.00
        set udg_AOEDamageEvent = 1.00
        set udg_AOEDamageEvent = 0.00
        set udg_DamageEventAOE = 1
    endif
    set udg_DamageEventLevel = 1
    set udg_EnhancedDamageTarget = null
    call GroupClear(udg_DamageEventAOEGroup)
endfunction
   
function DmgEvOnExpire takes nothing returns nothing
    set udg_DmgEvStarted = false
    call CheckDamagedLifeEvent(true)
    //Reset things so they don't perpetuate for AoE/Level target detection
    call DmgEvOnAOEEnd()
    set udg_DamageEventTarget = null
    set udg_DamageEventSource = null
endfunction

function PreCheckDamagedLifeEvent takes nothing returns boolean
    call CheckDamagedLifeEvent(true)
    return false
endfunction

function OnUnitDamage takes nothing returns boolean
    local boolean override = udg_DamageEventOverride
    local integer i
    local integer e = udg_DamageEventLevel
    local integer a = udg_DamageEventAOE
    local string s
    local real prevAmount
    local real life
    local real prevLife
    local unit u
    local unit f
    call CheckDamagedLifeEvent(false) //in case the unit state event failed and the 0.00 second timer hasn't yet expired
    set i = udg_DmgEvRecursionN - 1 //Had to be moved here due to false recursion tracking
    if i < 0 then
        //Added 25 July to detect AOE damage or multiple single-target damage
        set u                       = udg_DamageEventTarget
        set f                       = udg_DamageEventSource
    elseif i < 16 then
        set udg_LastDmgPrevAmount[i]= udg_DamageEventPrevAmt
        set udg_LastDmgValue[i]     = udg_DamageEventAmount
        set udg_LastDmgSource[i]    = udg_DamageEventSource
        set udg_LastDmgTarget[i]    = udg_DamageEventTarget
        set udg_LastDmgWasSpell[i]  = udg_IsDamageSpell
        set udg_LastDmgPrevType[i]  = udg_DamageEventType
    else
        set s = "WARNING: Recursion error when dealing damage! Make sure when you deal damage from within a DamageEvent trigger, do it like this:\n\n"
        set s = s + "Trigger - Turn off (This Trigger)\n"
        set s = s + "Unit - Cause...\n"
        set s = s + "Trigger - Turn on (This Trigger)"
       
        //Delete the next couple of lines to disable the in-game recursion crash warnings
        call ClearTextMessages()
        call DisplayTimedTextToPlayer(GetLocalPlayer(), 0.00, 0.00, 999.00, s)
        return false
    endif
    set udg_DmgEvRecursionN     = i + 2
    set prevAmount              = GetEventDamage()
    set udg_DamageEventTarget   = GetTriggerUnit()
    set udg_DamageEventSource   = GetEventDamageSource()
   
    set udg_DamageEventAmount   = prevAmount
   
    set udg_DamageEventType     = udg_NextDamageType
    set udg_NextDamageType      = 0
    set udg_DamageEventOverride = udg_NextDamageOverride
    set udg_NextDamageOverride  = false
   
    if i < 0 then
        //Added 25 July to detect AOE damage or multiple single-target damage
        if udg_DamageEventType == 0 then
            if f == udg_DamageEventSource then
                //Source has damaged more than once
                if IsUnitInGroup(udg_DamageEventTarget, udg_DamageEventAOEGroup) then
                    //Added 5 August to improve tracking of enhanced damage against, say, Pulverize
                    set udg_DamageEventLevel = udg_DamageEventLevel + 1
                    set udg_EnhancedDamageTarget = udg_DamageEventTarget
                else
                    //Multiple targets hit by this source - flag as AOE
                    set udg_DamageEventAOE = udg_DamageEventAOE + 1
                endif
            else
                //New damage source - unflag everything
                set u = udg_DamageEventSource
                set udg_DamageEventSource = f
                call DmgEvOnAOEEnd()
                set udg_DamageEventSource = u
            endif
            call GroupAddUnit(udg_DamageEventAOEGroup, udg_DamageEventTarget)
        endif
        if not udg_DmgEvStarted then
            set udg_DmgEvStarted = true
            call TimerStart(udg_DmgEvTimer, 0.00, false, function DmgEvOnExpire)
        endif
    endif
   
    if prevAmount == 0.00 then
        if not udg_HideDamageFrom[GetUnitUserData(udg_DamageEventSource)] then
            set udg_DamageEventPrevAmt = 0.00
            set udg_DamageEvent = 0.00
            set udg_DamageEvent = 2.00
            set udg_DamageEvent = 0.00
        endif
        call DmgEvResetVars()
    else
        set u = udg_DamageEventTarget
        set udg_IsDamageSpell = prevAmount < 0.00
        if udg_IsDamageSpell then
            set prevAmount = -udg_DamageEventAmount
            set life = 1.00
            if IsUnitType(u, UNIT_TYPE_ETHEREAL) and not IsUnitType(u, UNIT_TYPE_HERO) then
                set life = life*udg_DAMAGE_FACTOR_ETHEREAL //1.67
            endif
            if GetUnitAbilityLevel(u, 'Aegr') > 0 then
                set life = life*udg_DAMAGE_FACTOR_ELUNES //0.80
            endif
            if udg_DmgEvBracers != 0 and IsUnitType(u, UNIT_TYPE_HERO) then
                //Inline of UnitHasItemOfTypeBJ without the potential handle ID leak.
                set i = 6
                loop
                    set i = i - 1
                    if GetItemTypeId(UnitItemInSlot(u, i)) == udg_DmgEvBracers then
                        set life = life*udg_DAMAGE_FACTOR_BRACERS //0.67
                        exitwhen true
                    endif
                    exitwhen i == 0
                endloop
            endif
            set udg_DamageEventAmount = prevAmount*life
        endif
        set udg_DamageEventPrevAmt = prevAmount
        set udg_DamageModifierEvent = 0.00
        if not udg_DamageEventOverride then
            set udg_DamageModifierEvent = 1.00
            if not udg_DamageEventOverride then
                set udg_DamageModifierEvent = 2.00
                set udg_DamageModifierEvent = 3.00
            endif
        endif
        set udg_DamageEventOverride = override
        if udg_DamageEventAmount > 0.00 then
            set udg_DamageModifierEvent = 4.00
        endif
        set udg_DamageModifierEvent = 0.00
        if not udg_HideDamageFrom[GetUnitUserData(udg_DamageEventSource)] then
            set udg_DamageEvent = 0.00
            set udg_DamageEvent = 1.00
            set udg_DamageEvent = 0.00
        endif
        call CheckDamagedLifeEvent(true) //in case the unit state event failed from a recursive damage event
       
        //All events have run and the damage amount is finalized.
        set life = GetWidgetLife(u)
        set udg_DmgEvTrig = CreateTrigger()
        call TriggerAddCondition(udg_DmgEvTrig, Filter(function PreCheckDamagedLifeEvent))
        if not udg_IsDamageSpell then
            if udg_DamageEventAmount != prevAmount then
                set life = life + prevAmount - udg_DamageEventAmount
                if GetUnitState(u, UNIT_STATE_MAX_LIFE) < life then
                    set udg_LastDamageHP = life - prevAmount
                    call UnitAddAbility(u, udg_DamageBlockingAbility)
                endif
                call SetWidgetLife(u, RMaxBJ(life, 0.42))
            endif
            call TriggerRegisterUnitStateEvent(udg_DmgEvTrig, u, UNIT_STATE_LIFE, LESS_THAN, RMaxBJ(0.41, life - prevAmount/2.00))
        else
            set udg_LastDamageHP = GetUnitState(u, UNIT_STATE_MAX_LIFE)
            set prevLife = life
            if life + prevAmount*0.75 > udg_LastDamageHP then
                set life = RMaxBJ(udg_LastDamageHP - prevAmount/2.00, 1.00)
                call SetWidgetLife(u, life)
                set life = (life + udg_LastDamageHP)/2.00
            else
                set life = life + prevAmount*0.50
            endif
            set udg_LastDamageHP = prevLife - (prevAmount - (prevAmount - udg_DamageEventAmount))
            call TriggerRegisterUnitStateEvent(udg_DmgEvTrig, u, UNIT_STATE_LIFE, GREATER_THAN, life)
        endif
    endif
    set u = null
    set f = null
    return false
endfunction

function CreateDmgEvTrg takes nothing returns nothing
    set udg_DamageEventTrigger = CreateTrigger()
    call TriggerAddCondition(udg_DamageEventTrigger, Filter(function OnUnitDamage))
endfunction

function SetupDmgEv takes nothing returns boolean
    local integer i = udg_UDex
    local unit u
    if udg_UnitIndexEvent == 1.00 then
        set u = udg_UDexUnits[i]
        if GetUnitAbilityLevel(u, 'Aloc') == 0 and TriggerEvaluate(gg_trg_Damage_Engine_Config) then
            set udg_UnitDamageRegistered[i] = true
            call TriggerRegisterUnitEvent(udg_DamageEventTrigger, u, EVENT_UNIT_DAMAGED)
            call UnitAddAbility(u, udg_SpellDamageAbility)
            call UnitMakeAbilityPermanent(u, true, udg_SpellDamageAbility)
        endif
        set u = null
    else
        set udg_HideDamageFrom[i] = false
        if udg_UnitDamageRegistered[i] then
            set udg_UnitDamageRegistered[i] = false
            set udg_DamageEventsWasted = udg_DamageEventsWasted + 1
            if udg_DamageEventsWasted == 32 then //After 32 registered units have been removed...
                set udg_DamageEventsWasted = 0
               
                //Rebuild the mass EVENT_UNIT_DAMAGED trigger:
                call DestroyTrigger(udg_DamageEventTrigger)
                call CreateDmgEvTrg()
                set i = udg_UDexNext[0]
                loop
                    exitwhen i == 0
                    if udg_UnitDamageRegistered[i] then
                        call TriggerRegisterUnitEvent(udg_DamageEventTrigger, udg_UDexUnits[i], EVENT_UNIT_DAMAGED)
                    endif
                    set i = udg_UDexNext[i]
                endloop
            endif
        endif
    endif
    return false
endfunction
   
//===========================================================================
function InitTrig_Damage_Engine takes nothing returns nothing
    local unit u = CreateUnit(Player(15), 'uloc', 0, 0, 0)
    local integer i = 16
   
    //Create this trigger with UnitIndexEvents in order add and remove units
    //as they are created or removed.
    local trigger t = CreateTrigger()
    call TriggerRegisterVariableEvent(t, "udg_UnitIndexEvent", EQUAL, 1.00)
    call TriggerRegisterVariableEvent(t, "udg_UnitIndexEvent", EQUAL, 2.00)
    call TriggerAddCondition(t, Filter(function SetupDmgEv))
    set t = null
   
    //Run the configuration trigger to set all configurables:
    if gg_trg_Damage_Engine_Config == null then
        //It's possible this InitTrig_ function ran first, in which case use ExecuteFunc.
        call ExecuteFunc("Trig_Damage_Engine_Config_Actions")
    else
        call TriggerExecute(gg_trg_Damage_Engine_Config)
    endif
   
    //Create trigger for storing all EVENT_UNIT_DAMAGED events.
    call CreateDmgEvTrg()
   
    //Create GUI-friendly trigger for cleaning up after UnitDamageTarget.
    set udg_ClearDamageEvent = CreateTrigger()
    call TriggerAddCondition(udg_ClearDamageEvent, Filter(function PreCheckDamagedLifeEvent))
   
    //Disable SpellDamageAbility for every player.
    loop
        set i = i - 1
        call SetPlayerAbilityAvailable(Player(i), udg_SpellDamageAbility, false)
        exitwhen i == 0
    endloop
   
    //Preload abilities.
    call UnitAddAbility(u, udg_DamageBlockingAbility)
    call UnitAddAbility(u, udg_SpellDamageAbility)
    call RemoveUnit(u)
    set u = null
endfunction
EE Config
  Events
    Map initialization
  Conditions
  Actions
    -------- Eternal Evil ability --------
    Set VariableSet EE_Ability = Eternal Evil
    -------- Preserve heal? if yes, heal will be delayed until the ability duration ends --------
    Set VariableSet EE_PreserveHeal = True
    -------- Active effect --------
    Set VariableSet EE_SFX = Abilities\Spells\Undead\Unsummon\UnsummonTarget.mdl
    Set VariableSet EE_Attach = origin
    -------- Percentage of damage for final heal (1.00 = 100%) --------
    Set VariableSet EE_PercentageOfDamage[1] = 0.30
    Set VariableSet EE_PercentageOfDamage[2] = 0.70
    Set VariableSet EE_PercentageOfDamage[3] = 1.20
    -------- Minimum health --------
    Set VariableSet EE_MinimumHealth[1] = 1.00
    Set VariableSet EE_MinimumHealth[2] = 1.00
    Set VariableSet EE_MinimumHealth[3] = 1.00
    -------- Ability duration --------
    Set VariableSet EE_Duration[1] = 5.00
    Set VariableSet EE_Duration[2] = 5.00
    Set VariableSet EE_Duration[3] = 5.00
    -------- END Config --------
    Set VariableSet EE_Timeout = 0.05
    Trigger - Add to EE_Loop <gen> the event (Every EE_Timeout seconds of game time)
EE Cast
  Events
    Unit - A unit Starts the effect of an ability
  Conditions
    (Ability being cast) Equal to Eternal Evil
  Actions
    Set VariableSet EE_Caster = (Triggering unit)
    Set VariableSet EE_CustomValue = (Custom value of EE_Caster)
    Set VariableSet EE_Active[EE_CustomValue] = True
    Set VariableSet EE_Level[EE_CustomValue] = (Level of EE_Ability for EE_Caster)
    Set VariableSet EE_Timer[EE_CustomValue] = EE_Duration[EE_Level[EE_CustomValue]]
    If (All Conditions are True) then do (Then Actions) else do (Else Actions)
      If - Conditions
        (EE_Caster is in EE_Group.) Equal to False
      Then - Actions
        Set VariableSet EE_FinalHeal[EE_CustomValue] = 0.00
        Set VariableSet EE_Counter = (EE_Counter + 1)
        Unit Group - Add EE_Caster to EE_Group
        Special Effect - Create a special effect attached to the EE_Attach of EE_Caster using EE_SFX
        Set VariableSet EE_Effect[EE_CustomValue] = (Last created special effect)
        If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          If - Conditions
            EE_Counter Equal to 1
          Then - Actions
            Trigger - Turn on EE_Damage <gen>
            Trigger - Turn on EE_Loop <gen>
          Else - Actions
      Else - Actions
EE Damage
  Events
    Game - DamageEvent becomes Equal to 1.00
  Conditions
  Actions
    -------- Eternal Evil user is attacked --------
    Set VariableSet EE_CustomValue = (Custom value of DamageEventTarget)
    If (All Conditions are True) then do (Then Actions) else do (Else Actions)
      If - Conditions
        EE_Active[EE_CustomValue] Equal to True
      Then - Actions
        -------- +1 to circumvent the 0.41 death point --------
        If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          If - Conditions
            DamageEventAmount Greater than or equal to ((Life of DamageEventTarget) + 1.00)
          Then - Actions
            Set VariableSet DamageEventAmount = 0.00
            Unit - Set life of DamageEventTarget to EE_MinimumHealth[EE_Level[EE_CustomValue]]
          Else - Actions
      Else - Actions
    -------- Eternal Evil user is attacking --------
    Set VariableSet EE_CustomValue = (Custom value of DamageEventSource)
    If (All Conditions are True) then do (Then Actions) else do (Else Actions)
      If - Conditions
        EE_Active[EE_CustomValue] Equal to True
      Then - Actions
        Set VariableSet EE_FinalHeal[EE_CustomValue] = (EE_FinalHeal[EE_CustomValue] + DamageEventAmount)
        If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          If - Conditions
            EE_PreserveHeal Equal to False
          Then - Actions
            Set VariableSet EE_FinalHeal[EE_CustomValue] = (EE_FinalHeal[EE_CustomValue] x EE_PercentageOfDamage[EE_Level[EE_CustomValue]])
            Unit - Set life of DamageEventSource to ((Life of DamageEventSource) + DamageEventAmount)
            Set VariableSet EE_FinalHeal[EE_CustomValue] = 0.00
          Else - Actions
      Else - Actions
EE Loop
  Events
  Conditions
  Actions
    Unit Group - Pick every unit in EE_Group and do (Actions)
      Loop - Actions
        Set VariableSet EE_Caster = (Picked unit)
        Set VariableSet EE_CustomValue = (Custom value of EE_Caster)
        Set VariableSet EE_Timer[EE_CustomValue] = (EE_Timer[EE_CustomValue] - EE_Timeout)
        If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          If - Conditions
            EE_Timer[EE_CustomValue] Less than or equal to 0.00
          Then - Actions
            Special Effect - Destroy EE_Effect[EE_CustomValue]
            If (All Conditions are True) then do (Then Actions) else do (Else Actions)
              If - Conditions
                EE_PreserveHeal Equal to True
              Then - Actions
                Set VariableSet EE_FinalHeal[EE_CustomValue] = (EE_FinalHeal[EE_CustomValue] x EE_PercentageOfDamage[EE_Level[EE_CustomValue]])
                Unit - Set life of EE_Caster to ((Life of EE_Caster) + EE_FinalHeal[EE_CustomValue])
              Else - Actions
            Unit Group - Remove EE_Caster from EE_Group.
            Set VariableSet EE_Counter = (EE_Counter - 1)
            If (All Conditions are True) then do (Then Actions) else do (Else Actions)
              If - Conditions
                EE_Counter Equal to 0
              Then - Actions
                Trigger - Turn off (This trigger)
                Trigger - Turn off EE_Damage <gen>
              Else - Actions
          Else - Actions
Revive
  Events
    Unit - A unit owned by Player 2 (Blue).Dies
  Conditions
  Actions
    Set VariableSet TempUnit = (Triggering unit)
    Set VariableSet TempLoc = (Position of TempUnit)
    Unit - Create 1.(Unit-type of (Triggering unit)) for Player 2 (Blue) at TempLoc facing Default building facing degrees
    Custom script: call RemoveLocation(udg_TempLoc)
Hero Return
  Events
    Unit - A unit owned by Player 1 (Red).Dies
  Conditions
  Actions
    Wait 2.00 seconds
    Hero - Instantly revive EE_Caster at (Center of (Playable map area)), Show revival graphics