// ********************************************************
// *
// * Infernal Collapse v1.4
// * by Quilnez
// *
// * Description:
// * Calls forth exploding magmatic shards all around the
// * target point. All enemy units around the explosion
// * site will receive fire damage.
// *
// * Requirement(s):
// * None
// *
// * How to import:
// * • Copy "Infernal Collapse" trigger group to your map
// * • Delete variable creator trigger
// * • Export all necessary import data to your map
// * (Except "TerrainArt\Outland\Outland_Dirt.blp")
// * • Copy dummy unit (Object Editor) to your map
// * • Copy main ability (Object Editor) to your map
// * • Configure the spell
// *
// * Credits:
// * • BTNEvaporate By M0rbid
// * • Explosion.mdx By JetFangInferno
// * • ExplosiveTornado.mdx By JetFangInferno
// * • FlameBomb.mdx By WILL THE ALMIGHTY
// * • Fire Low.mdx By Pyritie
// * • LightningSphere_FX.mdx By PeeKay
// * • Shockwave.mdx By Vestras
// * • dummy.mdx By Vexorian
// * (All models are edited to fulfill the
// * needs of this spell)
// *
// * Author's note:
// * If you need assistanance on installing this to your
// * map, or to request another form of this spell, just
// * contact me anytime
// *
// ********************************************************
// ********************************************************
// *
// * Configuration
// *
// * 1. Dummy unit's raw code at object editor
constant function ICol__DummyID takes nothing returns integer
return 'h000'
endfunction
// *
// * 2. Main ability's raw code at object editor
constant function ICol__SpellID takes nothing returns integer
return 'A000'
endfunction
// *
// * 3. Just leave it as it is
constant function ICol__Interval takes nothing returns real
return 0.0312500
endfunction
// *
// * 4. Time given to special effects to decay before being removed
constant function ICol__SFXDecayTime takes nothing returns real
return 5.0
endfunction
// *
// * 5. If true, spell will become channeling:
// * The spell will be stopped whenever the caster is given another
// * order
constant function ICol__Channeling takes nothing returns boolean
return false
endfunction
// *
// * 6. Order id of the main ability, only useful when the spell is
// * channeling
constant function ICol__OrderID takes nothing returns integer
return 852218 // carrionswarm
endfunction
// *
// * 7. Core of the orb's model path
constant function ICol__CoreSFX takes nothing returns string
return "war3mapImported\\Fire Low.mdx"
endfunction
// *
// * 8. (i) Orb's minimum size (scale)
constant function ICol__CoreMinSize takes nothing returns real
return 1.0
endfunction
// *
// * (ii) Orb's maximum size (scale)
constant function ICol__CoreMaxSize takes nothing returns real
return 2.0
endfunction
// * * Orbs will be spawned at random starting size (scale)
// *
// * 9. Size of the orb when it's ready to explode
// * The grow rate of the orb will be automatically calculated
// * based on interval and orb's lifespan (configurable at the
// * dynamic configuration part below)
constant function ICol__CoreTargetSize takes nothing returns real
return 0.15
endfunction
// *
// * 10. Swirl effect's model path, will be attached to the orb
constant function ICol__SwirlSFX takes nothing returns string
return "war3mapImported\\ExplosiveTornado.mdx"
endfunction
// *
// * 11. Glow effect's model path, will be attached to the orb
constant function ICol__GlowSFX takes nothing returns string
return "war3mapImported\\LightningSphere_FX.mdx"
endfunction
// *
// * 12. Explosion effect's model path, will be used on explode event
constant function ICol__ExplosionSFX takes nothing returns string
return "war3mapImported\\FlameBomb.mdx"
endfunction
// *
// * 13. Wave effect's model path, will be used on explode event
constant function ICol__WaveSFX takes nothing returns string
return "war3mapImported\\Shockwave.mdx"
endfunction
// *
// * 14. Wave effect's model path, will be used on explode event
constant function ICol__SphereSFX takes nothing returns string
return "war3mapImported\\Explosion.mdx"
endfunction
// *
// * 15. Lifespan of the orb before exploded, may affects grow rate
constant function ICol__CoreLifespan takes integer level returns real
return 0.75
endfunction
// *
// * 16. (i) Orb's minimum distance from cast point
constant function ICol__MinDistance takes integer level returns real
return 150.0
endfunction
// *
// * (ii) Orb's maximum distance from cast point
constant function ICol__MaxDistance takes integer level returns real
return 300.0 + 150.0*level
endfunction
// * * Orbs will be spawned at random location around the cast point
// *
// * 17. (i) Orb's minimum fly height
constant function ICol__MinHeight takes integer level returns real
return 150.0
endfunction
// *
// * (ii) Orb's maximum fly height
constant function ICol__MaxHeight takes integer level returns real
return 300.0
endfunction
// * * Orbs will be spawned at random height
// *
// * 18. (i) Minimum delay before spawning another orb
constant function ICol__MinDelay takes integer level returns real
return 0.0
endfunction
// *
// * (ii) Maximum delay before spawning another orb
constant function ICol__MaxDelay takes integer level returns real
return 0.15
endfunction
// * * Orbs have random spawn rate
// *
// * 19. Maximum duration of the spell
// * Use 0 or lower to remove duration limit
constant function ICol__Duration takes integer level returns real
return 0.8*level
endfunction
// *
// * 20. Maximum count of spawned orbs per cast
// * Use 0 or lower to remove spawn limit
constant function ICol__Count takes integer level returns integer
return 0
endfunction
// *
// * 21. Maximum distance from target to the orb to take damage
constant function ICol__AoE takes integer level returns real
return 300.0
endfunction
// *
// * 22. If true, the AoE will become spherical
constant function ICol__3DAoE takes nothing returns boolean
return true
endfunction
// *
// * 23. Damage dealt to targets within explosion AoE
constant function ICol__Damage takes integer level returns real
return 70.0*level
endfunction
// *
// * 24. Attack type of dealt damage
constant function ICol__AttackType takes nothing returns attacktype
return ATTACK_TYPE_NORMAL
endfunction
// *
// * 25. Damage type of dealt damage
constant function ICol__DamageType takes nothing returns damagetype
return DAMAGE_TYPE_FIRE
endfunction
// *
// * 26. Weapon type of dealt damage
constant function ICol__WeaponType takes nothing returns weapontype
return WEAPON_TYPE_WHOKNOWS
endfunction
// *
// * 27. This part allows you to change spell's casting type, is it
// * point target or no target. For example if you want to change
// * it to no target (instant), you can modify this to
// * "return GetUnitX(caster)"
function ICol__GetCastTargetX takes unit caster returns real
return GetSpellTargetX()
endfunction
// *
// * 28. Same as above. For example if you want to change it to no
// * target (instant), you can modify this to
// * "return GetUnitY(caster)"
function ICol__GetCastTargetY takes unit caster returns real
return GetSpellTargetY()
endfunction
// * * Targeting unit cast type is not recommended
// *
// * 29. No need to touch this, used to check is unit alive or not
function ICol__isAlive takes unit id returns boolean
return GetWidgetLife(id) > 0.405 and not IsUnitType(id, UNIT_TYPE_DEAD)
endfunction
// *
// * 30. Classification of unit which can become a victim of the spell
function ICol__Targets takes unit target, player caster returns boolean
return ICol__isAlive(target) and IsUnitEnemy(target, caster) and not(IsUnitType(target, UNIT_TYPE_STRUCTURE) or IsUnitType(target, UNIT_TYPE_MAGIC_IMMUNE))
endfunction
// *
// * 31. This function will be called whenever a unit is damaged by this spell
function ICol__OnDamage takes unit target, unit caster, integer level returns nothing
call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Items\\AIfb\\AIfbSpecialArt.mdl", target, "chest"))
// call BJDebugMsg(GetUnitName(target) + " took " + R2SW(ICol__Damage(level), 4, 1) + " damage from " + GetUnitName(caster) + ".")
endfunction
// *
// * 32. This function will be called whenever an orb is exploded
function ICol__OnExplode takes unit caster, integer level, real x, real y, real z returns nothing
// call BJDebugMsg("Alert! An orb (level " + I2S(level) + " from " + GetUnitName(caster) + " has been exploded at [x: " + R2SW(x, 4, 1) + ", y: " + R2SW(y, 4, 1) + ", z: " + R2SW(z, 4, 1) + "]")
endfunction
// *
// * 33. This function will be called whenever an orb is spawned
function ICol__OnSpawn takes unit caster, integer level, real x, real y, real z returns nothing
// call BJDebugMsg("Alert! An orb (level " + I2S(level) + " from " + GetUnitName(caster) + " has been spawned at [x: " + R2SW(x, 4, 1) + ", y: " + R2SW(y, 4, 1) + ", z: " + R2SW(z, 4, 1) + "]")
endfunction
// *
// * End of Configuration
// *
// ********************************************************
function ICol__getZ takes real x, real y returns real
call MoveLocation(udg_ICol__TempLoc, x, y)
return GetLocationZ(udg_ICol__TempLoc)
endfunction
function ICol__setZ takes unit u, real z returns nothing
call SetUnitFlyHeight(u, z - ICol__getZ(GetUnitX(u), GetUnitY(u)), 0)
endfunction
// Orb periodic callback
function ICol__orb__periodic takes nothing returns nothing
local integer i = 1
local boolean b
local unit u
local real d
local real x
local real y
local real z
loop
exitwhen i > udg_ICol__Orb__Count
// If still need to grow
if udg_ICol__Orb__Scale[i] > ICol__CoreTargetSize() then
set udg_ICol__Orb__Scale[i] = udg_ICol__Orb__Scale[i] - udg_ICol__Orb__ScaleRate[i]
call SetUnitScale(udg_ICol__Orb__Dummy[i], udg_ICol__Orb__Scale[i], 1, 1)
else
set udg_ICol__OCount[udg_ICol__Orb__Source[i]] = udg_ICol__OCount[udg_ICol__Orb__Source[i]] - 1
call UnitApplyTimedLife(udg_ICol__Orb__Dummy[i], 'BTLF', ICol__SFXDecayTime())
call DestroyEffect(udg_ICol__Orb__CoreFx[i])
call DestroyEffect(udg_ICol__Orb__GlowFx[i])
call DestroyEffect(udg_ICol__Orb__SwirlFx[i])
// If the caster is still alive then allow orb to explode
if ICol__isAlive(udg_ICol__Caster[udg_ICol__Orb__Source[i]]) then
call ICol__OnExplode(udg_ICol__Caster[udg_ICol__Orb__Source[i]], udg_ICol__Level[udg_ICol__Orb__Source[i]], udg_ICol__Orb__X[i], udg_ICol__Orb__Y[i], udg_ICol__Orb__Z[i])
// We need dummy to adjust explosion effects' height
set u = CreateUnit(udg_ICol__Owner[udg_ICol__Orb__Source[i]], ICol__DummyID(), udg_ICol__Orb__X[i], udg_ICol__Orb__Y[i], 0)
if UnitAddAbility(u, 'Amrf') and UnitRemoveAbility(u, 'Amrf') then
endif
call ICol__setZ(u, udg_ICol__Orb__Z[i])
call DestroyEffect(AddSpecialEffectTarget(ICol__ExplosionSFX(), u, "origin"))
call DestroyEffect(AddSpecialEffectTarget(ICol__WaveSFX(), u, "origin"))
call DestroyEffect(AddSpecialEffectTarget(ICol__SphereSFX(), u, "origin"))
call UnitApplyTimedLife(u, 'BTLF', ICol__SFXDecayTime())
call GroupEnumUnitsInRange(udg_ICol__TempGroup, udg_ICol__Orb__X[i], udg_ICol__Orb__Y[i], udg_ICol__AoE[udg_ICol__Orb__Source[i]], null)
loop
set u = FirstOfGroup(udg_ICol__TempGroup)
exitwhen u == null
call GroupRemoveUnit(udg_ICol__TempGroup, u)
if ICol__Targets(u, udg_ICol__Owner[udg_ICol__Orb__Source[i]]) then
set b = true
if ICol__3DAoE() then
// Spherical collision (AoE)
set x = GetUnitX(u)
set y = GetUnitY(u)
set z = udg_ICol__Orb__Z[i]-(ICol__getZ(x, y)+GetUnitFlyHeight(u))
set d = SquareRoot((udg_ICol__Orb__X[i] - x)*(udg_ICol__Orb__X[i] - x) + (udg_ICol__Orb__Y[i] - y)*(udg_ICol__Orb__Y[i] - y))
set b = (d*d)+(z*z) < udg_ICol__AoE[udg_ICol__Orb__Source[i]]*udg_ICol__AoE[udg_ICol__Orb__Source[i]]
endif
if b then
call UnitDamageTarget(udg_ICol__Caster[udg_ICol__Orb__Source[i]], u, udg_ICol__Damage[udg_ICol__Orb__Source[i]], false, false, ICol__AttackType(), ICol__DamageType(), ICol__WeaponType())
call ICol__OnDamage(u, udg_ICol__Caster[udg_ICol__Orb__Source[i]], udg_ICol__Level[udg_ICol__Orb__Source[i]])
endif
endif
endloop
endif
if i != udg_ICol__Orb__Count then
// Deindexing
set udg_ICol__Orb__Dummy[i] = udg_ICol__Orb__Dummy[udg_ICol__Orb__Count]
set udg_ICol__Orb__CoreFx[i] = udg_ICol__Orb__CoreFx[udg_ICol__Orb__Count]
set udg_ICol__Orb__SwirlFx[i] = udg_ICol__Orb__SwirlFx[udg_ICol__Orb__Count]
set udg_ICol__Orb__GlowFx[i] = udg_ICol__Orb__GlowFx[udg_ICol__Orb__Count]
set udg_ICol__Orb__Scale[i] = udg_ICol__Orb__Scale[udg_ICol__Orb__Count]
set udg_ICol__Orb__ScaleRate[i] = udg_ICol__Orb__ScaleRate[udg_ICol__Orb__Count]
set udg_ICol__Orb__Source[i] = udg_ICol__Orb__Source[udg_ICol__Orb__Count]
set udg_ICol__Orb__X[i] = udg_ICol__Orb__X[udg_ICol__Orb__Count]
set udg_ICol__Orb__Y[i] = udg_ICol__Orb__Y[udg_ICol__Orb__Count]
set udg_ICol__Orb__Z[i] = udg_ICol__Orb__Z[udg_ICol__Orb__Count]
endif
// Remove leaks
set udg_ICol__Orb__Dummy[udg_ICol__Orb__Count] = null
set udg_ICol__Orb__CoreFx[udg_ICol__Orb__Count] = null
set udg_ICol__Orb__SwirlFx[udg_ICol__Orb__Count] = null
set udg_ICol__Orb__GlowFx[udg_ICol__Orb__Count] = null
set udg_ICol__Orb__Count = udg_ICol__Orb__Count - 1
if udg_ICol__Orb__Count < 1 then
call PauseTimer(udg_ICol__Orb__Timer)
else
set i = i - 1
endif
endif
set i = i + 1
endloop
endfunction
// To create an orb at given coordinates
function ICol__orb__create takes integer source, real x, real y, real z returns nothing
set udg_ICol__Orb__Count = udg_ICol__Orb__Count + 1
set udg_ICol__Orb__Source[udg_ICol__Orb__Count] = source
set udg_ICol__Orb__Dummy[udg_ICol__Orb__Count] = CreateUnit(udg_ICol__Owner[source], ICol__DummyID(), x, y, 0)
set udg_ICol__Orb__CoreFx[udg_ICol__Orb__Count] = AddSpecialEffectTarget(ICol__CoreSFX(), udg_ICol__Orb__Dummy[udg_ICol__Orb__Count], "origin")
set udg_ICol__Orb__SwirlFx[udg_ICol__Orb__Count] = AddSpecialEffectTarget(ICol__SwirlSFX(), udg_ICol__Orb__Dummy[udg_ICol__Orb__Count], "origin")
set udg_ICol__Orb__GlowFx[udg_ICol__Orb__Count] = AddSpecialEffectTarget(ICol__GlowSFX(), udg_ICol__Orb__Dummy[udg_ICol__Orb__Count], "origin")
set udg_ICol__Orb__Scale[udg_ICol__Orb__Count] = GetRandomReal(ICol__CoreMinSize(), ICol__CoreMaxSize())
set udg_ICol__Orb__ScaleRate[udg_ICol__Orb__Count] = (udg_ICol__Orb__Scale[udg_ICol__Orb__Count]-ICol__CoreTargetSize())/(udg_ICol__Lifespan[source]/ICol__Interval())
// Update orb's coordinate in case it's created at different loc (exceed map boundaries/pathing issue)
set udg_ICol__Orb__X[udg_ICol__Orb__Count] = GetUnitX(udg_ICol__Orb__Dummy[udg_ICol__Orb__Count])
set udg_ICol__Orb__Y[udg_ICol__Orb__Count] = GetUnitY(udg_ICol__Orb__Dummy[udg_ICol__Orb__Count])
set udg_ICol__Orb__Z[udg_ICol__Orb__Count] = z+ICol__getZ(udg_ICol__Orb__X[udg_ICol__Orb__Count], udg_ICol__Orb__Y[udg_ICol__Orb__Count])
if UnitAddAbility(udg_ICol__Orb__Dummy[udg_ICol__Orb__Count], 'Amrf') and UnitRemoveAbility(udg_ICol__Orb__Dummy[udg_ICol__Orb__Count], 'Amrf') then
endif
call SetUnitFlyHeight(udg_ICol__Orb__Dummy[udg_ICol__Orb__Count], z, 0)
call SetUnitScale(udg_ICol__Orb__Dummy[udg_ICol__Orb__Count], udg_ICol__Orb__Scale[udg_ICol__Orb__Count], 1, 1)
call ICol__OnSpawn(udg_ICol__Caster[source], udg_ICol__Level[source], x, y, z)
if udg_ICol__Orb__Count == 1 then
call TimerStart(udg_ICol__Orb__Timer, ICol__Interval(), true, function ICol__orb__periodic)
endif
endfunction
// Main spell's periodic callback
function ICol__periodic takes nothing returns nothing
local integer h
local integer i = 1
local integer j
local real d
local real a
loop
exitwhen i > udg_ICol__Count
if not udg_ICol__Dispose[i] then
if udg_ICol__Duration[i] > 0 then
set udg_ICol__Duration[i] = udg_ICol__Duration[i] - ICol__Interval()
set udg_ICol__Dispose[i] = udg_ICol__Duration[i] <= 0
endif
// If current order still matches
if not udg_ICol__Dispose[i] then
set udg_ICol__Dispose[i] = not ICol__isAlive(udg_ICol__Caster[i]) or ICol__Channeling() and GetUnitCurrentOrder(udg_ICol__Caster[i]) != ICol__OrderID()
endif
if not udg_ICol__Dispose[i] then
if udg_ICol__Delay[i] > ICol__Interval() then
set udg_ICol__Delay[i] = udg_ICol__Delay[i] - ICol__Interval()
else
// If still able to spawn more orbs
if udg_ICol__SpawnCount[i] > 0 then
set udg_ICol__SpawnCount[i] = udg_ICol__SpawnCount[i] - 1
set udg_ICol__Dispose[i] = udg_ICol__SpawnCount[i] == 0
endif
set udg_ICol__Delay[i] = GetRandomReal(udg_ICol__DelayMin[i], udg_ICol__DelayMax[i])
// Create new orb at random coordinate around the cast point
set d = GetRandomReal(udg_ICol__DistanceMin[i], udg_ICol__DistanceMax[i])
set a = GetRandomReal(-bj_PI, bj_PI)
set udg_ICol__OCount[i] = udg_ICol__OCount[i] + 1
call ICol__orb__create(i, udg_ICol__X[i]+d*Cos(a), udg_ICol__Y[i]+d*Sin(a), GetRandomReal(udg_ICol__HeightMin[i], udg_ICol__HeightMax[i]))
endif
endif
endif
// If the spell is ended
if udg_ICol__Dispose[i] then
if udg_ICol__OCount[i] <= 0 then
set h = GetHandleId(udg_ICol__Caster[i])
if HaveSavedInteger(udg_ICol__Hashtable, h, 0) then
if ICol__Channeling() then
if LoadInteger(udg_ICol__Hashtable, h, 0) == i then
call RemoveSavedInteger(udg_ICol__Hashtable, h, 0)
endif
endif
endif
if i != udg_ICol__Count then
// Index correction
if ICol__Channeling() then
call SaveInteger(udg_ICol__Hashtable, GetHandleId(udg_ICol__Caster[udg_ICol__Count]), 0, i)
endif
// Deindexing
set udg_ICol__Caster[i] = udg_ICol__Caster[udg_ICol__Count]
set udg_ICol__Owner[i] = udg_ICol__Owner[udg_ICol__Count]
set udg_ICol__X[i] = udg_ICol__X[udg_ICol__Count]
set udg_ICol__Y[i] = udg_ICol__Y[udg_ICol__Count]
set udg_ICol__Level[i] = udg_ICol__Level[udg_ICol__Count]
set udg_ICol__Damage[i] = udg_ICol__Damage[udg_ICol__Count]
set udg_ICol__Dispose[i] = udg_ICol__Dispose[udg_ICol__Count]
set udg_ICol__OCount[i] = udg_ICol__OCount[udg_ICol__Count]
set udg_ICol__AoE[i] = udg_ICol__AoE[udg_ICol__Count]
set udg_ICol__Lifespan[i] = udg_ICol__Lifespan[udg_ICol__Count]
set udg_ICol__SpawnCount[i] = udg_ICol__SpawnCount[udg_ICol__Count]
set udg_ICol__Duration[i] = udg_ICol__Duration[udg_ICol__Count]
set udg_ICol__DistanceMin[i] = udg_ICol__DistanceMin[udg_ICol__Count]
set udg_ICol__DistanceMax[i] = udg_ICol__DistanceMax[udg_ICol__Count]
set udg_ICol__HeightMin[i] = udg_ICol__HeightMin[udg_ICol__Count]
set udg_ICol__HeightMax[i] = udg_ICol__HeightMax[udg_ICol__Count]
set udg_ICol__DelayMin[i] = udg_ICol__DelayMin[udg_ICol__Count]
set udg_ICol__DelayMax[i] = udg_ICol__DelayMax[udg_ICol__Count]
set udg_ICol__Delay[i] = udg_ICol__Delay[udg_ICol__Count]
// Source index corrections
set j = 1
loop
exitwhen j > udg_ICol__Orb__Count
if udg_ICol__Orb__Source[j] == udg_ICol__Count then
set udg_ICol__Orb__Source[j] = i
endif
set j = j + 1
endloop
endif
// Remove leak
set udg_ICol__Caster[udg_ICol__Count] = null
set udg_ICol__Count = udg_ICol__Count - 1
if udg_ICol__Count < 1 then
call PauseTimer(udg_ICol__Timer)
else
set i = i - 1
endif
endif
endif
set i = i + 1
endloop
endfunction
// On cast event
function ICol__onCast takes nothing returns boolean
local integer h
if GetSpellAbilityId() == ICol__SpellID() then
set udg_ICol__Count = udg_ICol__Count + 1
set udg_ICol__Caster[udg_ICol__Count] = GetTriggerUnit()
set udg_ICol__Owner[udg_ICol__Count] = GetTriggerPlayer()
set udg_ICol__Dispose[udg_ICol__Count] = false
set udg_ICol__OCount[udg_ICol__Count] = 0
// Get cast point coordinate (customizable by user)
set udg_ICol__X[udg_ICol__Count] = ICol__GetCastTargetX(udg_ICol__Caster[udg_ICol__Count])
set udg_ICol__Y[udg_ICol__Count] = ICol__GetCastTargetY(udg_ICol__Caster[udg_ICol__Count])
set udg_ICol__Level[udg_ICol__Count] = GetUnitAbilityLevel(udg_ICol__Caster[udg_ICol__Count], ICol__SpellID())
set udg_ICol__Damage[udg_ICol__Count] = ICol__Damage(udg_ICol__Level[udg_ICol__Count])
set udg_ICol__AoE[udg_ICol__Count] = ICol__AoE(udg_ICol__Level[udg_ICol__Count])
set udg_ICol__Lifespan[udg_ICol__Count] = ICol__CoreLifespan(udg_ICol__Level[udg_ICol__Count])
set udg_ICol__SpawnCount[udg_ICol__Count] = ICol__Count(udg_ICol__Level[udg_ICol__Count])
set udg_ICol__Duration[udg_ICol__Count] = ICol__Duration(udg_ICol__Level[udg_ICol__Count])
set udg_ICol__DistanceMin[udg_ICol__Count] = ICol__MinDistance(udg_ICol__Level[udg_ICol__Count])
set udg_ICol__DistanceMax[udg_ICol__Count] = ICol__MaxDistance(udg_ICol__Level[udg_ICol__Count])
set udg_ICol__HeightMin[udg_ICol__Count] = ICol__MinHeight(udg_ICol__Level[udg_ICol__Count])
set udg_ICol__HeightMax[udg_ICol__Count] = ICol__MaxHeight(udg_ICol__Level[udg_ICol__Count])
set udg_ICol__DelayMin[udg_ICol__Count] = ICol__MinDelay(udg_ICol__Level[udg_ICol__Count])
set udg_ICol__DelayMax[udg_ICol__Count] = ICol__MaxDelay(udg_ICol__Level[udg_ICol__Count])
set udg_ICol__Delay[udg_ICol__Count] = GetRandomReal(udg_ICol__DelayMin[udg_ICol__Count], udg_ICol__DelayMax[udg_ICol__Count])
if udg_ICol__Count == 1 then
call TimerStart(udg_ICol__Timer, ICol__Interval(), true, function ICol__periodic)
endif
// Use hashtable to avoid casting collision (if channeling)
if ICol__Channeling() then
set h = GetHandleId(udg_ICol__Caster[udg_ICol__Count])
if HaveSavedInteger(udg_ICol__Hashtable, h, 0) then
set udg_ICol__Dispose[LoadInteger(udg_ICol__Hashtable, h, 0)] = true
endif
call SaveInteger(udg_ICol__Hashtable, h, 0, udg_ICol__Count)
endif
endif
return false
endfunction
// Initialization
function InitTrig_Infernal_Collapse takes nothing returns nothing
if ICol__Channeling() then
set udg_ICol__Hashtable = InitHashtable()
endif
set udg_ICol__Timer = CreateTimer()
set udg_ICol__Orb__Timer = CreateTimer()
set udg_ICol__TempGroup = CreateGroup()
set udg_ICol__TempLoc = Location(0, 0)
set gg_trg_Infernal_Collapse = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(gg_trg_Infernal_Collapse, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(gg_trg_Infernal_Collapse, Condition(function ICol__onCast))
endfunction