//TESH.scrollpos=0
//TESH.alwaysfold=0
Name | Type | is_array | initial_value |
AfterDamageEvent | real | No | |
CargoEvent | real | No | |
CargoTransportGroup | group | Yes | |
CargoTransportUnit | unit | Yes | |
CheckDeathInList | boolean | Yes | |
CheckDeathList | integer | Yes | |
CheckDeathTimer | timer | No | |
ClearDamageEvent | trigger | No | |
DAMAGE_FACTOR_BRACERS | real | No | |
DAMAGE_FACTOR_ELUNES | real | No | |
DAMAGE_FACTOR_ETHEREAL | real | No | |
DamageBlockingAbility | abilcode | No | |
DamageEvent | real | No | |
DamageEventAmount | real | No | |
DamageEventOverride | boolean | No | |
DamageEventPrevAmt | real | No | |
DamageEventSource | unit | No | |
DamageEventsWasted | integer | No | |
DamageEventTarget | unit | No | |
DamageEventTrigger | trigger | No | |
DamageEventType | integer | No | |
DamageModifierEvent | real | No | |
DamageTypeBlocked | integer | No | |
DamageTypeCriticalStrike | integer | No | |
DamageTypeExplosive | integer | No | |
DamageTypeHeal | integer | No | |
DamageTypeReduced | integer | No | |
DeathEvent | real | No | |
DetectRemoveAbility | abilcode | No | |
DetectTransformAbility | abilcode | No | |
DmgEvBracers | itemcode | No | |
DmgEvRecursionN | integer | No | |
DmgEvRunning | boolean | No | |
DmgEvStarted | boolean | No | |
DmgEvTimer | timer | No | |
DmgEvTrig | trigger | No | |
HideDamageFrom | boolean | Yes | |
IsDamageSpell | boolean | No | |
IsUnitAlive | boolean | Yes | |
IsUnitBeingUnloaded | boolean | Yes | |
IsUnitNew | boolean | Yes | |
IsUnitPreplaced | boolean | Yes | |
IsUnitReincarnating | boolean | Yes | |
IsUnitRemoved | boolean | Yes | |
IsUnitTransforming | boolean | Yes | |
KillerOfUnit | unit | Yes | |
LastDamageHP | real | No | |
LastDmgPrevAmount | real | Yes | |
LastDmgPrevType | integer | Yes | |
LastDmgSource | unit | Yes | |
LastDmgTarget | unit | Yes | |
LastDmgValue | real | Yes | |
LastDmgWasSpell | boolean | Yes | |
NextDamageOverride | boolean | No | |
NextDamageType | integer | No | |
SpellDamageAbility | abilcode | No | |
SummonerOfUnit | unit | Yes | |
UDex | integer | No | |
UDexLastRecycled | integer | No | |
UDexMax | integer | No | |
UDexNext | integer | Yes | |
UDexPrev | integer | Yes | |
UDexUnits | unit | Yes | |
UnitDamageRegistered | boolean | Yes | |
UnitIndexerEnabled | boolean | No | |
UnitIndexEvent | real | No | |
UnitTypeEvent | real | No | |
UnitTypeOf | unitcode | Yes | |
V_BuffCaster | unit | No | |
V_Dur1 | real | Yes | |
V_Dur2 | real | Yes | |
V_I | integer | No | |
V_Timer | timer | No | |
V_Type | integer | Yes | |
V_Unit | unit | Yes | |
VB_Caster | unit | Yes | |
VB_Dmg | real | Yes | |
VB_Dummy | unit | Yes | |
VB_GroupSearch | group | No | |
VB_I | integer | No | |
VB_MissileModel | effect | Yes | |
VB_SDmg | real | Yes | |
VB_Target | unit | Yes | |
VB_Timer | timer | No | |
VD_Angle | real | Yes | |
VD_Caster | unit | Yes | |
VD_DamageGroup | group | Yes | |
VD_Dmg | real | Yes | |
VD_DmgDetectTrig | trigger | No | |
VD_Dummy | unit | Yes | |
VD_Effect | effect | Yes | |
VD_Group | group | No | |
VD_I | integer | No | |
VD_StackDmgCount | integer | Yes | |
VD_StackDmgEffect | effect | Yes | |
VD_StackDmgGroup | group | No | |
VD_Timer | timer | No | |
VD_Travel | real | Yes | |
WorldMaxX | real | No | |
WorldMaxY | real | No |
//TESH.scrollpos=0
//TESH.alwaysfold=0
//===========================================================================
function UnitEventDestroyGroup takes integer i returns nothing
if udg_CargoTransportGroup[i] != null then
call DestroyGroup(udg_CargoTransportGroup[i])
set udg_CargoTransportGroup[i] = null
endif
endfunction
function UnitEventCheckAfter takes nothing returns nothing
local integer i = 0
loop
set i = udg_CheckDeathList[i]
exitwhen i == 0
if udg_IsUnitNew[i] then
//The unit was just created.
set udg_IsUnitNew[i] = false
elseif udg_IsUnitTransforming[i] then
//Added 21 July 2017 to fix the issue re-adding this ability in the same instant
set udg_UDex = i
set udg_UnitTypeEvent = 0.00
set udg_UnitTypeEvent = 1.00
set udg_UnitTypeOf[i] = GetUnitTypeId(udg_UDexUnits[i]) //Set this afterward to give the user extra reference
set udg_IsUnitTransforming[i] = false
call UnitAddAbility(udg_UDexUnits[i], udg_DetectTransformAbility)
elseif udg_IsUnitAlive[i] then
//The unit has started reincarnating.
set udg_IsUnitReincarnating[i] = true
set udg_IsUnitAlive[i] = false
set udg_UDex = i
set udg_DeathEvent = 0.50
set udg_DeathEvent = 0.00
endif
set udg_CheckDeathInList[i] = false
endloop
//Empty the list
set udg_CheckDeathList[0] = 0
endfunction
function UnitEventCheckAfterProxy takes integer i returns nothing
if udg_CheckDeathList[0] == 0 then
call TimerStart(udg_CheckDeathTimer, 0.00, false, function UnitEventCheckAfter)
endif
if not udg_CheckDeathInList[i] then
set udg_CheckDeathList[i] = udg_CheckDeathList[0]
set udg_CheckDeathList[0] = i
set udg_CheckDeathInList[i] = true
endif
endfunction
function UnitEventOnUnload takes nothing returns nothing
local integer i = udg_UDex
call GroupRemoveUnit(udg_CargoTransportGroup[GetUnitUserData(udg_CargoTransportUnit[i])], udg_UDexUnits[i])
set udg_IsUnitBeingUnloaded[i] = true
set udg_CargoEvent = 0.00
set udg_CargoEvent = 2.00
set udg_CargoEvent = 0.00
set udg_IsUnitBeingUnloaded[i] = false
if not IsUnitLoaded(udg_UDexUnits[i]) or IsUnitType(udg_CargoTransportUnit[i], UNIT_TYPE_DEAD) or GetUnitTypeId(udg_CargoTransportUnit[i]) == 0 then
set udg_CargoTransportUnit[i] = null
endif
endfunction
function UnitEventOnDeath takes nothing returns boolean
local integer pdex = udg_UDex
set udg_UDex = GetUnitUserData(GetTriggerUnit())
if udg_UDex != 0 then
set udg_KillerOfUnit[udg_UDex] = GetKillingUnit() //Added 29 May 2017 for GIMLI_2
set udg_IsUnitAlive[udg_UDex] = false
set udg_DeathEvent = 0.00
set udg_DeathEvent = 1.00
set udg_DeathEvent = 0.00
set udg_KillerOfUnit[udg_UDex] = null
if udg_CargoTransportUnit[udg_UDex] != null then
call UnitEventOnUnload()
endif
endif
set udg_UDex = pdex
return false
endfunction
function UnitEventOnOrder takes nothing returns boolean
local integer pdex = udg_UDex
local unit u = GetFilterUnit()
local integer i = GetUnitUserData(u)
if i > 0 then
set udg_UDex = i
if GetUnitAbilityLevel(u, udg_DetectRemoveAbility) == 0 then
if not udg_IsUnitRemoved[i] then
set udg_IsUnitRemoved[i] = true
set udg_IsUnitAlive[i] = false
set udg_SummonerOfUnit[i] = null
//For backwards-compatibility:
set udg_DeathEvent = 0.00
set udg_DeathEvent = 3.00
set udg_DeathEvent = 0.00
//Fire deindex event for UDex:
set udg_UnitIndexEvent = 0.00
set udg_UnitIndexEvent = 2.00
set udg_UnitIndexEvent = 0.00
set udg_UDexNext[udg_UDexPrev[i]] = udg_UDexNext[i]
set udg_UDexPrev[udg_UDexNext[i]] = udg_UDexPrev[i]
// Recycle the index for later use
set udg_UDexUnits[i] = null
set udg_UDexPrev[i] = udg_UDexLastRecycled
set udg_UDexLastRecycled = i
call UnitEventDestroyGroup(i)
endif
elseif not udg_IsUnitAlive[i] then
if not IsUnitType(u, UNIT_TYPE_DEAD) then
set udg_IsUnitAlive[i] = true
set udg_DeathEvent = 0.00
set udg_DeathEvent = 2.00
set udg_DeathEvent = 0.00
set udg_IsUnitReincarnating[i] = false
endif
elseif IsUnitType(u, UNIT_TYPE_DEAD) then
if udg_IsUnitNew[i] then
//This unit was created as a corpse.
set udg_IsUnitAlive[i] = false
set udg_DeathEvent = 0.00
set udg_DeathEvent = 1.00
set udg_DeathEvent = 0.00
elseif udg_CargoTransportUnit[i] == null or not IsUnitType(u, UNIT_TYPE_HERO) then
//The unit may have just started reincarnating.
call UnitEventCheckAfterProxy(i)
endif
elseif GetUnitAbilityLevel(u, udg_DetectTransformAbility) == 0 and not udg_IsUnitTransforming[i] then
set udg_IsUnitTransforming[i] = true
call UnitEventCheckAfterProxy(i) //This block has been updated on 21 July 2017
endif
if udg_CargoTransportUnit[i] != null and not udg_IsUnitBeingUnloaded[i] and not IsUnitLoaded(u) or IsUnitType(u, UNIT_TYPE_DEAD) then
call UnitEventOnUnload()
endif
set udg_UDex = pdex
endif
set u = null
return false
endfunction
function UnitEventOnSummon takes nothing returns boolean
local integer pdex = udg_UDex
set udg_UDex = GetUnitUserData(GetTriggerUnit())
if udg_IsUnitNew[udg_UDex] then
set udg_SummonerOfUnit[udg_UDex] = GetSummoningUnit()
set udg_UnitIndexEvent = 0.00
set udg_UnitIndexEvent = 0.50
set udg_UnitIndexEvent = 0.00
endif
set udg_UDex = pdex
return false
endfunction
function UnitEventOnLoad takes nothing returns boolean
local integer pdex = udg_UDex
local integer i = GetUnitUserData(GetTriggerUnit())
local integer index
if i != 0 then
set udg_UDex = i
if udg_CargoTransportUnit[i] != null then
call UnitEventOnUnload()
endif
//Loaded corpses do not issue an order when unloaded, therefore must
//use the enter-region event method taken from Jesus4Lyf's Transport.
if not udg_IsUnitAlive[i] then
call SetUnitX(udg_UDexUnits[i], udg_WorldMaxX)
call SetUnitY(udg_UDexUnits[i], udg_WorldMaxY)
endif
set udg_CargoTransportUnit[i] = GetTransportUnit()
set index = GetUnitUserData(udg_CargoTransportUnit[i])
if udg_CargoTransportGroup[index] == null then
set udg_CargoTransportGroup[index] = CreateGroup()
endif
call GroupAddUnit(udg_CargoTransportGroup[index], udg_UDexUnits[i])
set udg_CargoEvent = 0.00
set udg_CargoEvent = 1.00
set udg_CargoEvent = 0.00
set udg_UDex = pdex
endif
return false
endfunction
function UnitEventEnter takes nothing returns boolean
local integer pdex = udg_UDex
local integer i = udg_UDexLastRecycled
local unit u = GetFilterUnit()
if udg_UnitIndexerEnabled and GetUnitAbilityLevel(u, udg_DetectRemoveAbility) == 0 then
//Generate a unique integer index for this unit
if i == 0 then
set i = udg_UDexMax + 1
set udg_UDexMax = i
else
set udg_UDexLastRecycled = udg_UDexPrev[i]
endif
//Link index to unit, unit to index
set udg_UDexUnits[i] = u
call SetUnitUserData(u, i)
//For backwards-compatibility, add the unit to a linked list
set udg_UDexNext[i] = udg_UDexNext[0]
set udg_UDexPrev[udg_UDexNext[0]] = i
set udg_UDexNext[0] = i
set udg_UDexPrev[i] = 0
set udg_CheckDeathInList[i] = false
call UnitAddAbility(u, udg_DetectRemoveAbility)
call UnitMakeAbilityPermanent(u, true, udg_DetectRemoveAbility)
call UnitAddAbility(u, udg_DetectTransformAbility)
set udg_UnitTypeOf[i] = GetUnitTypeId(u)
set udg_IsUnitNew[i] = true
set udg_IsUnitAlive[i] = true
set udg_IsUnitRemoved[i] = false
set udg_IsUnitReincarnating[i] = false
set udg_IsUnitPreplaced[i] = udg_IsUnitPreplaced[0] //Added 29 May 2017 for Spellbound
call UnitEventCheckAfterProxy(i)
//Fire index event for UDex
set udg_UDex = i
set udg_UnitIndexEvent = 0.00
set udg_UnitIndexEvent = 1.00
set udg_UnitIndexEvent = 0.00
else
set udg_UDex = GetUnitUserData(u)
if udg_CargoTransportUnit[udg_UDex] != null and not IsUnitLoaded(u) then
//The unit was dead, but has re-entered the map.
call UnitEventOnUnload()
endif
endif
set udg_UDex = pdex
set u = null
return false
endfunction
//===========================================================================
function UnitEventInit takes nothing returns nothing
local integer i = bj_MAX_PLAYER_SLOTS //update to make it work with 1.29
local player p
local trigger t = CreateTrigger()
local trigger load = CreateTrigger()
local trigger death = CreateTrigger()
local trigger summon = CreateTrigger()
local rect r = GetWorldBounds()
local region re = CreateRegion()
local boolexpr enterB = Filter(function UnitEventEnter)
local boolexpr orderB = Filter(function UnitEventOnOrder)
set udg_WorldMaxX = GetRectMaxX(r)
set udg_WorldMaxY = GetRectMaxY(r)
call RegionAddRect(re, r)
call RemoveRect(r)
call UnitEventDestroyGroup(0)
call UnitEventDestroyGroup(1)
set udg_CheckDeathList[0] = 0
set udg_UnitIndexerEnabled = true
call TriggerRegisterEnterRegion(CreateTrigger(), re, enterB)
call TriggerAddCondition(load, Filter(function UnitEventOnLoad))
call TriggerAddCondition(death, Filter(function UnitEventOnDeath))
call TriggerAddCondition(summon, Filter(function UnitEventOnSummon))
loop
set i = i - 1
set p = Player(i)
call SetPlayerAbilityAvailable(p, udg_DetectRemoveAbility, false)
call SetPlayerAbilityAvailable(p, udg_DetectTransformAbility, false)
call TriggerRegisterPlayerUnitEvent(summon, p, EVENT_PLAYER_UNIT_SUMMON, null)
call TriggerRegisterPlayerUnitEvent(t, p, EVENT_PLAYER_UNIT_ISSUED_ORDER, orderB)
call TriggerRegisterPlayerUnitEvent(death, p, EVENT_PLAYER_UNIT_DEATH, null)
call TriggerRegisterPlayerUnitEvent(load, p, EVENT_PLAYER_UNIT_LOADED, null)
call GroupEnumUnitsOfPlayer(bj_lastCreatedGroup, p, enterB)
exitwhen i == 0
endloop
set summon = null
set death = null
set load = null
set re = null
set enterB = null
set orderB = null
set p = null
set r = null
set t = null
endfunction
function InitTrig_Unit_Event takes nothing returns nothing
endfunction
//TESH.scrollpos=87
//TESH.alwaysfold=0
//===========================================================================
// Damage Engine lets you detect, amplify, block or nullify damage. It even
// lets you detect if the damage was physical or from a spell. Just reference
// DamageEventAmount/Source/Target or the boolean IsDamageSpell, to get the
// necessary damage event data.
//
// - Detect damage: use the event "DamageEvent Equal to 1.00"
// - To change damage before it's dealt: use the event "DamageModifierEvent Equal to 1.00"
// - Detect damage after it was applied, use the event "AfterDamageEvent Equal to 1.00"
// - Detect spell damage: use the condition "IsDamageSpell Equal to True"
// - Detect zero-damage: use the event "DamageEvent Equal to 2.00" (an AfterDamageEvent will not fire for this)
//
// You can specify the DamageEventType before dealing triggered damage. To prevent an already-improbable error, I recommend running the trigger "ClearDamageEvent (Checking Conditions)" after dealing triggered damage from within a damage event:
// - Set NextDamageType = DamageTypeWhatever
// - Unit - Cause...
// - Trigger - Run ClearDamageEvent (Checking Conditions)
//
// You can modify the DamageEventAmount and the DamageEventType from a "DamageModifierEvent Equal to 1.00" trigger.
// - If the amount is modified to negative, it will count as a heal.
// - If the amount is set to 0, no damage will be dealt.
//
// If you need to reference the original in-game damage, use the variable "DamageEventPrevAmt".
//
//===========================================================================
// Programming note about "integer i" and "udg_DmgEvRecursionN": integer i
// ranges from -1 upwards. "udg_DmgEvRecursionN" ranges from 0 upwards.
// "integer i" is always 1 less than "udg_DmgEvRecursionN"
//
function DmgEvResetVars takes nothing returns nothing
local integer i = udg_DmgEvRecursionN - 2
set udg_DmgEvRecursionN = i + 1
if i >= 0 then
set udg_DamageEventPrevAmt = udg_LastDmgPrevAmount[i]
set udg_DamageEventAmount = udg_LastDmgValue[i]
set udg_DamageEventSource = udg_LastDmgSource[i]
set udg_DamageEventTarget = udg_LastDmgTarget[i]
set udg_IsDamageSpell = udg_LastDmgWasSpell[i]
set udg_DamageEventType = udg_LastDmgPrevType[i]
endif
endfunction
function CheckDamagedLifeEvent takes boolean clear returns nothing
if clear then
set udg_NextDamageOverride = false
set udg_NextDamageType = 0
endif
if udg_DmgEvTrig != null then
call DestroyTrigger(udg_DmgEvTrig)
set udg_DmgEvTrig = null
if udg_IsDamageSpell then
call SetWidgetLife(udg_DamageEventTarget, RMaxBJ(udg_LastDamageHP, 0.41))
if udg_LastDamageHP <= 0.405 then
if udg_DamageEventType < 0 then
call SetUnitExploded(udg_DamageEventTarget, true)
endif
//Kill the unit
call DisableTrigger(udg_DamageEventTrigger)
call UnitDamageTarget(udg_DamageEventSource, udg_DamageEventTarget, -999, false, false, null, DAMAGE_TYPE_UNIVERSAL, null)
call EnableTrigger(udg_DamageEventTrigger)
endif
elseif GetUnitAbilityLevel(udg_DamageEventTarget, udg_DamageBlockingAbility) > 0 then
call UnitRemoveAbility(udg_DamageEventTarget, udg_DamageBlockingAbility)
call SetWidgetLife(udg_DamageEventTarget, udg_LastDamageHP)
endif
if udg_DamageEventAmount != 0.00 and not udg_HideDamageFrom[GetUnitUserData(udg_DamageEventSource)] then
set udg_AfterDamageEvent = 0.00
set udg_AfterDamageEvent = 1.00
set udg_AfterDamageEvent = 0.00
endif
call DmgEvResetVars()
endif
endfunction
function DmgEvOnExpire takes nothing returns nothing
set udg_DmgEvStarted = false
call CheckDamagedLifeEvent(true)
endfunction
function PreCheckDamagedLifeEvent takes nothing returns boolean
call CheckDamagedLifeEvent(true)
return false
endfunction
function OnUnitDamage takes nothing returns boolean
local boolean override = udg_DamageEventOverride
local integer i = udg_DmgEvRecursionN - 1
local string s
local real prevAmount
local real life
local real prevLife
local unit u
call CheckDamagedLifeEvent(false) //in case the unit state event failed and the 0.00 second timer hasn't yet expired
if i >= 0 then
if i < 16 then
set udg_LastDmgPrevAmount[i]= udg_DamageEventPrevAmt
set udg_LastDmgValue[i] = udg_DamageEventAmount
set udg_LastDmgSource[i] = udg_DamageEventSource
set udg_LastDmgTarget[i] = udg_DamageEventTarget
set udg_LastDmgWasSpell[i] = udg_IsDamageSpell
set udg_LastDmgPrevType[i] = udg_DamageEventType
else
set s = "WARNING: Recursion error when dealing damage! Make sure when you deal damage from within a DamageEvent trigger, do it like this:\n\n"
set s = s + "Trigger - Turn off (This Trigger)\n"
set s = s + "Unit - Cause...\n"
set s = s + "Trigger - Turn on (This Trigger)"
//Delete the next couple of lines to disable the in-game recursion crash warnings
call ClearTextMessages()
call DisplayTimedTextToPlayer(GetLocalPlayer(), 0.00, 0.00, 999.00, s)
return false
endif
endif
set udg_DmgEvRecursionN = i + 2
set u = GetTriggerUnit()
set prevAmount = GetEventDamage()
set udg_DamageEventSource = GetEventDamageSource()
set udg_DamageEventAmount = prevAmount
set udg_DamageEventTarget = u
set udg_DamageEventType = udg_NextDamageType
set udg_NextDamageType = 0
set udg_DamageEventOverride = udg_NextDamageOverride
set udg_NextDamageOverride = false
if prevAmount == 0.00 then
if not udg_HideDamageFrom[GetUnitUserData(udg_DamageEventSource)] then
set udg_DamageEventPrevAmt = 0.00
set udg_DamageEvent = 0.00
set udg_DamageEvent = 2.00
set udg_DamageEvent = 0.00
endif
call DmgEvResetVars()
else
if not udg_DmgEvStarted then
set udg_DmgEvStarted = true
call TimerStart(udg_DmgEvTimer, 0.00, false, function DmgEvOnExpire)
endif
set udg_IsDamageSpell = prevAmount < 0.00
if udg_IsDamageSpell then
set prevAmount = -udg_DamageEventAmount
set life = 1.00
if IsUnitType(u, UNIT_TYPE_ETHEREAL) and not IsUnitType(u, UNIT_TYPE_HERO) then
set life = life*udg_DAMAGE_FACTOR_ETHEREAL //1.67
endif
if GetUnitAbilityLevel(u, 'Aegr') > 0 then
set life = life*udg_DAMAGE_FACTOR_ELUNES //0.80
endif
if udg_DmgEvBracers != 0 and IsUnitType(u, UNIT_TYPE_HERO) then
//Inline of UnitHasItemOfTypeBJ without the potential handle ID leak.
set i = 6
loop
set i = i - 1
if GetItemTypeId(UnitItemInSlot(u, i)) == udg_DmgEvBracers then
set life = life*udg_DAMAGE_FACTOR_BRACERS //0.67
exitwhen true
endif
exitwhen i == 0
endloop
endif
set udg_DamageEventAmount = prevAmount*life
endif
set udg_DamageEventPrevAmt = prevAmount
set udg_DamageModifierEvent = 0.00
if not udg_DamageEventOverride then
set udg_DamageModifierEvent = 1.00
if not udg_DamageEventOverride then
set udg_DamageModifierEvent = 2.00
set udg_DamageModifierEvent = 3.00
endif
endif
set udg_DamageEventOverride = override
if udg_DamageEventAmount > 0.00 then
set udg_DamageModifierEvent = 4.00
endif
set udg_DamageModifierEvent = 0.00
if not udg_HideDamageFrom[GetUnitUserData(udg_DamageEventSource)] then
set udg_DamageEvent = 0.00
set udg_DamageEvent = 1.00
set udg_DamageEvent = 0.00
endif
call CheckDamagedLifeEvent(true) //in case the unit state event failed from a recursive damage event
//All events have run and the damage amount is finalized.
set life = GetWidgetLife(u)
set udg_DmgEvTrig = CreateTrigger()
call TriggerAddCondition(udg_DmgEvTrig, Filter(function PreCheckDamagedLifeEvent))
if not udg_IsDamageSpell then
if udg_DamageEventAmount != prevAmount then
set life = life + prevAmount - udg_DamageEventAmount
if GetUnitState(u, UNIT_STATE_MAX_LIFE) < life then
set udg_LastDamageHP = life - prevAmount
call UnitAddAbility(u, udg_DamageBlockingAbility)
endif
call SetWidgetLife(u, RMaxBJ(life, 0.42))
endif
call TriggerRegisterUnitStateEvent(udg_DmgEvTrig, u, UNIT_STATE_LIFE, LESS_THAN, RMaxBJ(0.41, life - prevAmount/2.00))
else
set udg_LastDamageHP = GetUnitState(u, UNIT_STATE_MAX_LIFE)
set prevLife = life
if life + prevAmount*0.75 > udg_LastDamageHP then
set life = RMaxBJ(udg_LastDamageHP - prevAmount/2.00, 1.00)
call SetWidgetLife(u, life)
set life = (life + udg_LastDamageHP)/2.00
else
set life = life + prevAmount*0.50
endif
set udg_LastDamageHP = prevLife - (prevAmount - (prevAmount - udg_DamageEventAmount))
call TriggerRegisterUnitStateEvent(udg_DmgEvTrig, u, UNIT_STATE_LIFE, GREATER_THAN, life)
endif
set u = null
endif
return false
endfunction
function CreateDmgEvTrg takes nothing returns nothing
set udg_DamageEventTrigger = CreateTrigger()
call TriggerAddCondition(udg_DamageEventTrigger, Filter(function OnUnitDamage))
endfunction
function SetupDmgEv takes nothing returns boolean
local integer i = udg_UDex
local unit u
if udg_UnitIndexEvent == 1.00 then
set u = udg_UDexUnits[i]
if GetUnitAbilityLevel(u, 'Aloc') == 0 and TriggerEvaluate(gg_trg_Damage_Engine_Config) then
set udg_UnitDamageRegistered[i] = true
call TriggerRegisterUnitEvent(udg_DamageEventTrigger, u, EVENT_UNIT_DAMAGED)
call UnitAddAbility(u, udg_SpellDamageAbility)
call UnitMakeAbilityPermanent(u, true, udg_SpellDamageAbility)
endif
set u = null
else
set udg_HideDamageFrom[i] = false
if udg_UnitDamageRegistered[i] then
set udg_UnitDamageRegistered[i] = false
set udg_DamageEventsWasted = udg_DamageEventsWasted + 1
if udg_DamageEventsWasted == 32 then //After 32 registered units have been removed...
set udg_DamageEventsWasted = 0
//Rebuild the mass EVENT_UNIT_DAMAGED trigger:
call DestroyTrigger(udg_DamageEventTrigger)
call CreateDmgEvTrg()
set i = udg_UDexNext[0]
loop
exitwhen i == 0
if udg_UnitDamageRegistered[i] then
call TriggerRegisterUnitEvent(udg_DamageEventTrigger, udg_UDexUnits[i], EVENT_UNIT_DAMAGED)
endif
set i = udg_UDexNext[i]
endloop
endif
endif
endif
return false
endfunction
//===========================================================================
function InitTrig_Damage_Engine takes nothing returns nothing
local unit u = CreateUnit(Player(15), 'uloc', 0, 0, 0)
local integer i = 16
//Create this trigger with UnitIndexEvents in order add and remove units
//as they are created or removed.
local trigger t = CreateTrigger()
call TriggerRegisterVariableEvent(t, "udg_UnitIndexEvent", EQUAL, 1.00)
call TriggerRegisterVariableEvent(t, "udg_UnitIndexEvent", EQUAL, 2.00)
call TriggerAddCondition(t, Filter(function SetupDmgEv))
set t = null
//Run the configuration trigger to set all configurables:
if gg_trg_Damage_Engine_Config == null then
//It's possible this InitTrig_ function ran first, in which case use ExecuteFunc.
call ExecuteFunc("Trig_Damage_Engine_Config_Actions")
else
call TriggerExecute(gg_trg_Damage_Engine_Config)
endif
//Create trigger for storing all EVENT_UNIT_DAMAGED events.
call CreateDmgEvTrg()
//Create GUI-friendly trigger for cleaning up after UnitDamageTarget.
set udg_ClearDamageEvent = CreateTrigger()
call TriggerAddCondition(udg_ClearDamageEvent, Filter(function PreCheckDamagedLifeEvent))
//Disable SpellDamageAbility for every player.
loop
set i = i - 1
call SetPlayerAbilityAvailable(Player(i), udg_SpellDamageAbility, false)
exitwhen i == 0
endloop
//Preload abilities.
call UnitAddAbility(u, udg_DamageBlockingAbility)
call UnitAddAbility(u, udg_SpellDamageAbility)
call RemoveUnit(u)
set u = null
endfunction
//TESH.scrollpos=669
//TESH.alwaysfold=0
///********************************************************///
//
// *VENOM SPELL 1.7a
// -JC Helas
//
// *REQ.
// -Unit Event
// -Damage Engine
//
// *CREDITS
// -Bribe
//
// *FAQ
// -How to Import?
// 1. Goto File>Preferences>General> Mark "Automatically create unknown variable while pasting trigger data".
// 2. Copy all custom object that spell need into your map.
// 3. Copy Net Hook category into your map.
// 4. Then done, have fun.
//
//
// *CHANGELOG
// -1.1
// 1.Fixed Group Damaging
// -1.2
// 1.Minor Fix
// -1.3
// 1.Fixed Missile Movement
// 2.Fixed HaprDagger Cast Damage Group
// 3.Fixed Dummy Owner
// 4.Add Stocking Damage
// -1.4
// 1.Fixed Harp Blink Minor Fixed
// 2.Add Pick Enemy Flag of Harp Blink
// 3.Update the Required System
// -1.5
// 1.Documentd trigger
// 2.Fixed the missile size configuring
// 3.Fixed the damage detecting trigger
// 4.Add configure for loop periodic
// -1.6
// 1.Convert to Jass
// 2.Change name Harp to Venom because this spell
// seems not related to harp word.
// -a
// 1.Fixed Dagger Angle
// -1.7
// 1.Fixed Dagger
// 2.Fixed Damage Detect
// 3.Add New Spell "Venom Berserk"
// -1.7a
// 1.Switch loop function's event into variable timer.
// 2.Reduce local usage at cast functions.
// 3.Nullify some variable and local that has handle.
///***********************/********************************///
// //
// Dummy Caster Setup //
// //
///***********************/********************************///
//Determine which dummy id that will cast the slow and stun buff
constant function V_DummyCasterId takes nothing returns integer
return 'n000'
endfunction
//Ability Id of slow and stun
constant function V_BuffAbilityId takes integer t returns integer
local integer i
if t==1 then
set i='A006'//Slow Ability
elseif t==2 then
set i='A007'//Stun Ability
endif
return i
endfunction
//Buff Id of slow and stun
constant function V_BuffId takes integer t returns integer
local integer i
if t==1 then
set i='B000'//Slow Buff
elseif t==2 then
set i='BPSE'//Stun Buff
endif
return i
endfunction
//Order id of ability slow and stun
constant function V_OrderId takes integer t returns integer
local integer i
if t==1 then
set i=852096//Slow Order Id
elseif t==2 then
set i=852127//Stun Order Id
endif
return i
endfunction
//Owning player of dummy caster
constant function V_DummyCasterOwner takes nothing returns player
return Player(PLAYER_NEUTRAL_PASSIVE)
endfunction
//Periodic loop of buff
constant function V_LoopTimeOut takes nothing returns real
return 0.031250
endfunction
///********************************************************///
// //
// End Setup //
// //
///********************************************************///
function V_Move takes real x,real y,integer t returns nothing
call SetUnitX(udg_V_BuffCaster,x)
call SetUnitY(udg_V_BuffCaster,y)
call IssueImmediateOrderById(udg_V_BuffCaster,V_OrderId(t))
call SetUnitPosition(udg_V_BuffCaster,2147483647,2147483647)
endfunction
function V_DeI takes integer i returns integer
set udg_V_Unit[i]=null
set udg_V_Unit[i]=udg_V_Unit[udg_V_I]
set udg_V_Type[i]=udg_V_Type[udg_V_I]
set udg_V_I=udg_V_I-1
if udg_V_I==0 then
call PauseTimer(udg_V_Timer)
endif
return i-1
endfunction
function V_LoopBuff takes nothing returns nothing
local integer i=1
local integer id
loop
exitwhen i>udg_V_I
set id=GetUnitUserData(udg_V_Unit[i])
if udg_V_Type[i]==1 then
if udg_V_Dur1[id]>0.0 then
set udg_V_Dur1[id]=udg_V_Dur1[id]-V_LoopTimeOut()
else
call UnitRemoveAbility(udg_V_Unit[i],V_BuffId(udg_V_Type[i]))
set i=V_DeI(i)
endif
elseif udg_V_Type[i]==2 then
if udg_V_Dur2[id]>0.0 then
set udg_V_Dur2[id]=udg_V_Dur2[id]-V_LoopTimeOut()
else
call UnitRemoveAbility(udg_V_Unit[i],V_BuffId(udg_V_Type[i]))
set i=V_DeI(i)
endif
endif
set i=i+1
endloop
endfunction
function V_AddBuff takes unit u,real d,integer t returns nothing
local integer id=GetUnitUserData(u)
if t==1 then
if udg_V_Dur1[id]==0 then
set udg_V_I=udg_V_I+1
set udg_V_Unit[udg_V_I]=u
set udg_V_Type[udg_V_I]=t
set udg_V_Dur1[id]=d
call V_Move(GetUnitX(u),GetUnitY(u),t)
else
set udg_V_Dur1[id]=udg_V_Dur1[id]+d
endif
elseif t==2 then
if udg_V_Dur2[id]==0 then
set udg_V_I=udg_V_I+1
set udg_V_Unit[udg_V_I]=u
set udg_V_Type[udg_V_I]=t
set udg_V_Dur2[id]=d
call V_Move(GetUnitX(u),GetUnitY(u),t)
else
set udg_V_Dur2[id]=udg_V_Dur2[id]+d
endif
endif
if udg_V_I==1 then
call TimerStart(udg_V_Timer,V_LoopTimeOut(),true,function V_LoopBuff)
endif
endfunction
///********************************************************///
// //
// Venom Setup //
// //
///********************************************************///
//Ability id of Venom Dagger/Blink
constant function V_AbilityId takes integer t returns integer
local integer i
if t==1 then
set i='A000'//Venom Dagger
elseif t==2 then
set i='A008'//Venom Blink
elseif t==3 then
set i='A00A'//Venom Berserk
endif
return i
endfunction
//Owning player of all dummy missile
constant function V_DummyOwner takes nothing returns player
return Player(PLAYER_NEUTRAL_PASSIVE)
endfunction
//Id of dummy missile
constant function V_DummyId takes nothing returns integer
return 'o000'
endfunction
///********************************************************///
// //
// Venom Dagger Setup //
// //
///********************************************************///
//Determine what model for missile dagger
constant function VD_MissileModel takes nothing returns string
return "Abilities\\Weapons\\WardenMissile\\WardenMissile.mdl"
endfunction
//Determine where to attach the model of missile dagger
constant function VD_MissileAttach takes nothing returns string
return "origin"
endfunction
//Determine which effect will create upon hit of enemy qualifier
constant function VD_HitEffectModel takes nothing returns string
return "Abilities\\Spells\\Undead\\DeathCoil\\DeathCoilSpecialArt.mdl"
endfunction
//Determine where to attach the effect of affected
constant function VD_HitEffectAttach takes nothing returns string
return "origin"
endfunction
//Determine what model that stands as next attack has enchance
constant function VD_AttackEnhanceModel takes nothing returns string
return "Abilities\\Weapons\\AvengerMissile\\AvengerMissile.mdl"
endfunction
//Determine where to attach the enhance attack model
constant function VD_AttackEnhanceAttach takes nothing returns string
return "weapon"
endfunction
//Determine how duration of slow to end
constant function VD_SlowDuration takes nothing returns real
return 2.0
endfunction
///********************************************************///
// //
// Missile Setup //
// //
///********************************************************///
//Determine how many missile to execute of dagger ability
constant function VD_NumberOfMissile takes nothing returns integer
return 3
endfunction
//Determine how big will they spread
constant function VD_MissileSpreadAngle takes nothing returns real
return 45.0
endfunction
//Determine how speed travel of dagger each periodic
constant function VD_MissileSpeed takes nothing returns real
return 50.0
endfunction
//Determine how far does dagger travel
constant function VD_MissileTravel takes nothing returns real
return 700.0
endfunction
//Determine the AoE of dagger
constant function VD_MissileDamageRange takes nothing returns real
return 50.0
endfunction
//Determine if dagger will penetrate
constant function VD_Penetrate takes nothing returns boolean
return true
endfunction
///********************************************************///
// //
// Damage Setup //
// //
///********************************************************///
//Base damage of each dagger
constant function VD_DamageBase takes nothing returns real
return 40.0
endfunction
///Damage upgrade each ability lvl
constant function VD_DamageLv takes nothing returns real
return 10.0
endfunction
//Addtional damage by agi percentage given
constant function VD_AgiPercentDMG takes nothing returns real
return 1.80
endfunction
//After using skill,caster will stack enhance damage that will add damage to next attack
constant function VD_AgiPercentStockDMG takes nothing returns real
return 2.0
endfunction
//Attack Type of Dagger
constant function VD_AttackType takes nothing returns attacktype
return ATTACK_TYPE_NORMAL
endfunction
//Damage Type of Dagger
constant function VD_DamageType takes nothing returns damagetype
return DAMAGE_TYPE_NORMAL
endfunction
//Periodic of Dagger's Loop
constant function VD_LoopTimeOut takes nothing returns real
return 0.031250
endfunction
///********************************************************///
// //
// Dagger End Setup //
// //
///********************************************************///
// //
// Blink Setup //
// //
///********************************************************///
//Effect that created on caster position before leaving
constant function VB_EffectLeave takes nothing returns string
return "Abilities\\Spells\\Undead\\CarrionSwarm\\CarrionSwarmDamage.mdl"
endfunction
//Effect that created on caster postion after leaving
constant function VB_EffectFort takes nothing returns string
return "Abilities\\Spells\\Undead\\AnimateDead\\AnimateDeadTarget.mdl"
endfunction
//Model of homing missile
constant function VB_MissileModel takes nothing returns string
return "Abilities\\Spells\\Undead\\DeathCoil\\DeathCoilMissile.mdl"
endfunction
//Missile attach location to dummy
constant function VB_MissileModelAttach takes nothing returns string
return "origin"
endfunction
//Effect that created on target upon collision
constant function VB_CollideEffect takes nothing returns string
return "Abilities\\Spells\\Undead\\DeathCoil\\DeathCoilSpecialArt.mdl"
endfunction
//Collision effect attachment
constant function VB_CollideEffectAttach takes nothing returns string
return "origin"
endfunction
///********************************************************///
// //
// Travel Setup //
// //
///********************************************************///
//Determine the distance that caster travel
constant function VB_StepBackDistance takes nothing returns real
return 500.0
endfunction
//Determine the distance of searching target
constant function VB_DistanceTargetSearch takes nothing returns real
return 400.0
endfunction
//Determine the speed of dummy each periodic
constant function VB_MissileSpeed takes nothing returns real
return 15.0
endfunction
///********************************************************///
// //
// Damaging Setup //
// //
///********************************************************///
//Determine the base damage of missile
constant function VB_DamageBase takes nothing returns real
return 75.0
endfunction
//Determine the upgrade damage each level to missile damage
constant function VB_DamageLv takes nothing returns real
return 25.0
endfunction
//Determine the amount of stun damage, this damage will only occur when target has a buff of dagger
constant function VB_StunDamageBase takes nothing returns real
return 40.0
endfunction
//Determine the upgrade damage each level to stun damage
constant function VB_StunDamageLv takes nothing returns real
return 10.0
endfunction
//Determine the duration of stun
constant function VB_StunDuration takes nothing returns real
return .75
endfunction
//Determine the addtional damage by agi percent of caster
constant function VB_AgiPercentDamage takes nothing returns real
return 1.50//150%
endfunction
//Determine the attack type of missile
constant function VB_AttackType takes nothing returns attacktype
return ATTACK_TYPE_NORMAL
endfunction
//Determine the damage type of missile
constant function VB_DamageType takes nothing returns damagetype
return DAMAGE_TYPE_NORMAL
endfunction
//Determine the periodic of loop
constant function VB_LoopTimeOut takes nothing returns real
return 0.031250
endfunction
///********************************************************///
// //
// Blink End Setup //
// //
///********************************************************///
// //
// Berserk Setup //
// //
///********************************************************///
//The buff of Berserk
constant function VS_Buff takes nothing returns integer
return 'B001'
endfunction
//Amount of additional damage
constant function VS_DamagePercent takes nothing returns real
return 0.20//20%
endfunction
//Duration of slow
constant function VS_SlowDur takes nothing returns real
return 2.50
endfunction
//Slow base chance
constant function VS_SlowChanceBase takes nothing returns integer
return 40
endfunction
//Slow additional chance each level
constant function VS_SlowChanceLv takes nothing returns integer
return 10
endfunction
//Slow effect model
constant function VS_HitEffectModel takes nothing returns string
return "Abilities\\Spells\\Other\\Stampede\\StampedeMissileDeath.mdl"
endfunction
//Slow effect attach
constant function VS_HitEffectAttach takes nothing returns string
return "origin"
endfunction
//===========================================================================
constant function VD_Damage takes integer lv returns real
return VD_DamageBase()+(VD_DamageLv()*lv)
endfunction
constant function VD_Filter takes unit uc,unit ut returns boolean
return not IsUnitType(ut,UNIT_TYPE_DEAD) and not IsUnitType(ut,UNIT_TYPE_MAGIC_IMMUNE) and not IsUnitType(ut,UNIT_TYPE_STRUCTURE) and not IsUnitType(ut,UNIT_TYPE_MECHANICAL) and not IsUnitAlly(ut,GetOwningPlayer(uc))
endfunction
constant function VD_DDFilter takes nothing returns boolean
return udg_IsDamageSpell==false and udg_DamageEventType!=1 and udg_DamageEventAmount>0.00 and IsUnitInGroup(udg_DamageEventSource,udg_VD_StackDmgGroup)
endfunction
function VD_Move takes unit u,real x,real y,real s,real a returns nothing
call SetUnitX(u,x+s*Cos(a*bj_DEGTORAD))
call SetUnitY(u,y+s*Sin(a*bj_DEGTORAD))
endfunction
function VD_Dmg takes integer lv,unit u returns real
return VD_Damage(lv)+(GetHeroAgi(u,true)*VD_AgiPercentDMG())
endfunction
function VD_Ac takes integer dx returns real
return VD_MissileSpreadAngle()/I2R(dx)
endfunction
function VD_DmgDetect takes nothing returns nothing
local integer id=GetUnitUserData(udg_DamageEventSource)
if VD_DDFilter() then
set udg_DamageEventAmount=udg_DamageEventAmount+(GetHeroAgi(udg_DamageEventSource,true)*VD_AgiPercentStockDMG())
if GetUnitAbilityLevel(udg_DamageEventSource,VS_Buff())>0 then
set udg_DamageEventAmount=udg_DamageEventAmount+(udg_DamageEventAmount*VS_DamagePercent())
if VS_SlowChanceBase+(GetUnitAbilityLevel(udg_DamageEventSource,V_AbilityId(3))*VS_SlowChanceLv())>=GetRandomInt(1,100) then
call DestroyEffect(AddSpecialEffectTarget(VS_HitEffectModel(),udg_DamageEventTarget,VS_HitEffectAttach()))
call V_AddBuff(udg_DamageEventTarget,VS_SlowDur(),1)
endif
endif
set udg_VD_StackDmgCount[id]=udg_VD_StackDmgCount[id]-1
if udg_VD_StackDmgCount[id]==0 then
call GroupRemoveUnit(udg_VD_StackDmgGroup,udg_DamageEventSource)
call DestroyEffect(udg_VD_StackDmgEffect[id])
else
call DestroyEffect(AddSpecialEffectTarget(VD_AttackEnhanceModel(),udg_DamageEventSource,VD_AttackEnhanceAttach()))
endif
if FirstOfGroup(udg_VD_StackDmgGroup)==null then
call DisableTrigger(udg_VD_DmgDetectTrig)
endif
endif
endfunction
function VD_DeI takes integer i returns integer
set udg_VD_Caster[i]=null
set udg_VD_Dummy[i]=null
set udg_VD_Effect[i]=null
set udg_VD_DamageGroup[i]=null
set udg_VD_Caster[i]=udg_VD_Caster[udg_VD_I]
set udg_VD_Angle[i]=udg_VD_Angle[udg_VD_I]
set udg_VD_Dmg[i]=udg_VD_Dmg[udg_VD_I]
set udg_VD_Travel[i]=udg_VD_Travel[udg_VD_I]
set udg_VD_Dummy[i]=udg_VD_Dummy[udg_VD_I]
set udg_VD_Effect[i]=udg_VD_Effect[udg_VD_I]
set udg_VD_DamageGroup[i]=udg_VD_DamageGroup[udg_VD_I]
set udg_VD_I=udg_VD_I-1
if udg_VD_I==0 then
call PauseTimer(udg_VD_Timer)
endif
return i-1
endfunction
function VD_Loop takes nothing returns nothing
local integer i=1
local real x
local real y
local unit u
loop
exitwhen i>udg_VD_I
if udg_VD_Travel[i]>0 then
set x=GetUnitX(udg_VD_Dummy[i])
set y=GetUnitY(udg_VD_Dummy[i])
set udg_VD_Travel[i]=udg_VD_Travel[i]-VD_MissileSpeed()
call VD_Move(udg_VD_Dummy[i],x,y,VD_MissileSpeed(),udg_VD_Angle[i])
call GroupEnumUnitsInRange(udg_VD_Group,x,y,VD_MissileDamageRange(),null)
loop
set u=FirstOfGroup(udg_VD_Group)
exitwhen u==null
if VD_Filter(udg_VD_Caster[i],u) and not IsUnitInGroup(u,udg_VD_DamageGroup[i]) then
call GroupAddUnit(udg_VD_DamageGroup[i],u)
call V_AddBuff(u,VD_SlowDuration(),1)
call UnitDamageTarget(udg_VD_Caster[i],u,udg_VD_Dmg[i],false,false,VD_AttackType(),VD_DamageType(),null)
call DestroyEffect(AddSpecialEffectTarget(VD_HitEffectModel(),u,VD_HitEffectAttach()))
if not VD_Penetrate() then
set udg_VD_Travel[i]=0
endif
endif
call GroupRemoveUnit(udg_VD_Group,u)
endloop
else
call DestroyEffect(udg_VD_Effect[i])
call RemoveUnit(udg_VD_Dummy[i])
call DestroyGroup(udg_VD_DamageGroup[i])
set i=VD_DeI(i)
endif
set i=i+1
endloop
endfunction
function VD_Create takes nothing returns nothing
local unit u=GetTriggerUnit()
local real x1=GetUnitX(u)
local real y1=GetUnitY(u)
local real x2=GetSpellTargetX()
local real y2=GetSpellTargetY()
local integer lv=GetUnitAbilityLevel(u,V_AbilityId(1))
local integer dx=VD_NumberOfMissile()
local real af=(Atan2(y2-y1,x2-x1)*bj_RADTODEG)-(VD_MissileSpreadAngle()/2)-(VD_Ac(dx)/2)
loop
set af=af+VD_Ac(VD_NumberOfMissile())
set udg_VD_I=udg_VD_I+1
set udg_VD_Caster[udg_VD_I]=u
set udg_VD_Angle[udg_VD_I]=af
set udg_VD_Dmg[udg_VD_I]=VD_Dmg(lv,u)
set udg_VD_Travel[udg_VD_I]=VD_MissileTravel()
set udg_VD_Dummy[udg_VD_I]=CreateUnit(V_DummyOwner(),V_DummyId(),x1,y1,af)
set udg_VD_Effect[udg_VD_I]=AddSpecialEffectTarget(VD_MissileModel(),udg_VD_Dummy[udg_VD_I],VD_MissileAttach())
set udg_VD_DamageGroup[udg_VD_I]=CreateGroup()
if udg_VD_I==1 then
call TimerStart(udg_VD_Timer,V_LoopTimeOut(),true,function VD_Loop)
endif
set dx=dx-1
exitwhen dx==0
endloop
set lv=GetUnitUserData(u)
if udg_VD_StackDmgCount[lv]==0 then
set udg_VD_StackDmgEffect[lv]=AddSpecialEffectTarget(VD_AttackEnhanceModel(),u,VD_AttackEnhanceAttach())
endif
set udg_VD_StackDmgCount[lv]=udg_VD_StackDmgCount[lv]+1
if FirstOfGroup(udg_VD_StackDmgGroup)==null then
call EnableTrigger(udg_VD_DmgDetectTrig)
endif
call GroupAddUnit(udg_VD_StackDmgGroup,u)
set u=null
endfunction
//===========================================================================
constant function VB_Damage takes integer lv returns real
return VB_DamageBase()+(VB_DamageLv()*lv)
endfunction
constant function VB_StunDamage takes integer lv returns real
return VB_StunDamageBase()+(VB_StunDamageLv()*lv)
endfunction
constant function VB_Filter takes unit uc,unit ut returns boolean
return not IsUnitType(ut,UNIT_TYPE_DEAD) and not IsUnitType(ut,UNIT_TYPE_MAGIC_IMMUNE) and not IsUnitType(ut,UNIT_TYPE_STRUCTURE) and not IsUnitType(ut,UNIT_TYPE_MECHANICAL) and not IsUnitAlly(ut,GetOwningPlayer(uc))
endfunction
function VB_Dmg takes integer lv,unit u returns real
return VB_Damage(lv)+(GetHeroAgi(u,true)*VB_AgiPercentDamage())
endfunction
function VB_DeI takes integer i returns integer
set udg_VB_Caster[i]=null
set udg_VB_Target[i]=null
set udg_VB_Dummy[i]=null
set udg_VB_Dmg[i]=udg_VB_Dmg[udg_VB_I]
set udg_VB_SDmg[i]=udg_VB_SDmg[udg_VB_I]
set udg_VB_Caster[i]=udg_VB_Caster[udg_VB_I]
set udg_VB_Target[i]=udg_VB_Target[udg_VB_I]
set udg_VB_Dummy[i]=udg_VB_Dummy[udg_VB_I]
set udg_VB_MissileModel[i]=udg_VB_MissileModel[udg_VB_I]
set udg_VB_I=udg_VB_I-1
if udg_VB_I==0 then
call PauseTimer(udg_VB_Timer)
endif
return i-1
endfunction
function VB_Loop takes nothing returns nothing
local integer i=1
local real x1
local real y1
local real x2
local real y2
local real dx
local real dy
local real d
local real a
loop
exitwhen i>udg_VB_I
set x1=GetUnitX(udg_VB_Dummy[i])
set y1=GetUnitY(udg_VB_Dummy[i])
set x2=GetUnitX(udg_VB_Target[i])
set y2=GetUnitY(udg_VB_Target[i])
set dx=x2-x1
set dy=y2-y1
set d=SquareRoot(dx*dx+dy*dy)
if d>VB_MissileSpeed() and not IsUnitType(udg_VB_Target[i],UNIT_TYPE_DEAD) then
set a=Atan2(y2-y1,x2-x1)*bj_RADTODEG
call SetUnitX(udg_VB_Dummy[i],x1+VB_MissileSpeed()*Cos(a*bj_DEGTORAD))
call SetUnitY(udg_VB_Dummy[i],y1+VB_MissileSpeed()*Sin(a*bj_DEGTORAD))
call SetUnitFacing(udg_VB_Dummy[i],a)
else
if GetUnitAbilityLevel(udg_VB_Target[i],V_BuffId(1))>0 then
call V_AddBuff(udg_VB_Target[i],VB_StunDuration,2)
call UnitDamageTarget(udg_VB_Caster[i],udg_VB_Target[i],udg_VB_SDmg[i],false,false,VB_AttackType(),VB_DamageType(),null)
endif
call UnitDamageTarget(udg_VB_Caster[i],udg_VB_Target[i],udg_VB_Dmg[i],false,false,VB_AttackType(),VB_DamageType(),null)
call DestroyEffect(AddSpecialEffectTarget(VB_CollideEffect(),udg_VB_Target[i],VB_CollideEffectAttach()))
call DestroyEffect(udg_VB_MissileModel[i])
call RemoveUnit(udg_VB_Dummy[i])
set i=VB_DeI(i)
endif
set i=i+1
endloop
endfunction
function VB_Create takes nothing returns nothing
local unit u=GetTriggerUnit()
local unit t
local integer lv=GetUnitAbilityLevel(u,V_AbilityId(2))
local real a=GetUnitFacing(u)
local real x=GetUnitX(u)
local real y=GetUnitY(u)
call DestroyEffect(AddSpecialEffect(VB_EffectLeave(),x,y))
call SetUnitX(u,x-VB_StepBackDistance()*Cos(a*bj_DEGTORAD))
call SetUnitY(u,y-VB_StepBackDistance()*Sin(a*bj_DEGTORAD))
call GroupEnumUnitsInRange(udg_VB_GroupSearch,x,y,VB_DistanceTargetSearch(),null)
loop
set t=FirstOfGroup(udg_VB_GroupSearch)
exitwhen t==null
if VB_Filter(u,t) then
set udg_VB_I=udg_VB_I+1
set udg_VB_Dmg[udg_VB_I]=VB_Dmg(lv,u)
set udg_VB_SDmg[udg_VB_I]=VB_StunDamage(lv)
set udg_VB_Caster[udg_VB_I]=u
set udg_VB_Target[udg_VB_I]=t
set udg_VB_Dummy[udg_VB_I]=CreateUnit(V_DummyOwner(),V_DummyId(),x,y,0)
set udg_VB_MissileModel[udg_VB_I]=AddSpecialEffectTarget(VB_MissileModel(),udg_VB_Dummy[udg_VB_I],VB_MissileModelAttach())
if udg_VB_I==1 then
call TimerStart(udg_VB_Timer,V_LoopTimeOut(),true,function VB_Loop)
endif
endif
call GroupRemoveUnit(udg_VB_GroupSearch,t)
endloop
set x=x-VB_StepBackDistance()*Cos(a*bj_DEGTORAD)
set y=y-VB_StepBackDistance()*Sin(a*bj_DEGTORAD)
call DestroyEffect(AddSpecialEffect(VB_EffectFort(),x,y))
call SetUnitX(u,x)
call SetUnitY(u,y)
set u=null
endfunction
//===========================================================================
function Trig_Venom_Dagger_Actions takes nothing returns nothing
if GetSpellAbilityId()==V_AbilityId(1) then
call VD_Create()
elseif GetSpellAbilityId()==V_AbilityId(2) then
call VB_Create()
endif
endfunction
//===========================================================================
function InitTrig_VenomSpell takes nothing returns nothing
set gg_trg_VenomSpell=CreateTrigger()
set udg_VD_DmgDetectTrig = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(gg_trg_VenomSpell,EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerRegisterVariableEvent(udg_VD_DmgDetectTrig,"udg_DamageModifierEvent",EQUAL,1.00)
call TriggerAddAction(gg_trg_VenomSpell,function Trig_Venom_Dagger_Actions)
call TriggerAddAction(udg_VD_DmgDetectTrig,function VD_DmgDetect)
call DisableTrigger(udg_VD_DmgDetectTrig)
set udg_V_BuffCaster=CreateUnit(V_DummyCasterOwner(),V_DummyCasterId(),0,0,0)
call UnitAddAbility(udg_V_BuffCaster,V_BuffAbilityId(1))
call UnitAddAbility(udg_V_BuffCaster,V_BuffAbilityId(2))
call UnitAddAbility(udg_V_BuffCaster,'Aloc')
call SetUnitPosition(udg_V_BuffCaster,2147483647,2147483647)
endfunction
//TESH.scrollpos=1
//TESH.alwaysfold=0
function skip takes nothing returns nothing
local unit u1 = gg_unit_Ewar_0002
local unit u2 = gg_unit_Ewar_0003
call SetUnitState(u1,UNIT_STATE_MANA,GetUnitState(u1, UNIT_STATE_MAX_MANA)*RMaxBJ(0,100)*0.01)
call SetUnitState(u2,UNIT_STATE_MANA,GetUnitState(u2, UNIT_STATE_MAX_MANA)*RMaxBJ(0,100)*0.01)
call UnitResetCooldown(u1)
call UnitResetCooldown(u2)
call V_AddBuff(u1,1,2)
endfunction
function InitTrig_Spell_Test takes nothing returns nothing
local trigger resetcd = CreateTrigger()
call TriggerRegisterPlayerEvent(resetcd,Player(0),EVENT_PLAYER_END_CINEMATIC)
call TriggerAddAction(resetcd,function skip)
call DisplayTimedTextToPlayer(Player(0),0,0,120,"Press skip to reset cd and restore properties")
endfunction