Name | Type | is_array | initial_value |
cast | unit | No | |
LF_Angle | real | No | |
LF_Boolean | boolean | No | |
LF_Dummy | unit | Yes | |
LF_Int | integer | No | |
LF_OverallTime | real | Yes | |
LF_SFX | string | No | |
LF_SFXandDMGTime | real | Yes | |
Spell__Ability | abilcode | No | |
Spell__Caster | unit | No | |
Spell__CasterOwner | player | No | |
Spell__CastPoint | location | No | |
Spell__DummyGroup | group | No | |
Spell__DummyOwner | player | No | |
Spell__DummyType | unitcode | No | |
Spell__Index | integer | No | |
Spell__Interval | real | No | |
Spell__Level | integer | No | |
Spell__Target | unit | No | |
Spell__TargetGroup | group | No | |
Spell__TargetPoint | location | No | |
Spell__Time | real | No | |
Spell__Trigger_OnCast | trigger | No | |
Spell__Trigger_OnDestroy | trigger | No | |
Spell__Trigger_OnLoop | trigger | No | |
Spell__UseDummyGroup | boolean | No | |
Spell__UseTargetGroup | boolean | No | |
Spell_e_BeginsCast | integer | No | |
Spell_e_BeginsChannel | integer | No | |
Spell_e_Event | integer | No | |
Spell_e_FinishesCast | integer | No | |
Spell_e_StartsEffect | integer | No | |
Spell_e_StopsCast | integer | No | |
Spell_i_AbilAsInt | integer | No | |
Spell_i_Caster | unit | Yes | |
Spell_i_DummyGroup | group | Yes | |
Spell_i_Hash | hashtable | No | |
Spell_i_Index_Gen | integer | No | |
Spell_i_Index_Head | integer | No | |
Spell_i_Index_LastRecycled | integer | No | |
Spell_i_Index_Next | integer | Yes | |
Spell_i_Index_Node | integer | No | |
Spell_i_Index_Prev | integer | Yes | |
Spell_i_Index_RecycleList | integer | Yes | |
Spell_i_Index_Ref | integer | Yes | |
Spell_i_Level | integer | Yes | |
Spell_i_OnCastStack | trigger | Yes | |
Spell_i_OnDestroyStack | trigger | Yes | |
Spell_i_OnLoopStack | trigger | Yes | |
Spell_i_Player | player | Yes | |
Spell_i_PreloadDummy | unit | No | |
Spell_i_Target | unit | Yes | |
Spell_i_TargetGroup | group | Yes | |
Spell_i_TargetX | real | Yes | |
Spell_i_TargetY | real | Yes | |
Spell_i_Time | real | Yes | |
Spell_i_Timer | timer | No | |
Spell_i_TimerHeadRef | integer | Yes | |
Spell_i_TimerHeadStack | integer | Yes | |
Spell_i_TimerN | integer | No | |
Spell_i_UseDG | boolean | Yes | |
Spell_i_UseTG | boolean | Yes | |
TempPoint | location | No | |
TempPoint2 | location | No | |
unit | unit | Yes |
//TESH.scrollpos=0
//TESH.alwaysfold=0
//Called automatically before running OnLoop triggers. Can be called manually
//by the user if needed at a different time.
function SpellIndexGetVars takes nothing returns nothing
set udg_Spell__Caster = udg_Spell_i_Caster[udg_Spell__Index]
set udg_Spell__CasterOwner = udg_Spell_i_Player[udg_Spell__Index]
set udg_Spell__Level = udg_Spell_i_Level[udg_Spell__Index]
set udg_Spell__Target = udg_Spell_i_Target[udg_Spell__Index]
//Assign the saved coordinates to the static locations
call MoveLocation(udg_Spell__CastPoint, GetUnitX(udg_Spell__Caster), GetUnitY(udg_Spell__Caster))
if udg_Spell__Target == null then
call MoveLocation(udg_Spell__TargetPoint, udg_Spell_i_TargetX[udg_Spell__Index], udg_Spell_i_TargetY[udg_Spell__Index])
else
call MoveLocation(udg_Spell__TargetPoint, GetUnitX(udg_Spell__Target), GetUnitY(udg_Spell__Target))
endif
set udg_Spell__DummyGroup = udg_Spell_i_DummyGroup[udg_Spell__Index]
set udg_Spell__TargetGroup = udg_Spell_i_TargetGroup[udg_Spell__Index]
endfunction
//Purges unit group array slots
function SpellSystemDestroyGroups takes integer i returns nothing
if udg_Spell_i_DummyGroup[i] != null then
call DestroyGroup(udg_Spell_i_DummyGroup[i])
set udg_Spell_i_DummyGroup[i] = null
endif
if udg_Spell_i_TargetGroup[i] != null then
call DestroyGroup(udg_Spell_i_TargetGroup[i])
set udg_Spell_i_TargetGroup[i] = null
endif
endfunction
//Runs every Spell__Interval seconds.
function SpellTimerLoop takes nothing returns nothing
local integer i = udg_Spell_i_TimerN
local integer node
//Run stack top to bottom to avoid skipping slots when destroying.
loop
set i = i - 1
exitwhen i < 0
set udg_Spell_i_Index_Head = udg_Spell_i_TimerHeadStack[i]
set node = udg_Spell_i_Index_Head
//This inner loop is a linked list.
loop
set node = udg_Spell_i_Index_Next[node]
exitwhen node == udg_Spell_i_Index_Head
//Set Spell__Index so the user can access it.
set udg_Spell__Index = node
set udg_Spell_i_Time[node] = udg_Spell_i_Time[node] - udg_Spell__Interval
if udg_Spell_i_Time[node] <= 0.00 then
call SpellIndexGetVars()
//Run the user's trigger.
call TriggerExecute(udg_Spell_i_OnLoopStack[udg_Spell_i_Index_Head])
//In case the user set these variables from the callback trigger,
//store them into the array
set udg_Spell_i_Time[node] = udg_Spell__Time
set udg_Spell__Time = 0.00
endif
endloop
endloop
endfunction
//This function is called automatically before running the OnCast trigger if
//you specified an OnLoop trigger. Otherwise, it could be called manually if
//you need to keep track of your indexing in a different way. I don't call it
//automatically in case the user doesn't need indexing and just wants a simple
//spell event.
function CreateSpellIndex takes nothing returns nothing
if udg_Spell_i_Index_LastRecycled == 0 then
//Create a new, unique index
set udg_Spell_i_Index_Gen = udg_Spell_i_Index_Gen + 1
set udg_Spell__Index = udg_Spell_i_Index_Gen
else
//Use a recycled one
set udg_Spell__Index = udg_Spell_i_Index_LastRecycled
set udg_Spell_i_Index_LastRecycled = udg_Spell_i_Index_RecycleList[udg_Spell_i_Index_LastRecycled]
endif
set udg_Spell_i_Caster[udg_Spell__Index] = udg_Spell__Caster
set udg_Spell_i_Player[udg_Spell__Index] = udg_Spell__CasterOwner
set udg_Spell_i_Level[udg_Spell__Index] = udg_Spell__Level
set udg_Spell_i_Target[udg_Spell__Index] = udg_Spell__Target
//Only store coordinates so as to never need to create or remove those locations
set udg_Spell_i_TargetX[udg_Spell__Index] = GetLocationX(udg_Spell__TargetPoint)
set udg_Spell_i_TargetY[udg_Spell__Index] = GetLocationY(udg_Spell__TargetPoint)
if udg_Spell_i_UseDG[udg_Spell_i_Index_Head] then
set udg_Spell__DummyGroup = CreateGroup()
set udg_Spell_i_DummyGroup[udg_Spell__Index] = udg_Spell__DummyGroup
endif
if udg_Spell_i_UseTG[udg_Spell_i_Index_Head] then
set udg_Spell__TargetGroup = CreateGroup()
set udg_Spell_i_TargetGroup[udg_Spell__Index] = udg_Spell__TargetGroup
endif
// Index the head node of this ability ID
set udg_Spell_i_Index_Ref[udg_Spell__Index] = udg_Spell_i_Index_Head
if udg_Spell_i_OnLoopStack[udg_Spell_i_Index_Head] != null then
if udg_Spell_i_Index_Next[udg_Spell_i_Index_Head] == udg_Spell_i_Index_Head then
// If the list is empty, allocate the loop trigger.
set udg_Spell_i_TimerHeadStack[udg_Spell_i_TimerN] = udg_Spell_i_Index_Head
set udg_Spell_i_TimerHeadRef[udg_Spell_i_Index_Head] = udg_Spell_i_TimerN
set udg_Spell_i_TimerN = udg_Spell_i_TimerN + 1
if udg_Spell_i_TimerN == 1 then
// If this is the only OnLoop trigger activated, start the OnLoop system timer
call TimerStart(udg_Spell_i_Timer, udg_Spell__Interval, true, function SpellTimerLoop)
endif
endif
// Add the new index to the linked list of the head node
set udg_Spell_i_Index_Prev[udg_Spell__Index] = udg_Spell_i_Index_Prev[udg_Spell_i_Index_Head]
set udg_Spell_i_Index_Next[udg_Spell_i_Index_Prev[udg_Spell_i_Index_Head]] = udg_Spell__Index
set udg_Spell_i_Index_Prev[udg_Spell_i_Index_Head] = udg_Spell__Index
set udg_Spell_i_Index_Next[udg_Spell__Index] = udg_Spell_i_Index_Head
endif
// Set the following variable to -1 to let the system know this index is safe to recycle later on
set udg_Spell_i_Index_RecycleList[udg_Spell__Index] = -1
endfunction
function SpellSystemEvent takes nothing returns boolean
set udg_Spell__Ability = GetSpellAbilityId()
set udg_Spell_i_Index_Head = LoadInteger(udg_Spell_i_Hash, GetHandleId(GetTriggerEventId()), udg_Spell__Ability)
if udg_Spell_i_Index_Head > 0 then
//Recover event response values
set udg_Spell__Caster = GetTriggerUnit()
set udg_Spell__CasterOwner = GetTriggerPlayer()
set udg_Spell__Level = GetUnitAbilityLevel(udg_Spell__Caster, udg_Spell__Ability)
call MoveLocation(udg_Spell__CastPoint, GetUnitX(udg_Spell__Caster), GetUnitY(udg_Spell__Caster))
set udg_Spell__Target = GetSpellTargetUnit()
if udg_Spell__Target != null then
call MoveLocation(udg_Spell__TargetPoint, GetUnitX(udg_Spell__Target), GetUnitY(udg_Spell__Target))
else
call MoveLocation(udg_Spell__TargetPoint, GetSpellTargetX(), GetSpellTargetY())
endif
if udg_Spell_i_OnLoopStack[udg_Spell_i_Index_Head] != null then
call CreateSpellIndex()
endif
//Run the user's OnCast trigger.
call TriggerExecute(udg_Spell_i_OnCastStack[udg_Spell_i_Index_Head])
//If you use indexing and a Spell__Time was specified, remember that time.
if udg_Spell__Time > 0.00 then
set udg_Spell_i_Time[udg_Spell__Index] = udg_Spell__Time
set udg_Spell__Time = 0.00
endif
endif
return false
endfunction
//===========================================================================
function InitTrig_Spell_System takes nothing returns nothing
local integer i = 0
//This runs before map init events so the hashtable is ready before then.
set udg_Spell_i_Hash = InitHashtable()
//Default event: EVENT_PLAYER_UNIT_SPELL_EFFECT
set udg_Spell_e_Event = 274
//Initialize these two locations which will never get removed
set udg_Spell__CastPoint = Location(0, 0)
set udg_Spell__TargetPoint = Location(0, 0)
//Destroy all system unit groups as they will be overwritten.
call DestroyGroup(udg_Spell__DummyGroup)
call DestroyGroup(udg_Spell__TargetGroup)
set udg_Spell__DummyGroup = null
set udg_Spell__TargetGroup = null
call SpellSystemDestroyGroups(0)
call SpellSystemDestroyGroups(1)
//Create a dummy unit for preloading abilities.
set udg_Spell_i_PreloadDummy = CreateUnit(udg_Spell__DummyOwner, udg_Spell__DummyType, 0, 0, 0)
call UnitApplyTimedLife(udg_Spell_i_PreloadDummy, 'BTLF', 0.01)
//I am using this global trigger to give users the ability to disable or
//enable all spell events at once if they desire it.
set gg_trg_Spell_System = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(gg_trg_Spell_System, EVENT_PLAYER_UNIT_SPELL_CHANNEL)
call TriggerRegisterAnyUnitEventBJ(gg_trg_Spell_System, EVENT_PLAYER_UNIT_SPELL_CAST)
call TriggerRegisterAnyUnitEventBJ(gg_trg_Spell_System, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerRegisterAnyUnitEventBJ(gg_trg_Spell_System, EVENT_PLAYER_UNIT_SPELL_ENDCAST)
call TriggerRegisterAnyUnitEventBJ(gg_trg_Spell_System, EVENT_PLAYER_UNIT_SPELL_FINISH)
call TriggerAddCondition(gg_trg_Spell_System, Filter(function SpellSystemEvent))
//Run the configuration trigger so its variables are ready before the
//map initialization events run.
call TriggerExecute(gg_trg_Spell_System_Config)
endfunction