/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Wietlol's Advanced Event Management System 1.2 24/04/2015
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Description:
// This system is made to create events and add triggers aka event responses to an event.
// The reason is that you can remove event responses from an event, create subevents to increase performance by ignoring checks
// and to control priority of event responses.
// This system is written in JASS and requires JASSHelper to copmile.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// How to install:
// 1. Copy the Advanced Event Management System (AEM) category and paste it in your map.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// How to create event responses for GUI triggers:
// 1. Find out how the trigger is called...
// Trigger names are "gg_trg_" + the name of the trigger in the list at the left of the screen
// where spaces are replaced by underscores.
// Trigger "AEM System" is called "gg_trg_AEM_System"
// 2. Go to any JASS trigger and find the InitTrig_<triggerName> function. (Ussually found at the bottom.)
// You can go to the AEM_Normal_Events_Implementation trigger.
// 3. Write "call AEM_FunctionRegisterEvent(<eventName>, <triggerName>, udg_AEM_EXECUTION_TYPE_CONDITIONAL, 0, true, true)"
// <eventName> is the name of the event.
// <triggerName> is the name of the trigger which we have made in step 1.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Feature list:
// This system:
// - allows you to create custom events.
// - allows you to remove triggers from events.
// - allows you to control priority of event responses.
// - allows you to automatically remove an event response after the first call.
// - allows you to create an event with a (integer)parameter to separate speficif event responses into the proper events.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Variable explaination:
//////////////////////////
// General:
// - AEM_EXECUTION_TYPE_CONDITIONAL - integer
// This is the execution type for regular execution.
// It is recommended for GUI triggers.
//
// - AEM_EXECUTION_TYPE_EVALUATE - integer
// This is the execution type for conditions only.
// It is recommended for JASS triggers.
//
// - AEM_EXECUTION_TYPE_EXECUTE - integer
// This is the execution type for actions only.
// It is recommended for ... well... nothing.
//
// - AEM_Hashtable - hashtable
// The AEM System uses 3 hashtables.
// In the first hashtable are the events saved together with all their event responses.
// In the second hashtable are event ids saved of events that have a subtype.
// These subtypes can be used to increase performance of event responses
// by only running the triggers that very probably have actions on that event.
// The third hashtable allows a second subtype making events even more specific.
//
// - udg_AEM_NextIndex - integer
// This is the index of the latest event.
// When creating an event response to an unknown event, a unique number is created that will represent that event.
// For NextIndex3, the next index is for the
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Changelog:
// 1.2 - 24/04/2015 -
// - Added other spell events in the Normal Event Implementation trigger.
// - Added spell examples.
// - Added the possibility to stop all other actions to the current event.
// - Added the possibility to start an event from a certain priority.
//
// 1.1 - 20/04/2015 - Second Subtype.
// - Now has a second subtype for even more specific events.
// - Renamed register functions so the name is more logic.
// - Made the creation event have "bj_lastCreatedUnit" as the created unit.
//
// 1.0 - 17/04/2015 - First official release on the Hive.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Known bugs:
// - You can add an event response to an event multiple times but you only remove one.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
library aemSystem
globals
integer udg_AEM_EXECUTION_TYPE_CONDITIONAL = 0
integer udg_AEM_EXECUTION_TYPE_EVALUATE = 1
integer udg_AEM_EXECUTION_TYPE_EXECUTE = 2
hashtable udg_AEM_Hashtable1 = InitHashtable()
hashtable udg_AEM_Hashtable2 = InitHashtable()
hashtable udg_AEM_Hashtable3 = InitHashtable()
integer udg_AEM_NextIndex2 = 9999
integer udg_AEM_NextIndex3 = 9999
integer udg_AEM_StopRemainingEventResponses = 1
//////////////////////////////////////////////////////////////////////////////////////
//
// Event List:
// Make sure that all events have a unique id between 1 and 9,999.
// Events with 0 or lower are illegal events.
// Events above 9,999 are dynamic events, created by the second hashtable.
// You can increase that amount in the global variable above but you won't have much problems with 9,999 events.
//
// |----|-|----| |----------------------------------------------------------------|
// |0001|-|0017| |AEM_Normal_Events_Implementation |
// |----|-|----| |----------------------------------------------------------------|
//////////////////////////////////////////////////////////////////////////////////////
endglobals
//////////////////////////////////////////////////////////////////////////////////////
//These functions remove an event response from an event.
// whichEvent is the event id where the response is linked to.
// whichTrigger is the trigger that must be removed.
function AEM_FunctionRemoveEvent takes integer whichEvent, trigger whichTrigger returns nothing
local integer i = 0
local trigger t
loop
//The end of the responses is reached.
exitwhen not(HaveSavedHandle(udg_AEM_Hashtable1, whichEvent, i))
//The trigger has been found.
set t = LoadTriggerHandle(udg_AEM_Hashtable1, whichEvent, i)
if t == whichTrigger then
loop
exitwhen not HaveSavedHandle(udg_AEM_Hashtable1, whichEvent, i+4)
//Replace all event responses after the found trigger by the ones that follow it afterwards.
call SaveTriggerHandle(udg_AEM_Hashtable1, whichEvent, i, LoadTriggerHandle(udg_AEM_Hashtable1, whichEvent, i+4))
call SaveInteger(udg_AEM_Hashtable1, whichEvent, i+1, LoadInteger(udg_AEM_Hashtable1, whichEvent, i+5))
call SaveBoolean(udg_AEM_Hashtable1, whichEvent, i+2, LoadBoolean(udg_AEM_Hashtable1, whichEvent, i+6))
call SaveInteger(udg_AEM_Hashtable1, whichEvent, i+3, LoadInteger(udg_AEM_Hashtable1, whichEvent, i+7))
set i = i + 3
endloop
//Remove the last event response from the event.
call RemoveSavedHandle(udg_AEM_Hashtable1, whichEvent, i)
call RemoveSavedInteger(udg_AEM_Hashtable1, whichEvent, i+1)
call RemoveSavedBoolean(udg_AEM_Hashtable1, whichEvent, i+2)
call RemoveSavedInteger(udg_AEM_Hashtable1, whichEvent, i+3)
return
endif
set i = i + 3
endloop
endfunction
//Same as above.
// whichParameter is the subtype of the event response.
function AEM_FunctionRemoveEvent2 takes integer whichEvent, integer whichParameter2, trigger whichTrigger returns nothing
local integer index = LoadInteger(udg_AEM_Hashtable2, whichEvent, whichParameter2)
if index == 0 then
return
endif
call AEM_FunctionRemoveEvent(index, whichTrigger)
endfunction
//Same as above.
// whichParameter is the subtype of the event response.
function AEM_FunctionRemoveEvent3 takes integer whichEvent, integer whichParameter2, integer whichParameter3, trigger whichTrigger returns nothing
local integer index = LoadInteger(udg_AEM_Hashtable3, whichEvent, whichParameter2)
if index == 0 then
return
endif
call AEM_FunctionRemoveEvent2(index, whichParameter3, whichTrigger)
endfunction
//////////////////////////////////////////////////////////////////////////////////////
//These functions call the events made in this system.
// whichEvent is the event id that is fired.
function AEM_CallEventWithPriority takes integer whichEvent, integer startingPriority returns nothing
local trigger array triggers
local integer index
local integer i
local integer array executionType
local integer oldStopRemainingEventResponses
//Check if the event is a valid event.
if whichEvent <= 0 then
return
endif
//Save all event responses locally.
set i = startingPriority
set index = 0
loop
exitwhen not(HaveSavedHandle(udg_AEM_Hashtable1, whichEvent, i))
set triggers[index] = LoadTriggerHandle(udg_AEM_Hashtable1, whichEvent, i)
set executionType[index] = LoadInteger(udg_AEM_Hashtable1, whichEvent, i+3)
if not(LoadBoolean(udg_AEM_Hashtable1, whichEvent, i+2)) then
//Remove the event response because it is not repeating.
call AEM_FunctionRemoveEvent(whichEvent, triggers[index])
set i = i - 4
endif
set index = index + 1
set i = i + 4
endloop
//Call all locally saved triggers.
set oldStopRemainingEventResponses = udg_AEM_StopRemainingEventResponses
set udg_AEM_StopRemainingEventResponses = 1
set i = 0
loop
exitwhen udg_AEM_StopRemainingEventResponses <= 0
exitwhen i >= index
if executionType[i] == udg_AEM_EXECUTION_TYPE_CONDITIONAL then
if TriggerEvaluate(triggers[i]) then
call TriggerExecute(triggers[i])
endif
elseif executionType[i] == udg_AEM_EXECUTION_TYPE_EVALUATE then
call TriggerEvaluate(triggers[i])
elseif executionType[i] == udg_AEM_EXECUTION_TYPE_EXECUTE then
call TriggerExecute(triggers[i])
endif
set triggers[i] = null
set i = i + 1
endloop
set udg_AEM_StopRemainingEventResponses = oldStopRemainingEventResponses
endfunction
function AEM_CallEvent takes integer whichEvent returns nothing
call AEM_CallEventWithPriority(whichEvent, 0)
endfunction
//Same as above.
// whichParameter2 is the subtype of the event response.
function AEM_CallEvent2WithPriority takes integer whichEvent, integer whichParameter2, integer startingPriority returns nothing
call AEM_CallEventWithPriority(LoadInteger(udg_AEM_Hashtable2, whichEvent, whichParameter2), startingPriority)
endfunction
function AEM_CallEvent2 takes integer whichEvent, integer whichParameter2 returns nothing
call AEM_CallEvent2WithPriority(whichEvent, whichParameter2, 0)
endfunction
//Same as above.
// whichParameter3 is the sub-subtype of the event response.
function AEM_CallEvent3WithPriority takes integer whichEvent, integer whichParameter2, integer whichParameter3, integer startingPriority returns nothing
call AEM_CallEvent2WithPriority(LoadInteger(udg_AEM_Hashtable3, whichEvent, whichParameter2), whichParameter3, startingPriority)
endfunction
function AEM_CallEvent3 takes integer whichEvent, integer whichParameter2, integer whichParameter3 returns nothing
call AEM_CallEvent3WithPriority(whichEvent, whichParameter2, whichParameter3, 0)
endfunction
//////////////////////////////////////////////////////////////////////////////////////
//These functions register a trigger to an event.
// whichEvent is the event id that is used.
// whichTrigger is the trigger that is executed when the event fires.
// executionType is the type of how the trigger is executed (only conditions, only actions, both (if conditions allow to)).
// priority is the order in which the triggers are executed. Low priority is called first. High priority is called last.
// priorize is if this trigger must be before the other trigger in the same priority. Be aware that registrations after this one can override that priority.
// repeating is if the trigger must remain on the event. When this is put to false, the trigger gets removed from the event on the next call.
function AEM_RegisterTrigger takes integer whichEvent, trigger whichTrigger, integer executionType, integer priority, boolean priorize, boolean repeating returns nothing
local integer i = 0
local integer i2
local boolean shiftRemaining = false
//Find the proper place for the event response.
loop
exitwhen not(HaveSavedHandle(udg_AEM_Hashtable1, whichEvent, i))
set shiftRemaining = true
if priorize then
exitwhen LoadInteger(udg_AEM_Hashtable1, whichEvent, i+1) >= priority
else
exitwhen LoadInteger(udg_AEM_Hashtable1, whichEvent, i+1) > priority
endif
set shiftRemaining = false
set i = i + 4
endloop
//Check if the event response is placed between other event responses or placed at the end.
if shiftRemaining then
set i2 = i + 4
loop
exitwhen not(HaveSavedHandle(udg_AEM_Hashtable1, whichEvent, i2))
set i2 = i2 + 4
endloop
loop
exitwhen i2 == i
call SaveTriggerHandle(udg_AEM_Hashtable1, whichEvent, i2, LoadTriggerHandle(udg_AEM_Hashtable1, whichEvent, i2-4))
call SaveInteger(udg_AEM_Hashtable1, whichEvent, i2+1, LoadInteger(udg_AEM_Hashtable1, whichEvent, i2-3))
call SaveBoolean(udg_AEM_Hashtable1, whichEvent, i2+2, LoadBoolean(udg_AEM_Hashtable1, whichEvent, i2-2))
call SaveInteger(udg_AEM_Hashtable1, whichEvent, i+3, LoadInteger(udg_AEM_Hashtable1, whichEvent, i2-1))
set i2 = i2 - 4
endloop
endif
//Save the event response to the event.
call SaveTriggerHandle(udg_AEM_Hashtable1, whichEvent, i, whichTrigger)
call SaveInteger(udg_AEM_Hashtable1, whichEvent, i+1, priority)
call SaveBoolean(udg_AEM_Hashtable1, whichEvent, i+2, repeating)
call SaveInteger(udg_AEM_Hashtable1, whichEvent, i+3, executionType)
endfunction
//Same as above.
// whichParameter2 is the subtype of the event.
function AEM_RegisterTrigger2 takes integer whichEvent, integer whichParameter2, trigger whichTrigger, integer executionType, integer priority, boolean priorize, boolean repeating returns nothing
//If the event doesn't exist yet, create an event with the NextIndex2.
local integer index = LoadInteger(udg_AEM_Hashtable2, whichEvent, whichParameter2)
if index == 0 then
set udg_AEM_NextIndex2 = udg_AEM_NextIndex2 + 1
set index = udg_AEM_NextIndex2
call SaveInteger(udg_AEM_Hashtable2, whichEvent, whichParameter2, index)
endif
//Add the trigger to the event response.
call AEM_RegisterTrigger(index, whichTrigger, executionType, priority, priorize, repeating)
endfunction
//Same as above.
// whichParameter3 is the sub-subtype of the event.
function AEM_RegisterTrigger3 takes integer whichEvent, integer whichParameter2, integer whichParameter3, trigger whichTrigger, integer executionType, integer priority, boolean priorize, boolean repeating returns nothing
//If the event doesn't exist yet, create an event with the NextIndex3.
local integer index = LoadInteger(udg_AEM_Hashtable3, whichEvent, whichParameter2)
if index == 0 then
set udg_AEM_NextIndex3 = udg_AEM_NextIndex3 + 1
set index = udg_AEM_NextIndex3
call SaveInteger(udg_AEM_Hashtable3, whichEvent, whichParameter2, index)
endif
//Add the trigger to the event response.
call AEM_RegisterTrigger2(index, whichParameter3, whichTrigger, executionType, priority, priorize, repeating)
endfunction
endlibrary
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// AEM System end
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////