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 | |
DarkElf_Player_Group | force | No | |
DE_Abduct_Caster | unit | Yes | |
DE_Abduct_Group | group | No | |
DE_Abduct_Timer | real | Yes | |
DE_Arrow_Damage | real | Yes | |
DE_Arrow_Owner | unit | Yes | |
DE_Bane_Caster | unit | Yes | |
DE_Bane_Group | group | No | |
DE_BarbedBlades_AINT | integer | No | |
DE_BarbedBlades_BINT | integer | No | |
DE_BarbedBlades_Counter | real | Yes | |
DE_BarbedBlades_Damage | real | Yes | |
DE_BarbedBlades_Duration | real | Yes | |
DE_BarbedBlades_IsActive | boolean | Yes | |
DE_BarbedBlades_Owner | unit | Yes | |
DE_BarbedBlades_Spec | effect | Yes | |
DE_BarbedBlades_Spec_Counter | integer | Yes | |
DE_BarbedBlades_Target | unit | Yes | |
DE_Barrage_Damage | real | No | |
DE_Barrage_Event | real | No | |
DE_Barrage_Missile | unitcode | No | |
DE_Barrage_Target | unit | No | |
DE_Barrage_Unit | unit | No | |
DE_Cult_Of_Darkness | boolean | Yes | |
DE_Cult_Of_Dread | boolean | Yes | |
DE_Cult_Of_Shadows | boolean | Yes | |
DE_Cult_Of_Spider | boolean | Yes | |
DE_Cult_Spec | effect | Yes | |
DE_Cult_Spider_level | integer | Yes | |
DE_DarkRadiance_BannedGroup | group | No | |
DE_DarkRadiance_GroupDisabled | group | No | |
DE_DarkRadiance_GroupEnabled | group | No | |
DE_DarkRadiance_GroupHealing | group | No | |
DE_DarkRadiance_Spec | unit | Yes | |
DE_DarkSacrifice_Mana | real | Yes | |
DE_Deathbolt_Caster | unit | Yes | |
DE_Deathbolt_Group | group | No | |
DE_Deathbolt_GroupSkeletons | group | No | |
DE_Deathbolt_TimerSkeletons | real | Yes | |
DE_Devour_Magic_Integer | integer | Yes | |
DE_Disintegrate_Counter | integer | Yes | |
DE_Disintegrate_Group | group | No | |
DE_Disintegrate_Lightning | lightning | Yes | |
DE_Disintegrate_SlowCount | integer | Yes | |
DE_Disintegrate_Spec | effect | Yes | |
DE_Disintegrate_Target | unit | Yes | |
DE_Disintegrate_Timer | real | Yes | |
DE_Entropy_Group | group | No | |
DE_Entropy_Source | unit | Yes | |
DE_Faith | real | Yes | |
DE_Faith_Miltiboard | multiboard | Yes | |
DE_Faith_Trigger_Amount | real | No | |
DE_Faith_Trigger_Key | integer | No | |
DE_Favor | real | Yes | |
DE_Global_ManaDuration | real | Yes | |
DE_Global_ManaGroup | group | No | |
DE_Global_ManaSpec | effect | Yes | |
DE_Global_NestGroup | group | No | |
DE_Global_NestTimer | real | Yes | |
DE_Global_NightmareDurtaion | real | Yes | |
DE_Global_NightmareGroup | group | No | |
DE_Global_NightmareSpec | effect | Yes | |
DE_Global_ProvidenceDuration | real | Yes | |
DE_Global_ProvidenceGroup | group | No | |
DE_Global_ProvidenceSpec | effect | Yes | |
DE_Global_StrideDuration | real | Yes | |
DE_Global_StrideGroup | group | No | |
DE_Global_StrideSpec | effect | Yes | |
DE_Goldmine_Arcanum | unit | Yes | |
DE_Goldmine_ArcanumBoolean | boolean | Yes | |
DE_Goldmine_ArcanumWorkers | integer | Yes | |
DE_Goldmine_Nexus | unit | Yes | |
DE_Goldmine_NexusCounter | real | Yes | |
DE_Goldmine_Notified | boolean | Yes | |
DE_Goldmine_WorkerArcanum | unit | Yes | |
DE_Goldmine_WorkerGroup | group | No | |
DE_GoldmineAngle | real | Yes | |
DE_GoldmineCounter | integer | Yes | |
DE_GoldmineGroup | group | No | |
DE_Hero_Beacon_AINT | integer | No | |
DE_Hero_Beacon_Angle | real | Yes | |
DE_Hero_Beacon_BINT | integer | No | |
DE_Hero_Beacon_Caster | unit | Yes | |
DE_Hero_Beacon_Duration | real | Yes | |
DE_Hero_Beacon_IsActive | boolean | Yes | |
DE_Hero_Beacon_Level | integer | Yes | |
DE_Hero_Beacon_Point | location | Yes | |
DE_Hero_Beacon_Timer | real | Yes | |
DE_Hero_Charge_Angle | real | Yes | |
DE_Hero_Charge_Damaged | boolean | Yes | |
DE_Hero_Charge_DamagedGroup | group | No | |
DE_Hero_Charge_Distance | real | Yes | |
DE_Hero_Charge_Group | group | No | |
DE_Hero_Charge_Level | integer | Yes | |
DE_Hero_Charge_Point | location | Yes | |
DE_Hero_Charge_TargetDistance | real | Yes | |
DE_Hero_DemFamBool | boolean | Yes | |
DE_Hero_DemFamOwner | unit | Yes | |
DE_Hero_DemFamUnit | unit | Yes | |
DE_Hero_EnrageDuration | real | Yes | |
DE_Hero_EnrageGroup | group | No | |
DE_Hero_Grasp_Caster | unit | Yes | |
DE_Hero_Grasp_Group | group | No | |
DE_Hero_Grasp_Level | integer | Yes | |
DE_Hero_Grasp_Timer | real | Yes | |
DE_Hero_Shadowdance_Bool | boolean | No | |
DE_Hero_Shadowdance_Duration | real | Yes | |
DE_Hero_Shadowdance_Group | group | No | |
DE_Hero_Shadowdance_Owner | unit | Yes | |
DE_Hero_Shadowdance_Targets | group | No | |
DE_Hero_Shadowrun_Group | group | No | |
DE_Hero_ShadowVeil_Level | integer | Yes | |
DE_Hero_Voidbolt_Caster | unit | Yes | |
DE_Hero_Voidbolt_Level | integer | Yes | |
DE_Hero_Witherwind_Caster | unit | Yes | |
DE_Hero_Witherwind_Level | integer | Yes | |
DE_Implosion_Group | group | No | |
DE_Implosion_Spec | effect | Yes | |
DE_Implosion_Timer | integer | Yes | |
DE_Infestation_Egg_Group | group | No | |
DE_Infestation_Group | group | No | |
DE_Infestation_Owner | player | Yes | |
DE_Invocation_Acolyte_Spec | effect | Yes | |
DE_Invocation_Acolytes_Group | group | No | |
DE_Invocation_Faith_Counter | real | Yes | |
DE_Invocation_Shrine | unit | Yes | |
DE_Invocation_Shrine_Devotees | integer | Yes | |
DE_Invocation_Shrine_Group | group | No | |
DE_LivingBombs_Group | group | No | |
DE_LivingBombs_Spec | effect | Yes | |
DE_LivingBombs_Timer | integer | Yes | |
DE_ManaLink_Group | group | No | |
DE_ManaLink_Target | unit | Yes | |
DE_Mesmerize_Delay | real | Yes | |
DE_Mesmerize_Group | group | No | |
DE_Mesmerize_Lightning | lightning | Yes | |
DE_Mesmerize_Target | unit | Yes | |
DE_Nexus_Dummy | unit | Yes | |
DE_Nexus_Spec | effect | Yes | |
DE_Parry_Group | group | No | |
DE_Parry_TimerAnimation | real | Yes | |
DE_Parry_TimerCooldown | real | Yes | |
DE_Parry_TimerTarget | unit | Yes | |
DE_PortalLink_Bool | boolean | Yes | |
DE_PortalLink_Group | group | No | |
DE_PortalLink_Region | rect | Yes | |
DE_PortalLink_RegionRegistered | boolean | Yes | |
DE_PortalLink_Target | unit | Yes | |
DE_Promotion_WidowmakerDebugg | group | No | |
DE_Shadowflame_Caster | unit | Yes | |
DE_Shadows_AttackType | attacktype | Yes | |
DE_Shadows_Damage | real | Yes | |
DE_Shadows_Group | group | No | |
DE_Shadows_Owner | unit | Yes | |
DE_Shadows_Timer | real | Yes | |
DE_ShadowStep_Group | group | No | |
DE_ShadowStep_Target | unit | Yes | |
DE_ShadowWalk_Group | group | No | |
DE_ShadowWalk_Spec | effect | Yes | |
DE_ShadowWalk_Timer | real | Yes | |
DE_Spiderbane_CooldownGroup | group | No | |
DE_Spiderbane_CooldownTimer | real | Yes | |
DE_Spire_Alarm | boolean | Yes | |
DE_Spire_AlarmDuration | real | Yes | |
DE_Spire_AnimGroup | group | No | |
DE_Spire_AnimTimer | real | Yes | |
DE_Spire_Count | integer | Yes | |
DE_Spire_Count_Stasis | integer | Yes | |
DE_Spire_GargsAlarm | boolean | Yes | |
DE_Spire_GargsGroup | group | No | |
DE_Spire_GargsOwner | unit | Yes | |
DE_Spire_Group | group | No | |
DE_Spire_Order | boolean | No | |
DE_Spire_Ownership | boolean | Yes | |
DE_Spire_Target | unit | Yes | |
DE_Spire_Timer | real | Yes | |
DE_StaffOfNexus_Group | group | No | |
DE_StaffOfNexus_Link | unit | Yes | |
DE_Summon_Daemon_Angle | real | Yes | |
DE_Summon_Daemon_Group | group | No | |
DE_Summon_Daemon_Source | unit | Yes | |
DE_Summon_Daemon_Spec | effect | Yes | |
DE_Summon_Daemon_Unit | unit | Yes | |
DE_Summon_Imp_Dummy | unit | Yes | |
DE_Summon_Imp_Group | group | No | |
DE_Summon_Imp_Progress | real | Yes | |
DE_Summon_Incubus_Group | group | No | |
DE_Summon_Incubus_Source | unit | Yes | |
DE_Tech_Dummy1 | unit | Yes | |
DE_Tech_Dummy2 | unit | Yes | |
DE_Tech_Dummy3 | unit | Yes | |
DE_Tech_Tier2Reached | boolean | Yes | |
DE_Tech_Tier3Reached | boolean | Yes | |
DE_Teching_Bool | boolean | Yes | |
DE_Teching_Dummy | unit | Yes | |
DE_Teching_Group | group | No | |
DE_Terror_Boolean | boolean | No | |
DE_Terror_Damage | real | Yes | |
DE_Terror_Duration | real | Yes | |
DE_Terror_Group | group | No | |
DE_Terror_PointCurrent | location | Yes | |
DE_Terror_PointStart | location | Yes | |
DE_Terror_Timer | real | Yes | |
DE_Venom_AINT | integer | No | |
DE_Venom_BINT | integer | No | |
DE_Venom_Damage | real | Yes | |
DE_Venom_Duration | real | Yes | |
DE_Venom_IsActive | boolean | Yes | |
DE_Venom_Owner | unit | Yes | |
DE_Venom_Spec | effect | Yes | |
DE_Venom_SpecCounter | integer | Yes | |
DE_Venom_Target | unit | Yes | |
DE_Venom_Timer | real | Yes | |
DE_Voidblast_Caster | unit | Yes | |
DE_Voidfall_Group | group | No | |
DE_Voidrain_Counter | integer | Yes | |
DE_Voidrain_Group | group | No | |
DE_Voidrain_RainAngle | real | Yes | |
DE_Voidrain_RainBool | boolean | Yes | |
DE_Voidrain_RainGroup | group | No | |
DE_Voidrain_RainTimer | real | Yes | |
DE_Voidrain_Timer | real | Yes | |
DE_Voidray_Angle | real | Yes | |
DE_Voidray_Damaged | boolean | Yes | |
DE_Voidray_DamagedGroup | group | No | |
DE_Voidray_Distance | real | Yes | |
DE_Voidray_Group | group | No | |
DE_Voidray_Lightning | lightning | Yes | |
DE_Voidray_Point | location | Yes | |
DE_Voidstone_Duration | real | Yes | |
DE_Voidstone_Group | group | No | |
DmgAMSGroup | group | No | |
DmgAMSHealth | real | Yes | |
DmgEvBracers | itemcode | No | |
DmgEvMana | real | No | |
DmgEvManaMult | real | No | |
DmgEvMSlvl | integer | No | |
DmgEvRecursionN | integer | No | |
DmgEvRunning | boolean | No | |
DmgEvStarted | boolean | No | |
DmgEvTimer | timer | No | |
DmgEvTrig | trigger | No | |
EnhancedDamageTarget | unit | No | |
HideDamageFrom | boolean | Yes | |
IsDamageSpell | boolean | No | |
IsDamageTriggered | boolean | No | |
IsUnitPreplaced | boolean | Yes | |
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 | |
Temp_Ability | abilcode | No | |
Temp_Bool | boolean | No | |
Temp_Group | group | No | |
Temp_Group2 | group | No | |
Temp_Integer | integer | No | |
Temp_Integer2 | integer | No | |
Temp_Item | itemcode | No | |
Temp_Key | integer | No | |
Temp_Lightning | lightning | No | |
Temp_Player | player | No | |
Temp_PlayerGroup | force | No | |
Temp_PlayerGroup2 | force | No | |
Temp_Real | real | No | |
Temp_Real2 | real | No | |
Temp_Unit | unit | No | |
Temp_Unit2 | unit | No | |
Temp_Unit_Type | unitcode | No | |
TempPoint | location | No | |
TempPoint2 | location | No | |
TempPoint3 | location | No | |
UDex | integer | No | |
UDexGen | integer | No | |
UDexNext | integer | Yes | |
UDexPrev | integer | Yes | |
UDexRecycle | integer | No | |
UDexUnits | unit | Yes | |
UDexWasted | integer | No | |
UMovNext | integer | Yes | |
UMovPrev | integer | Yes | |
UnitDamageRegistered | boolean | Yes | |
UnitIndexerEnabled | boolean | No | |
UnitIndexEvent | real | No | |
UnitMovementInterval | real | No | |
UnitMoving | boolean | Yes | |
UnitMovingEvent | real | No | |
UnitMovingX | real | Yes | |
UnitMovingY | real | Yes | |
zaDamage | real | No | |
zaTargetOfCurrentOrder | unit | Yes | |
zaUnderConstruction | group | No |
//TESH.scrollpos=75
//TESH.alwaysfold=0
function IsUnitMovementTracked takes integer i returns boolean
return udg_UMovPrev[i] != 0 or udg_UMovNext[0] == i
endfunction
function UnitMovementRegister takes nothing returns boolean
local integer i = udg_UDex
if not IsUnitMovementTracked(i) and TriggerEvaluate(gg_trg_Is_Unit_Moving_Config) then
set udg_UMovPrev[udg_UMovNext[0]] = i
set udg_UMovNext[i] = udg_UMovNext[0]
set udg_UMovNext[0] = i
set udg_UnitMovingX[i] = GetUnitX(udg_UDexUnits[i])
set udg_UnitMovingY[i] = GetUnitY(udg_UDexUnits[i])
endif
return false
endfunction
function UnitMovementUnregister takes nothing returns boolean
local integer i = udg_UDex
if IsUnitMovementTracked(i) then
set udg_UnitMoving[i] = false
set udg_UMovNext[udg_UMovPrev[i]] = udg_UMovNext[i]
set udg_UMovPrev[udg_UMovNext[i]] = udg_UMovPrev[i]
set udg_UMovPrev[i] = 0
endif
return false
endfunction
function RunUnitMovementEvent takes integer i, real e returns nothing
local integer pdex = udg_UDex
if e == 1.00 then
set udg_UnitMoving[i] = true
else
set udg_UnitMoving[i] = false
endif
set udg_UDex = i
set udg_UnitMovingEvent = e
set udg_UnitMovingEvent = 0.00
set udg_UDex = pdex
endfunction
//===========================================================================
// This function runs periodically to check if units are actually moving.
//
function UnitMovementTracker takes nothing returns nothing
local integer i = 0
local integer n
local real x
local real y
loop
set i = udg_UMovNext[i]
exitwhen i == 0
set x = GetUnitX(udg_UDexUnits[i])
set y = GetUnitY(udg_UDexUnits[i])
if x != udg_UnitMovingX[i] or y != udg_UnitMovingY[i] then
set udg_UnitMovingX[i] = x
set udg_UnitMovingY[i] = y
if not udg_UnitMoving[i] then
if GetUnitTypeId(udg_UDexUnits[i]) != 0 then
call RunUnitMovementEvent(i, 1.00)
else
set n = udg_UDex
set udg_UDex = i
set i = udg_UMovPrev[i] //avoid skipping checks
call UnitMovementUnregister()
set udg_UDex = n
endif
endif
elseif udg_UnitMoving[i] then
call RunUnitMovementEvent(i, 2.00)
endif
endloop
endfunction
//===========================================================================
function InitTrig_Is_Unit_Moving takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterVariableEvent(t, "udg_UnitIndexEvent", EQUAL, 1.00)
call TriggerAddCondition(t, Filter(function UnitMovementRegister))
set t = CreateTrigger()
call TriggerRegisterVariableEvent(t, "udg_UnitIndexEvent", EQUAL, 2.00)
call TriggerAddCondition(t, Filter(function UnitMovementUnregister))
if gg_trg_Is_Unit_Moving_Config != null then
call TriggerExecute(gg_trg_Is_Unit_Moving_Config)
else
call ExecuteFunc("Trig_Is_Unit_Moving_Config_Actions")
endif
call TimerStart(CreateTimer(), udg_UnitMovementInterval, true, function UnitMovementTracker)
endfunction
//===========================================================================
// 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 2017 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 2017 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 2017 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(bj_PLAYER_NEUTRAL_EXTRA), 'uloc', 0, 0, 0)
local integer i = bj_MAX_PLAYERS //Fixed in 3.8
//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