//TESH.scrollpos=225
//TESH.alwaysfold=0
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
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// EOT System header file
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//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
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Delayed Order Snippet
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function IssueOrderCallback takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer id = GetHandleId(t)
local unit whichUnit = LoadUnitHandle(udg_DelayedOrder_Hashtable, id, 0)
local integer orderType = LoadInteger(udg_DelayedOrder_Hashtable, id, 1)
local string order = LoadStr(udg_DelayedOrder_Hashtable, id, 2)
local widget targetWidget
local location targetLocation
local integer unitTypeId
if orderType == udg_DelayedOrder_TypeTarget then
set targetWidget = LoadWidgetHandle(udg_DelayedOrder_Hashtable, id, 3)
call IssueTargetOrder(whichUnit, order, targetWidget)
set targetWidget = null
elseif orderType == udg_DelayedOrder_TypePointTarget then
set targetLocation = LoadLocationHandle(udg_DelayedOrder_Hashtable, id, 3)
call IssuePointOrder(whichUnit, order, GetLocationX(targetLocation), GetLocationY(targetLocation))
call RemoveLocation(targetLocation)
set targetLocation = null
elseif orderType == udg_DelayedOrder_TypeTrain then
set unitTypeId = LoadInteger(udg_DelayedOrder_Hashtable, id, 3)
call IssueImmediateOrderById(whichUnit, unitTypeId)
elseif orderType == udg_DelayedOrder_TypeNoTarget then
call IssueImmediateOrder(whichUnit, order)
endif
call FlushChildHashtable(udg_DelayedOrder_Hashtable, id)
call DestroyTimer(t)
set t = null
set whichUnit = null
endfunction
function IssueTargetOrderDelayed takes unit whichUnit, string order, widget targetWidget, real delay returns nothing
local timer t = CreateTimer()
local integer id = GetHandleId(t)
call TimerStart(t, delay, false, function IssueOrderCallback)
call SaveUnitHandle(udg_DelayedOrder_Hashtable, id, 0, whichUnit)
call SaveInteger(udg_DelayedOrder_Hashtable, id, 1, udg_DelayedOrder_TypeTarget)
call SaveStr(udg_DelayedOrder_Hashtable, id, 2, order)
call SaveWidgetHandle(udg_DelayedOrder_Hashtable, id, 3, targetWidget)
set t = null
endfunction
function IssuePointOrderDelayed takes unit whichUnit, string order, location targetLocation, real delay returns nothing
local timer t = CreateTimer()
local integer id = GetHandleId(t)
call TimerStart(t, delay, false, function IssueOrderCallback)
call SaveUnitHandle(udg_DelayedOrder_Hashtable, id, 0, whichUnit)
call SaveInteger(udg_DelayedOrder_Hashtable, id, 1, udg_DelayedOrder_TypePointTarget)
call SaveStr(udg_DelayedOrder_Hashtable, id, 2, order)
call SaveLocationHandle(udg_DelayedOrder_Hashtable, id, 3, targetLocation)
set t = null
endfunction
function IssueTrainOrderDelayed takes unit whichUnit, integer unitTypeId, real delay returns nothing
local timer t = CreateTimer()
local integer id = GetHandleId(t)
call TimerStart(t, delay, false, function IssueOrderCallback)
call SaveUnitHandle(udg_DelayedOrder_Hashtable, id, 0, whichUnit)
call SaveInteger(udg_DelayedOrder_Hashtable, id, 1, udg_DelayedOrder_TypeNoTarget)
call SaveInteger(udg_DelayedOrder_Hashtable, id, 3, unitTypeId)
set t = null
endfunction
function IssueImmediateOrderDelayed takes unit whichUnit, string order, real delay returns nothing
local timer t = CreateTimer()
local integer id = GetHandleId(t)
call TimerStart(t, delay, false, function IssueOrderCallback)
call SaveUnitHandle(udg_DelayedOrder_Hashtable, id, 0, whichUnit)
call SaveInteger(udg_DelayedOrder_Hashtable, id, 1, udg_DelayedOrder_TypeNoTarget)
call SaveStr(udg_DelayedOrder_Hashtable, id, 2, order)
set t = null
endfunction
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// End Delayed Order Snippet
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Name | Type | is_array | initial_value |
Bowsette_Ability | abilcode | No | |
Bowsette_AbilityLevel | integer | Yes | |
Bowsette_AbilityOrderID | string | No | |
Bowsette_AttackCounter | real | Yes | |
Bowsette_Caster | unit | Yes | |
Bowsette_CasterLoc | location | Yes | |
Bowsette_Counter | real | Yes | |
Bowsette_Duration | real | Yes | |
Bowsette_IndexCurrent | integervar | No | |
Bowsette_IndexMax | integer | No | |
Bowsette_PeriodicTimer | real | No | |
Bowsette_Player | player | Yes | |
Bowsette_PointTarget | location | Yes | |
Bowsette_PulseInterval | real | No | |
CenterPoint | location | No | |
CP_HiddenItems | item | Yes | |
CP_HiddenItemsIndex | integer | No | |
CP_Item | item | No | |
CP_Point | location | No | |
CP_PointIsWalkable | boolean | No | |
CP_Rect | rect | No | |
D_M_Tatsumaki | real | Yes | |
DamageEventAmount | real | No | |
DeathGripAngle | real | No | |
DeathGripCaster | unit | No | |
DeathGripDistance | real | No | |
DeathGripHashtable | hashtable | No | |
DeathGripPosition | location | No | |
DeathGripPosition2 | location | No | |
DeathGripRemainingTime | real | No | |
DeathGripUnitGroup | group | No | |
DelayedOrder_Hashtable | hashtable | No | |
DelayedOrder_TypeNoTarget | integer | No | |
DelayedOrder_TypePointTarget | integer | No | |
DelayedOrder_TypeTarget | integer | No | |
DelayedOrder_TypeTrain | integer | No | |
DetectClosestUnit | unit | No | |
DetectFinalPickedUnitLocation | location | No | |
DetectPickedUnit | unit | No | |
DetectPickedUnitDistance | real | No | |
DetectPickedUnitLocation | location | No | |
DetectShortestDistance | real | No | |
DetectTempPoint | location | 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 | |
FF_Ability_ID | abilcode | No | |
FF_Angle | real | Yes | |
FF_AoE | real | Yes | |
FF_Attack_Type | attacktype | No | |
FF_Caster | unit | Yes | |
FF_Current_Index | integervar | No | |
FF_Damage | real | Yes | |
FF_Damage_Type | damagetype | No | |
FF_DamagedUnits | group | Yes | |
FF_DestroyTree | boolean | No | |
FF_Distance | real | Yes | |
FF_Level | integer | Yes | |
FF_Max_Index | integer | No | |
FF_ReachedDist | real | Yes | |
FF_Spec | string | No | |
FF_Speed | real | Yes | |
FF_TreeDestroyer | unit | No | |
FF_TreeDestroyer_ID | unitcode | No | |
FF_Velo | real | Yes | |
Flag30Seconds | boolean | No | |
FlagCommandItemDrop | boolean | No | |
FlagCommandItemDropAll | boolean | No | |
FlagUniqueRandomEventCooldown | boolean | No | |
Hashtable | hashtable | No | |
Hina_Ability | abilcode | No | |
Hina_AbilityLevel | integer | Yes | |
Hina_AbilityOrderID | string | No | |
Hina_AttackCounter | real | Yes | |
Hina_Caster | unit | Yes | |
Hina_CasterLoc | location | Yes | |
Hina_Counter | real | Yes | |
Hina_Duration | real | Yes | |
Hina_IndexCurrent | integer | No | |
Hina_IndexMax | integer | No | |
Hina_PeriodicTimer | real | No | |
Hina_Player | player | Yes | |
Hina_PulseInterval | real | No | |
HTERID | handle | No | |
HTKumokoEggRevival | hashtable | 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 | |
Knockback_Demi_Shockwave | boolean | Yes | |
MCS_AttachmentPoint1 | string | No | |
MCS_AttachmentPoint2 | string | No | |
MCS_Caster1 | unit | No | |
MCS_Caster2 | unit | Yes | |
MCS_curDuration | real | Yes | |
MCS_Deadboolean | boolean | Yes | |
MCS_Duration1 | real | No | |
MCS_Duration2 | real | Yes | |
MCS_Integer | integer | Yes | |
MCS_MindControlledGroup | group | No | |
MCS_Player | player | Yes | |
MCS_SfxAtEndString | string | No | |
MCS_SfxAtEndString2 | string | Yes | |
MCS_SfxAtStartString | modelfile | No | |
MCS_SfxContinous1 | effect | Yes | |
MCS_SfxContinous1String | string | No | |
MCS_SfxContinous2 | effect | Yes | |
MCS_SfxContinous2String | string | No | |
MCS_Target1 | unit | No | |
MCS_Target2 | unit | Yes | |
MS_Ability | abilcode | No | |
MS_AbilityLvl | integer | Yes | |
MS_AbilityStun | abilcode | No | |
MS_AoE | real | No | |
MS_AttackType | attacktype | No | |
MS_Blue | real | No | |
MS_Caster | unit | Yes | |
MS_Counter_SFX | real | Yes | |
MS_CurrentHeight | real | No | |
MS_Damage | real | Yes | |
MS_DamageType | damagetype | No | |
MS_DestroyTreeAoE | real | No | |
MS_DestroyTrees | boolean | No | |
MS_DistanceTraveled | real | Yes | |
MS_Dummy | unitcode | No | |
MS_DummyCaster | unit | No | |
MS_FallRate_XY | real | No | |
MS_FallRate_Z | real | No | |
MS_FallTime | real | No | |
MS_Green | real | No | |
MS_KBAoE | real | No | |
MS_KBDistance | real | No | |
MS_KBTime | real | No | |
MS_LandAoE | real | No | |
MS_LandingDamage | real | No | |
MS_LoopInt | integervar | No | |
MS_M_SpawnDistance | real | No | |
MS_M_SpawnHeight | real | No | |
MS_MaxIndex | integer | No | |
MS_MaxLevel | integer | No | |
MS_Meteor_SFX | effect | Yes | |
MS_MeteorDummy | unit | Yes | |
MS_MeteorLoc | location | No | |
MS_MeteorSize | real | No | |
MS_MoveRate | real | Yes | |
MS_NodeNext | integer | Yes | |
MS_NodePrev | integer | Yes | |
MS_Owner | player | Yes | |
MS_PeriodicTimer | real | No | |
MS_RecycledSize | integer | No | |
MS_RecycledStack | integer | Yes | |
MS_Red | real | No | |
MS_RollDirection | real | Yes | |
MS_RollDistance | real | Yes | |
MS_RollTime | real | Yes | |
MS_SFX_FallFreq | real | No | |
MS_SFX_RollFreq | real | Yes | |
MS_SFXDeath | string | No | |
MS_SFXFall | string | No | |
MS_SFXKB | string | No | |
MS_SFXLand | string | No | |
MS_SFXMeteor | string | No | |
MS_SFXRoll | string | No | |
MS_Size | real | No | |
MS_Spell_ID | integer | No | |
MS_SpellCount | integer | No | |
MS_Stage | integer | Yes | |
MS_StunAoE | real | No | |
MS_TargetLoc | location | Yes | |
MS_TempDest | destructable | No | |
MS_TempHeight | real | No | |
MS_TempInt | integervar | No | |
MS_TempLoc | location | No | |
MS_TempReal | real | No | |
MS_TempUnit | unit | No | |
MS_TreeKiller | unit | 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 | |
RandomCivilianTypeVariant | unitcode | Yes | |
RandomCreepGateTypeVariant | unitcode | Yes | |
RandomCreepGateTypeVariantNum | integer | No | |
RandomCreepTypeVariantA | unitcode | Yes | |
RandomCreepTypeVariantB | unitcode | Yes | |
RandomCreepTypeVariantNum | integer | No | |
S_caster | unit | Yes | |
S_dummy | unit | Yes | |
S_dummypoint | location | No | |
S_index1 | integer | Yes | |
S_index2 | integer | No | |
S_index3 | integervar | No | |
S_index_max | integer | No | |
S_index_size | integer | No | |
S_pause | boolean | Yes | |
S_speed | real | Yes | |
S_stopduration | real | Yes | |
S_stopgroup | group | Yes | |
S_targetpoint | location | No | |
SW_AffectAir | boolean | Yes | |
SW_AffectAlly | boolean | Yes | |
SW_AffectEnemy | boolean | Yes | |
SW_AffectGround | boolean | Yes | |
SW_AffectStructure | boolean | Yes | |
SW_Angle | real | No | |
SW_AreaCurrent | real | Yes | |
SW_AreaFinal | real | Yes | |
SW_AreaGrowth | real | Yes | |
SW_AreaInitial | real | Yes | |
SW_Attachment | string | No | |
SW_AttackType | attacktype | Yes | |
SW_Caster | unit | Yes | |
SW_Damage | real | Yes | |
SW_DamageType | damagetype | Yes | |
SW_DamageX | real | Yes | |
SW_Distance | real | Yes | |
SW_DistanceX | real | Yes | |
SW_Dummy | unit | Yes | |
SW_ExtraEffect | trigger | Yes | |
SW_ExtraEffectCheck | boolean | Yes | |
SW_ExtraEffectTarget | trigger | Yes | |
SW_ExtraEffectTargetCheck | boolean | Yes | |
SW_Group | group | No | |
SW_GroupDone | group | Yes | |
SW_Loop | integervar | No | |
SW_LoopingSfx | boolean | Yes | |
SW_Lvl | integer | Yes | |
SW_Max | integer | No | |
SW_NextPoint | location | Yes | |
SW_OneInstance | boolean | Yes | |
SW_Point | location | Yes | |
SW_Speed | real | Yes | |
SW_SpeedX | real | Yes | |
SW_Wave | effect | Yes | |
SW_WaveEffect | modelfile | Yes | |
SW_WaveEffectEnd | modelfile | Yes | |
SW_WaveEffectLoop | modelfile | Yes | |
T_P_Tatsumaki | location | Yes | |
TargetPoint | location | No | |
Tauren_WarStomp | boolean | Yes | |
TavernGroup2 | group | No | |
TavernGroup3 | group | No | |
TavernGroup4 | group | No | |
TavernInitialGroup | group | No | |
TavernInitialLoc | location | No | |
TavernInt | integer | No | |
TavernUnit | unit | Yes | |
TempAbility | abilcode | No | |
TempAbilityCopy | abilcode | Yes | |
TempAbilityCopy2 | abilcode | No | |
tempAngle_Real | real | No | |
TempBowserAirshipLoadedGroup | group | No | |
TempBowserAirshipUnitGroup | group | No | |
TempBowsetteRegion | rect | No | |
TempBRSCurrentMana | integer | Yes | |
tempCaster | unit | No | |
TempCasterUnit | unit | No | |
TempCasterUnit2 | unit | No | |
tempDamage_Scaling_Total | real | No | |
tempDamage_Total | real | No | |
TempDest | destructable | No | |
TempDummyUnit | unit | No | |
tempDuration_Total | real | No | |
TempEntomaPlayerUnit | unit | Yes | |
TempGoblinSlayerDyingUnit | unit | No | |
TempGoblinSlayerPlayerCooldown | boolean | Yes | |
TempGoblinSlayerPlayerUnit | unit | Yes | |
TempGoblinSlayerPlayerUnitLoc | location | Yes | |
TempGroup | group | No | |
TempHPBonusAbilityLvl | integer | Yes | |
TempHPBonusLvl1Learned | boolean | Yes | |
TempHPBonusLvl2Learned | boolean | Yes | |
TempHPBonusLvl3Learned | boolean | Yes | |
TempHPBonusReal | real | Yes | |
TempHPBoostInt | integer | Yes | |
TempIndexCounter | integer | Yes | |
TempIndexCurrent | integervar | No | |
TempIndexMax | integer | No | |
TempIndexPoint | location | Yes | |
TempIndexUnit | unit | Yes | |
TempInt | integer | No | |
TempInt2 | integer | No | |
TempInt3 | integer | No | |
tempInt_Counter | integer | No | |
tempInt_Counter_2 | integer | No | |
TempInteger | integer | No | |
TempInventoryItems | item | Yes | |
tempItem | item | No | |
tempKey | integer | No | |
TempKnockbackBRSDeadMaster | boolean | Yes | |
TempKnockbackDemiShockwave | boolean | Yes | |
TempKnockbackMeteoricSmash | boolean | Yes | |
TempKumokoEggRevivalCooldown | boolean | Yes | |
TempKumokoEggRevivalHero | unit | Yes | |
TempKumokoPoisonSynthesis | boolean | Yes | |
TempKumokoPoisonSynthesisLevel | integer | Yes | |
TempKumokoStickyWebTrapLevel | integer | Yes | |
TempLearner | unit | No | |
tempLevel | real | No | |
TempLoc | location | No | |
TempLocation | location | No | |
TempNum | integer | No | |
TempNum2 | integer | No | |
TempOwner | player | No | |
TempPickedUnit | unit | No | |
tempPickedUnit | unit | No | |
TempPlayer | player | No | |
TempPlayerIDNum | integer | No | |
TempPlayerUnit | unit | Yes | |
TempPoint | location | No | |
TempPoint2 | location | No | |
TempPoint3 | location | No | |
tempPoint_Target | location | No | |
tempPoint_Temp | location | No | |
tempPoint_Whirlpool | location | No | |
TempPointEvent | location | No | |
TempPointEvent2 | location | No | |
tempPull_Intensity_Total | real | No | |
TempRandomEventRescuableUnits | integer | No | |
tempRange_Total | real | No | |
TempReal | real | No | |
TempStormCasterUnitGroup | group | No | |
TempStormPoint | location | No | |
TempStormRegion | rect | No | |
TempStormUnit | unit | No | |
TempStormUnitGroup | group | No | |
TempTargetedUnit | unit | No | |
TempTimerKumokoEggRevival | timer | Yes | |
TempTimerRandomEventUnique | timer | No | |
TempUnit | unit | No | |
TempUnitBRSSource | unit | No | |
TempUnitBRSSourceLevel | integer | No | |
TempUnitBRSSourcePoint | location | No | |
TempUnitBRSTarget | unit | No | |
TempUnitEvent | unit | No | |
TempUnitFacing | real | No | |
TempUnitGroup | group | No | |
TempUnitGroupBRSSourceAura | group | No | |
TempUnitGroupBRSTargetAura | group | No | |
TempUnitGroupBRSTargetAuraNum | integer | No | |
TempUnitGroupEvent | group | No | |
TempUnitGroupHina | group | No | |
TempUnitGroupHinaMOV | group | No | |
TempUnitGroupHPJASourceAura | group | No | |
TempUnitGroupHPJATargetAura | group | No | |
TempUnitGroupHPJATargetAuraNum | integer | No | |
TempUnitHero | unit | No | |
TempUnitHJPASource | unit | No | |
TempUnitHJPASourcePoint | location | No | |
TempUnitHPJASourceLevel | integer | No | |
TempUnitHPJASourcePoint | location | No | |
TempUnitHPJATarget | unit | No | |
TempUnitNameString | string | No | |
TempUnitType | unitcode | No | |
TimerEventCountdown | timer | No | |
TimerEventSpecialCountdown | timer | No | |
TimerTimeElapsed | timer | No | |
TimerTimeElapsedSeconds | real | No | |
TimerTimeElapsedWindow | timerdialog | No | |
TimerTimeEventWindow | timerdialog | No | |
TS | integervar | No | |
TS_Angle | real | Yes | |
TS_Damage | real | Yes | |
TS_Distance | real | Yes | |
TS_Group | group | Yes | |
TS_Height | real | Yes | |
TS_Hero | unit | Yes | |
TS_MaxDistance | real | Yes | |
TS_Off | boolean | Yes | |
TS_Parabola | real | Yes | |
TS_Point | location | Yes | |
TS_Radius | real | Yes | |
TS_Skip | integer | No | |
TS_Slams | integer | Yes | |
TS_Speed | real | Yes | |
TS_Target | unit | Yes | |
TS_Times | integer | No | |
UAS_Count | integer | Yes | |
UAS_GroupDmgPass | group | Yes | |
UAS_KeepCastAngle | real | Yes | |
UAS_KeepCaster | unit | Yes | |
UAS_KeepColourReal | real | Yes | |
UAS_KeepDmgPass | real | Yes | |
UAS_KeepEff | effect | Yes | |
UAS_KeepLevel | integer | Yes | |
UAS_KeepMissile | unit | Yes | |
UAS_KeepSpeed | real | Yes | |
UAS_KeepTarget | unit | Yes | |
UAS_KeepTimeDurain | real | Yes | |
UAS_KeepTimeTrigger | real | Yes | |
UAS_KeepTriggerLoop | trigger | Yes | |
UAS_KeepWorking | boolean | Yes | |
UAS_TimeLoop | real | Yes | |
UAS_WantDesCount | boolean | Yes | |
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 | |
UnitIndexerEnabled | boolean | No | |
UnitIndexEvent | real | No | |
UnitMovementInterval | real | No | |
UnitMoving | boolean | Yes | |
UnitMovingEvent | real | No | |
UnitMovingX | real | Yes | |
UnitMovingY | real | Yes | |
WP_Ability_Order | string | No | |
WP_Attack_Type | attacktype | No | |
WP_Damage_Base | real | No | |
WP_Damage_Bonus | real | No | |
WP_Damage_Scaling_Base | real | No | |
WP_Damage_Scaling_Bonus | real | No | |
WP_Damage_Scaling_Max | real | No | |
WP_Damage_Type | damagetype | No | |
WP_Dummy_Loop | unit | No | |
WP_Dummy_Scale_Factor | real | No | |
WP_Dummy_Whirlpool | unit | No | |
WP_Duration_Base | real | No | |
WP_Duration_Bonus | real | No | |
WP_Duration_Max | real | No | |
WP_Effect_Center | string | No | |
WP_Effect_Hit | string | No | |
WP_Group_Counter | integer | No | |
WP_Hashtable | hashtable | No | |
WP_Interval_Integer | integer | No | |
WP_Loop_Group | group | No | |
WP_Pull_Intensity_Base | real | No | |
WP_Pull_Intensity_Bonus | real | No | |
WP_Pull_Intensity_Max | real | No | |
WP_Pull_Interval | integer | No | |
WP_Range_Base | real | No | |
WP_Range_Bonus | real | No | |
WP_Range_Max | real | No | |
WP_Spell_ID | abilcode | No | |
WP_Spell_ID_2 | abilcode | No | |
WP_Unit_Type_Dummy | unitcode | No | |
WP_Unit_Type_Whirl_Dummy | unitcode | No | |
WP_Unit_Type_Whirl_Dummy_2 | unitcode | No |
//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 = 'A000'
set udg_PDD_SET_MAX_LIFE = 'A001'
// 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
//TESH.scrollpos=0
//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
//TESH.scrollpos=205
//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
//TESH.scrollpos=82
//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
//TESH.scrollpos=0
//TESH.alwaysfold=0
/*
Meteor Strike
v2.01
by KILLCIDE
Did my absolute best to not make this similar to the Chaos Meteor from DotA D:
Requirements:
--------
- Check Walkability
- dummy.mdx
- GUI Knockback 2D
- GUI Unit Indexer
Credits:
-------
- Bribe for GUI Knockback 2D & GUI Unit Indexer
- PurgeandFire for Check Walkability
- Vexorian for the dummy.mdx
How to Install:
--------------
1. Under Preferences, make sure you have "Automatically create unknown variables while pasting trigger data" checked
2. Import dummy.mdx, then copy and paste the dummy unit and two custom abilities into your map
NOTE: If you already have dummy.mdx imported into your map, you DO NOT have to reimport it
If you already have a global dummy unit in your map, you can skip this step
3. Copy and paste the Resources folder into your map
NOTE: If you already have a resource in the Resources folder imported into your map, you DO NOT have to reimport it
4. Copy and paste the Meteor Strike folder into your map
5. Go to the MS Config trigger, and change the Ability, AbilityStun, & Dummy variables to the corresponding objects you just imported
Changelog:
---------
- v2.01 (March 22, 2016): Added an optional Meteor Strike folder that is integrated with GUI Spell System
Added Bribe's new knockback system update
Fixed bug of meteor falling at a completely different location when casted directly on top of the caster
Removed unnecesary NodeLast[] variable for linked list; last spell instance now stores into NodePrev[0]
Removed If/Then/Else that would set NodeLast = NodePrev[Spell_ID] if NodeLast == Spell_ID
- v2.00 (January 25, 2016): Added a filter for air units (both knockback and damage)
Changed data structure to linked listing
- v1.03 (December 05, 2015): Changed spell to now use one global dummy caster instead of one dummy caster per spell instance
Changed RollDirection to now be indexed with spell instance
Removed a lot of unnecessary calculations for FallRate and MoveRate (now done on init)
- v1.02 (December 03, 2015): Added multi-level support for rolling travel time & SFXRoll frequency
Changed MS Init trigger name to MS Cast
Fixed Owner[] variable to now use Triggering Player instead of Owner of (Unit)
Fixed a small bug where dummies for SFXFall were not being removed
Fixed Create a Unit functions to now reference MS_Dummy instead of actual dummy unit-type
Fixed self-made tree destroy system to be much safer by adding harvest ability to the created treeKiller
Removed Damage[] variable so that calculations are now done on map init instead of on cast
Removed unnecessary function call when turning off MS Loop (Turn off (This trigger) -> (Turn off MS Loop))
- v1.01 (December 02, 2015): Added Bribe's new knockback system update
Added a landing damage mechanic
Removed damage interval mechanic; spell now deals damage constantly as it rolls
- v1.00 (December 01, 2015): Uploaded onto Hive