// CONFIGURATION
// Constants
// Main spell raw code
constant function FF_GetSpellID takes nothing returns integer
return 'A004'
endfunction
// Field Effect
constant function FF_FieldFx takes nothing returns string
return "war3mapimported\\FreezingField.mdx"
endfunction
// Explosion Effect
constant function FF_ExpFx takes nothing returns string
return "war3mapimported\\SnowyBlizzardTarget.mdx"
endfunction
// Explosion Effect delay
constant function FF_ExpDelay takes nothing returns real
return 0.8
endfunction
// Explosion Interval
constant function FF_Interval takes nothing returns real
return 0.05
endfunction
// Booleans
function FF_FilterUnit takes player casterowner, unit u returns boolean
return IsUnitEnemy(u, casterowner) and not IsUnitType (u, UNIT_TYPE_DEAD) and GetUnitAbilityLevel(u, 'Avul') == 0 and not IsUnitType (u, UNIT_TYPE_MAGIC_IMMUNE)
endfunction
// Get spell level
function FF_SpellLvl takes unit caster returns integer
return GetUnitAbilityLevel (caster, FF_GetSpellID()) // Get the spell level of the caster
endfunction
// Level dependable values
function FF_Duration takes integer level returns real
return 5.
endfunction
function FF_ExpDmg takes integer level returns real
return 100. + level*20.
endfunction
function FF_ExpAoE takes integer level returns real
return 100. + level*20.
endfunction
function FF_FieldAoe takes integer level returns real
return 400. + level*50.
endfunction
// Attack - Damage - Weapon type
function FF_AttackType takes nothing returns attacktype
return ATTACK_TYPE_NORMAL
endfunction
function FF_DamageType takes nothing returns damagetype
return DAMAGE_TYPE_MAGIC
endfunction
function FF_WeaponType takes nothing returns weapontype
return WEAPON_TYPE_WHOKNOWS
endfunction
// END CONFIGURATION
// SPELL FUNCTIONS
// This is the main function of the spell
function FF_TimerLoop takes nothing returns nothing
local integer ID
local integer ID2
local integer listmax = LoadInteger(udg_FF_Hashtable, -1, 0 )
local unit caster
local integer i = 0
local unit u
local real x
local real y
local real x1
local real y1
local integer level
local real t
local integer j
local integer modifier
local real r
// Now we start looping through all the spell instances
loop
exitwhen i >= listmax
// First we load the saved values of a spell instance
set i = i + 1
set ID = LoadInteger(udg_FF_Hashtable, -1, i)
set caster = LoadUnitHandle(udg_FF_Hashtable, ID, 1)
set x = LoadReal(udg_FF_Hashtable, ID, 2)
set y = LoadReal(udg_FF_Hashtable, ID, 3)
set level = FF_SpellLvl(caster)
set t = LoadReal(udg_FF_Hashtable, ID, 5)
set j = LoadInteger(udg_FF_Hashtable, ID, 6)
if t >= FF_Duration(level) then
call DestroyEffect(LoadEffectHandle(udg_FF_Hashtable, ID, 4))
if listmax != i then
call SaveInteger(udg_FF_Hashtable, LoadInteger(udg_FF_Hashtable, -1, listmax), 0, i)
call SaveInteger(udg_FF_Hashtable, -1, i, LoadInteger(udg_FF_Hashtable, -1, listmax))
call RemoveSavedInteger(udg_FF_Hashtable, -1, listmax)
set i = i - 1
endif
set listmax = listmax - 1
call SaveInteger(udg_FF_Hashtable, -1, 0, listmax)
if LoadInteger(udg_FF_Hashtable, 0, 0) + 1 == LoadInteger(udg_FF_Hashtable, 0, -1) then
call FlushChildHashtable(udg_FF_Hashtable, 0)
call PauseTimer(LoadTimerHandle(udg_FF_Hashtable, -2, 0))
else
call SaveInteger (udg_FF_Hashtable, 0, 0, LoadInteger(udg_FF_Hashtable, 0, 0) + 1)
call SaveInteger(udg_FF_Hashtable, 0, LoadInteger(udg_FF_Hashtable, 0, 0), ID)
endif
call FlushChildHashtable(udg_FF_Hashtable, ID)
else
if LoadBoolean(udg_FF_Hashtable, ID, 7) then
set r = LoadReal(udg_FF_Hashtable, ID, 10)
if r >= FF_ExpDelay() then
call GroupEnumUnitsInRange(udg_FF_Group, LoadReal(udg_FF_Hashtable, ID, 8), LoadReal(udg_FF_Hashtable, ID, 9), FF_ExpAoE(level), null)
loop
set u = FirstOfGroup(udg_FF_Group)
exitwhen u == null
if FF_FilterUnit (GetOwningPlayer(caster), u) and IsUnitVisible(u, GetOwningPlayer(caster)) then
call UnitDamageTarget(caster, u, FF_ExpDmg(level), false, false, FF_AttackType(), FF_DamageType(), FF_WeaponType())
endif
call GroupRemoveUnit(udg_FF_Group, u)
endloop
if listmax != i then
call SaveInteger (udg_FF_Hashtable, LoadInteger (udg_FF_Hashtable, -1, listmax), 0, i)
call SaveInteger (udg_FF_Hashtable, -1, i, LoadInteger (udg_FF_Hashtable,-1, listmax))
call RemoveSavedInteger (udg_FF_Hashtable, -1, listmax)
set i = i - 1
endif
set listmax = listmax - 1
call SaveInteger (udg_FF_Hashtable, -1, 0, listmax )
if LoadInteger (udg_FF_Hashtable, 0, 0) + 1 == LoadInteger (udg_FF_Hashtable, 0, -1) then
call FlushChildHashtable (udg_FF_Hashtable, 0)
call PauseTimer (LoadTimerHandle (udg_FF_Hashtable, -2, 0))
else
call SaveInteger (udg_FF_Hashtable, 0, 0, LoadInteger(udg_FF_Hashtable, 0, 0) + 1)
call SaveInteger (udg_FF_Hashtable, 0, LoadInteger(udg_FF_Hashtable, 0, 0), ID)
endif
call FlushChildHashtable (udg_FF_Hashtable, ID)
else
call SaveReal(udg_FF_Hashtable, ID, 10, r + FF_Interval())
endif
else
set modifier = j - (j/4)*4
set x1 = x + GetRandomReal (135, FF_FieldAoe(FF_SpellLvl(caster)))*Cos(GetRandomReal(-90, 0) + modifier*90.)
set y1 = y + GetRandomReal (135, FF_FieldAoe(FF_SpellLvl(caster)))*Sin(GetRandomReal(-90, 0) + modifier*90.)
call DestroyEffect(AddSpecialEffect (FF_ExpFx(), x1, y1))
set ID2 = LoadInteger (udg_FF_Hashtable, 0, 0)
if ID2 > 0 then
call SaveInteger (udg_FF_Hashtable, 0, 0, ID2 - 1)
set ID2 = LoadInteger (udg_FF_Hashtable, 0, ID2)
else
set ID2 = LoadInteger (udg_FF_Hashtable, 0, -1) + 1
call SaveInteger (udg_FF_Hashtable, 0,-1, ID2)
endif
call SaveUnitHandle (udg_FF_Hashtable, ID2, 1, caster)
call SaveReal (udg_FF_Hashtable, ID2, 8, x1)
call SaveReal (udg_FF_Hashtable, ID2, 9, y1)
call SaveReal(udg_FF_Hashtable, ID2, 10, 0)
call SaveBoolean (udg_FF_Hashtable, ID2, 7, true)
set listmax = listmax + 1
call SaveInteger (udg_FF_Hashtable, -1, 0, listmax )
call SaveInteger (udg_FF_Hashtable, -1, listmax, ID2)
call SaveInteger (udg_FF_Hashtable, ID2, 0, listmax)
call SaveReal(udg_FF_Hashtable, ID, 5, t + FF_Interval())
call SaveInteger(udg_FF_Hashtable, ID, 6, j + 1)
endif
endif
set caster = null
endloop
endfunction
function Trig_FF_Conditions takes nothing returns boolean
local unit caster
local integer ID
local integer listmax
local real x
local real y
if GetSpellAbilityId() == FF_GetSpellID() then
set caster = GetTriggerUnit()
set x = GetSpellTargetX()
set y = GetSpellTargetY()
set ID = LoadInteger(udg_FF_Hashtable, 0, 0)
// Now we start indexing the spell
if ID>0 then
call SaveInteger(udg_FF_Hashtable, 0, 0, ID - 1)
set ID = LoadInteger (udg_FF_Hashtable, 0, ID)
else
set ID = LoadInteger(udg_FF_Hashtable, 0, -1) + 1
call SaveInteger(udg_FF_Hashtable,0 ,-1, ID)
if ID == 1 then
call TimerStart (LoadTimerHandle(udg_FF_Hashtable, -2, 0), FF_Interval(), true, function FF_TimerLoop)
endif
endif
// Save the values related to this spell instance
call SaveUnitHandle(udg_FF_Hashtable, ID, 1, caster)
call SaveReal(udg_FF_Hashtable, ID, 2, x)
call SaveReal(udg_FF_Hashtable, ID, 3, y)
call SaveEffectHandle(udg_FF_Hashtable, ID, 4, AddSpecialEffect (FF_FieldFx(), x, y))
call SaveReal(udg_FF_Hashtable, ID, 5, 0)
call SaveInteger(udg_FF_Hashtable, ID, 6, 0)
set listmax = LoadInteger (udg_FF_Hashtable, -1, 0) + 1
call SaveInteger (udg_FF_Hashtable, -1, 0, listmax )
call SaveInteger (udg_FF_Hashtable, -1, listmax, ID)
call SaveInteger (udg_FF_Hashtable, ID, 0, listmax)
set caster = null
endif
return false
endfunction
//===========================================================================
function InitTrig_Freezing_Field takes nothing returns nothing
local trigger FF = CreateTrigger()
set udg_FF_Hashtable = InitHashtable ()
call SaveTimerHandle (udg_FF_Hashtable, -2, 0, CreateTimer())
call TriggerRegisterAnyUnitEventBJ(FF, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(FF, Condition( function Trig_FF_Conditions))
set FF = null
endfunction