• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[ROC]Event Manager v1.0f2 1.24&vJASS required

WARNING : YOU MUST USE JASSHELPER 0.9.Z.5 !!!
Download here : http://www.wc3c.net/showthread.php?t=88142


This system was made in order to allow very intuitive callbacks.
This works like WC3's events : you register a trigger (or several triggers) to an event and you'll get callback each time the event is triggered.
The system triggers an event whenever you tells him to do.

Events does not even need to be predefined. They are designed by an integer (use stringhashes plz), and will check if there are triggers bound to this integer when you trigger an event. But it won't check anything when you register the event.

Of course, the system can do more, so read the doc, for depth use.

first, you may want to read the step by step tutorial.

Any comment/suggestion on how to improve this system are welcome. You can also share tips about using the system for special cases



JASS:
//--------------------------------
// Welcome to the documentation   
//--------------------------------
// System made by : IaMfReNcH     
//                                
// Hope you'll find all you want  
// to know here. If you don't,    
// feel free to ask your questions
//--------------------------------

// Short description :

// This system was made in order to allow easily interfacing between user and systems.
// Because when you create a system, sometimes, you may want to allow user to react to what you are doing.
// With this system, this is possible. You can trigger custom events, so it's up to the user to decide
// which trigger(s) may handle your events, or simply ignore them.

// For a basic use, you may only need 1 function
// if you are a user :
call TriggerRegisterCustomEventString(your_trigger, EventName)
// if you are want to trigger user's triggers
call TriggerCustomEventString(EventName)

// Well, everytime you (or someone) calls TriggerCustomEventString, all trigger registered with
// TriggerRegisterCustomEventString will be fired after checking conditions

// Then is the in depth doc, describing all available functions (if I didn't forget to update anything)

//-----------------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------

// 0 - Tips
//      * You can register several events for a same trigger
//      * You can register several triggers for a same event
//      * This is not intended for debuging purpose only.
//        You may use it in various situations, giving custom data with globals
//      * If you're trigger doesn't instant use data, you shall copy globals into locals

//-----------------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------

// 1 - Functions to register an event handler

// those functions enables you register an event for your trigger in the same way you would do with blizzard's ones.

function TriggerRegisterCustomEvent takes trigger whichTrigger, integer EventId returns boolean
function TriggerRegisterCustomEventString takes trigger whichTrigger, string Event returns boolean

// both functions takes the handler has the first trigger argument

// The first function takes an integer for the event id to be handled by the trigger.
// It's meant to be a constant used here. Here is a sample.
constant integer GenericErrorCode = StringHash("GenericError")
// So, it's easier to avoid clashes with names

// The second function takes a string as parameter,
// so you don't need to use a constant or cast the string yourself
// Your line will looks shorter.
// If you enable inlining, you won't loss efficiency

// the functions will return false if the trigger is already bound to the event

// Once a event is triggered, you can check the event with
function GetEventId takes nothing returns integer
// Then, you may use the triggerer's function/globals to gather data

// Whenever an event is registered, a TriggerRegisteredAnyEvent event is sent.
// here is the code :
constant integer TriggerRegisteredAnyEventCode = StringHash("TriggerRegisteredAnyEvent")
// Another specific event is sent. Register it with the following line :
TriggerRegisterCustomEventString(trigger, "TriggerRegisteredEvent" + I2S(EVENT_ID))
// you can also retrieve EVENT_ID by StringHash(EVENT_NAME)
// then retrieve data with :
function GetRegisteringTrigger takes nothing returns trigger
function GetRegisteredEventId takes nothing returns integer

//-----------------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------

// 2 - functions to unregister an event handler

// those functions simply unregister an event for a trigger, so it won't fire when the event will be summoned again

function TriggerUnregisterCustomEvent takes trigger whichTrigger, integer EventId returns boolean
function TriggerUnregisterCustomEventString takes trigger whichTrigger, string Event returns boolean

// Those functions works same as the registering ones.
// But they'll return false if the trigger isn't bound or if an error happened
// if an error happens, an EventManagerError will be triggered. Use the function below for more details on the error

function GetEventManagerError takes nothing returns string

// an event is sent, like the one sent by TriggerRegisterCustomEvent :
constant integer TriggerRegisteredAnyEventCode = StringHash("TriggerUnregisteredAnyEvent")
// special event line :
TriggerRegisterCustomEventString(trigger, "TriggerUnregisteredEvent" + I2S(EVENT_ID))
// data functions :
function GetUnregisteringTrigger takes nothing returns trigger
function GetUnregisteredEventId takes nothing returns integer

//-----------------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------

// 3 - function to trigger an event

// those functions cause the system firing all the trigger registered with the specified event id

function TriggerCustomEvent takes integer EventId returns boolean
function TriggerCustomEventString takes string Event returns boolean

// You just give as an argument the event id/name.
// the function will return false if there is no handler for this event

// You may give your own data with globals.

// The following function will trigger a GenericError event, and put message into the string GenericError.
// It's just to trigger easily error, in one meaningful line.
function TriggerError takes string message returns boolean

//-----------------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------

// 4 - checking functions

// those functions allows you to check a register state

// returns true if the trigger has registered the event, false else
function IsRegisteredEvent takes trigger whichTrigger, integer EventId returns boolean
function IsRegisteredEventString takes trigger whichTrigger, string Event returns boolean

// returns true if the event have registered triggers, false else
function HasRegisteredTriggers takes integer EventId returns boolean
function HasRegisteredTriggersString takes string Event returns boolean

You'll see how short it is to create and use events.

First, copy triggers which are in the folder 'EventManager'.
Maybe also the folder 'EventPack'

then think about your event name.

Then, wherever you want to call your event, copy this :
JASS:
call TriggerCustomEventString("your event name")
And it's done ! A single line is enough !

The user may use as well a single line :
JASS:
call TriggerRegisterCustomEventString(his trigger, "your event name")
nothing else is needed.

Of course library has other functions for advanced use : hooking event registering, asking wether a trigger is bound and unregistering a trigger.
Everyfunctions has a string and integer version for speed freaks.
Using strings allows you to generate events following a rule you tell the user, so he can follow the same rule to register specific events.

So, you want to register a trigger that will fire when an event is trigger... But you want to be triggered only on specific cases (like WC3's specific unit events, but with everything)
So, here is the solution : since events doesn't needs to be predefined, you can use dynamic strings for triggering/registering an event. You just need to generate a new string with a part of data embeded :
JASS:
"MyEvent" + I2S(GetHandleId(what I want to embed))
You are here generating a new string.
This will only fire triggers which registered this event. I repeat it again : events does not need to be predefined (in a sort, it's the user who define them to the system, as you told him to define). So, this can be overused without problems. It'll be faster than a condition.

JASS:
globals
    // there is the data you want. Should be initialized with null values
endglobals

function Trig_MyEventRegisterHandler_Actions takes nothing returns nothing
    // now check the event id
    if GetEventId() != "TriggerRegisteredEvent" + I2S(MY_EVENT_ID) then
        return
    endif

    // check the data

    if invalid or missing data then
        // unbind the trigger
        call TriggerUnregisterCustomEvent(GetRegisteringTrigger(), GetRegisteredEventId())
        call TriggerError("invalid or missing data") // you may also tell which data is wrong
        // eventually spread your own error event with the invalid globals
    else
        // process data. Do what you want
    endif

    // reset the data to ensure it won't hide a missing error on a further registering
    // you can eventually store into locals and reset then if you need some waits.
endfunction

//===========================================================================
function InitTrig_MyEventRegisterHandler takes nothing returns nothing
    set gg_trg_MyEventRegisterHandler = CreateTrigger(  )
    
    // register the event like any other event.
    call TriggerRegisterCustomEventString(gg_trg_MyEventRegisterHandler, "TriggerRegisteredEvent" + I2S(MY_EVENT_ID))
    
    call TriggerAddAction( gg_trg_MyEventRegisterHandler, function Trig_MyEventRegisterHandler_Actions )
endfunction

1.0f2 -> introduce blizzard's event emulation

1.0f -> minor fixes

1.0e2 -> added a benchmark, which can be triggered via "-trigger busy" to compute execution time on your system.

1.0e -> small fixes. Added a new core version using a struct instead of dummies. Since I don't really know which is best, I didn't removed the previous, and I update both on versions.

1.0d -> The event manager now throws 2 events when a trigger register/unregister an event

1.0c -> added checking function
  • IsRegisteredEvent(trigger whichTrigger, integer EventId)
  • IsRegisteredEventString(trigger whichTrigger, string Event)
  • HasRegisteredTriggers(integer EventId)
  • HasRegisteredTriggersString(string Event)
1.0b
  • added function GetEventId()
  • added function TriggerError(string message) to trigger easily generics error
1.0 -> first release

The last version provide an event pack.
  • auto-enable macro is a macro used to enable a trigger only if an event is registered.
  • "AnyUnitDamaged" event to avoid you coding again and again this trigger. This requires auto-enable macro. You can take a look to this trigger to see how works auto-enable macro
  • Blizzard's event emulation. This is a macro which automatically create a trigger listening a blizzard event and triggering a custom event. So you can listen blizzard event as if they were custom event (unregistering, registration check...)

Feel free to request for events to be included in this event pack (and you'll get credited).



JASS:
library EventManager

    private struct TriggerList
        
        TriggerList next
        TriggerList prev
        trigger handler
        
        // just init with default values
        static method create takes nothing returns TriggerList
            local TriggerList this = TriggerList.allocate()
            
            set this.next = 0
            set this.prev = 0
            set this.handler = null
            
            return this
        endmethod
        
    endstruct

    globals
    
        // public data
            
            // errors code, use for EventId
            constant integer EventManagerErrorCode = StringHash("EventManagerError")
            constant integer GenericErrorCode = StringHash("GenericError")
            // code to use as EventId when people (un)registers a trigger
            constant integer TriggerRegisteredAnyEventCode = StringHash("TriggerRegisteredAnyEvent")
            constant integer TriggerUnregisteredAnyEventCode = StringHash("TriggerUnregisteredAnyEvent")
            
            // string you can use for a GenericError
            string GenericError = ""
        
        // private data
        private string EventManagerError = ""
        private hashtable EventManagerHash = InitHashtable()
        private integer EventIdG
        private trigger RegisteringTrigger
        private integer RegisteredEventId
        private trigger UnregisteringTrigger
        private integer UnregisteredEventId
        
    endglobals
    
    // returns the triggering event id
    function GetEventId takes nothing returns integer
        return EventIdG
    endfunction
    
    // returns the internal event manager error description
    function GetEventManagerError takes nothing returns string
        return EventManagerError
    endfunction

    // returns the registering trigger
    function GetRegisteringTrigger takes nothing returns trigger
        return RegisteringTrigger
    endfunction
    
    // returns the registered event
    function GetRegisteredEventId takes nothing returns integer
        return RegisteredEventId
    endfunction
    
    // returns the unregistering trigger
    function GetUnregisteringTrigger takes nothing returns trigger
        return UnregisteringTrigger
    endfunction
    
    // returns the unregistered event
    function GetUnregisteredEventId takes nothing returns integer
        return UnregisteredEventId
    endfunction
    
    // we'll return true to notify at least one handler, false if there is no handler
    function TriggerCustomEvent takes integer EventId returns boolean
    
        local TriggerList iterator = LoadInteger(EventManagerHash, EventId, 0) // the value into the hashtable is the first index
        
        // check the List
        if iterator == 0 then
            return false
        endif
        
        set EventIdG = EventId
        
        // enumerate and execute every trigger into the list
        loop
            
            // check conditions, and execute the trigger then
            if IsTriggerEnabled(iterator.handler) then
                if TriggerEvaluate(iterator.handler) then
                    call TriggerExecute(iterator.handler)
                endif
            endif
            
            // exit when there is no next elements
            exitwhen iterator.next == 0
            
            // select the next element
            set iterator = iterator.next
        endloop    
        
        // if it's a generic error, back the string to "", to avoid bad infos next time if the string doesn't change
        if EventId == GenericErrorCode then
            set GenericError = ""
        endif
        // reset the EventId's global
        set EventIdG = 0
        
        return true
    endfunction
    
    function TriggerCustomEventString takes string Event returns boolean
        return TriggerCustomEvent(StringHash(Event))
    endfunction
    
    // this function just do the triggering error easy in a single line (instead of two)
    // This function is just more readable and meaningfull
    function TriggerError takes string message returns boolean
        set GenericError = message
        return TriggerCustomEvent(GenericErrorCode)
    endfunction
    
    // register a trigger with an event, so it'll be called back when the event happens
    // returns false if the trigger was already registered
    function TriggerRegisterCustomEvent takes trigger whichTrigger, integer EventId returns boolean
    
        // try to load the list
        local TriggerList iterator = LoadInteger(EventManagerHash, EventId, 0)
        
        // check the trigger isn't already bound to the event
        local TriggerList element = LoadInteger(EventManagerHash, EventId, GetHandleId(whichTrigger))
        
        // the trigger is already bound to an event
        if element != 0 then
            // check an eventual error
            if iterator == 0 then
                set EventManagerError = "The trigger is bound to a list element for this event, but the event list could not be found... please report"
                call TriggerCustomEvent(EventManagerErrorCode)
            endif
            
            if element.handler != whichTrigger then
                set EventManagerError = "The trigger is bound to an element in the list, but the element is not bound to the trigger... please report"
                call TriggerCustomEvent(EventManagerErrorCode)
            endif
            
            return false
        endif
        
        // allocate a list element
        set element = TriggerList.create()
        
        // if the list isn't yet created, we do this right now
        if iterator == 0 then
            set iterator = element
            call SaveInteger(EventManagerHash, EventId, 0, iterator)
        else
            // push as a first element
            set iterator.prev = element
            set element.next = iterator
            set iterator = element
        endif
        
        set element.handler = whichTrigger
        //and the trigger to the element
        call SaveInteger(EventManagerHash, EventId, GetHandleId(whichTrigger), element)
        
        // send an event to notify that a trigger registered an event
        set RegisteringTrigger = whichTrigger
        set RegisteredEventId = EventId
        
        call TriggerCustomEvent(TriggerRegisteredAnyEventCode)
        call TriggerCustomEventString("TriggerRegisteredEvent" + I2S(EventId))
        
        set RegisteringTrigger = null
        set RegisteredEventId = 0
    
        return true
        
    endfunction
    
    function TriggerRegisterCustomEventString takes trigger whichTrigger, string Event returns boolean
        return TriggerRegisterCustomEvent(whichTrigger, StringHash(Event))
    endfunction
    
    // return false if something is weird or if the trigger isn't registered
    // if something is weird, a EventManagerError event will be triggered
    function TriggerUnregisterCustomEvent takes trigger whichTrigger, integer EventId returns boolean
    
        local TriggerList iterator = LoadInteger(EventManagerHash, EventId, 0)
        local TriggerList element = LoadInteger(EventManagerHash, EventId, GetHandleId(whichTrigger))
        
        // if the element is null, the event isn't registered : abort
        if element == 0 then
            return false
        endif
        
        if iterator == 0 then
            set EventManagerError = "The trigger seems to be registered: an element has been found, but the list couldn't be found... please report"
            call TriggerCustomEvent(EventManagerErrorCode)
            // abort
            return false
        endif
        
        if element.handler != whichTrigger then
            set EventManagerError = "The trigger is bound to a list element, but the element isn't bound to the trigger... please report"
            call TriggerCustomEvent(EventManagerErrorCode)
            // abort
            return false
        endif
        
        // remove the binding
        call RemoveSavedInteger(EventManagerHash, EventId, GetHandleId(whichTrigger))
        
        if element.next == 0 and element.prev == 0 then
        
            // first case : single element into the list
            if element != iterator then
                set EventManagerError = "The list element says he is the single of the list(so the first), but the hashtable says he isn't the first... please report"
                call TriggerCustomEvent(EventManagerErrorCode)
                return false
            endif
            
            call RemoveSavedInteger(EventManagerHash, EventId, 0)
            call element.destroy()
            
        elseif element.next == 0 then
        
            // last element of the list
            set element.prev.next = 0
            call element.destroy()
            
        elseif element.prev == 0 then
        
            // first element of the list
            if element != iterator then
                set EventManagerError = "The list element says he is the first of the list, but the hashtable says he isn't the first... please report"
                call TriggerCustomEvent(EventManagerErrorCode)
                return false
            endif
            set element.next.prev = 0
            call SaveInteger(EventManagerHash, EventId, 0, element.next)
            call element.destroy()
            
        else
        
            // element between other elements
            set element.next.prev = element.prev
            set element.prev.next = element.next
            call element.destroy()
            
        endif
        
        // send an event to notify that a trigger unregistered an event
        set UnregisteringTrigger = whichTrigger
        set UnregisteredEventId = EventId
        
        call TriggerCustomEvent(TriggerUnregisteredAnyEventCode)
        call TriggerCustomEventString("TriggerUnregisteredEvent" + I2S(EventId))
        
        set UnregisteringTrigger = null
        set UnregisteredEventId = 0
        
        // sucess
        return true
        
    endfunction
    
    function TriggerUnregisterCustomEventString takes trigger whichTrigger, string Event returns boolean
        return TriggerUnregisterCustomEvent(whichTrigger, StringHash(Event))
    endfunction
    
    // returns true if the trigger has registered the event, false else
    function IsRegisteredEvent takes trigger whichTrigger, integer EventId returns boolean
    
        local TriggerList element = LoadInteger(EventManagerHash, EventId, GetHandleId(whichTrigger))
        
        return element != 0
        
    endfunction
    
    function IsRegisteredEventString takes trigger whichTrigger, string Event returns boolean
        return IsRegisteredEvent(whichTrigger, StringHash(Event))
    endfunction

    // returns true if the event have registered triggers, false else
    function HasRegisteredTriggers takes integer EventId returns boolean
    
        // Get the list
        local TriggerList iterator = LoadInteger(EventManagerHash, EventId, 0)
        
        return iterator != 0
        
    endfunction
    
    function HasRegisteredTriggersString takes string Event returns boolean
        return HasRegisteredTriggers(StringHash(Event))
    endfunction
    
endlibrary
JASS:
//--------------------------------
// Welcome to the documentation   
//--------------------------------
// System made by : IaMfReNcH     
//                                
// Hope you'll find all you want  
// to know here. If you don't,    
// feel free to ask your questions
//--------------------------------

// Short description :

// This system was made in order to allow easily interfacing between user and systems.
// Because when you create a system, sometimes, you may want to allow user to react to what you are doing.
// With this system, this is possible. You can trigger custom events, so it's up to the user to decide
// which trigger(s) may handle your events, or simply ignore them.

// For a basic use, you may only need 1 function
// if you are a user :
call TriggerRegisterCustomEventString(your_trigger, EventName)
// if you are want to trigger user's triggers
call TriggerCustomEventString(EventName)

// Well, everytime you (or someone) calls TriggerCustomEventString, all trigger registered with
// TriggerRegisterCustomEventString will be fired after checking conditions

// Then is the in depth doc, describing all available functions (if I didn't forget to update anything)

//-----------------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------

// 0 - Tips
//      * You can register several events for a same trigger
//      * You can register several triggers for a same event
//      * This is not intended for debuging purpose only.
//        You may use it in various situations, giving custom data with globals
//      * If you're trigger doesn't instant use data, you shall copy globals into locals

//-----------------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------

// 1 - Functions to register an event handler

// those functions enables you register an event for your trigger in the same way you would do with blizzard's ones.

function TriggerRegisterCustomEvent takes trigger whichTrigger, integer EventId returns boolean
function TriggerRegisterCustomEventString takes trigger whichTrigger, string Event returns boolean

// both functions takes the handler has the first trigger argument

// The first function takes an integer for the event id to be handled by the trigger.
// It's meant to be a constant used here. Here is a sample.
constant integer GenericErrorCode = StringHash("GenericError")
// So, it's easier to avoid clashes with names

// The second function takes a string as parameter,
// so you don't need to use a constant or cast the string yourself
// Your line will looks shorter.
// If you enable inlining, you won't loss efficiency

// the functions will return false if the trigger is already bound to the event

// Once a event is triggered, you can check the event with
function GetEventId takes nothing returns integer
// Then, you may use the triggerer's function/globals to gather data

// Whenever an event is registered, a TriggerRegisteredAnyEvent event is sent.
// here is the code :
constant integer TriggerRegisteredAnyEventCode = StringHash("TriggerRegisteredAnyEvent")
// Another specific event is sent. Register it with the following line :
TriggerRegisterCustomEventString(trigger, "TriggerRegisteredEvent" + I2S(EVENT_ID))
// you can also retrieve EVENT_ID by StringHash(EVENT_NAME)
// then retrieve data with :
function GetRegisteringTrigger takes nothing returns trigger
function GetRegisteredEventId takes nothing returns integer

//-----------------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------

// 2 - functions to unregister an event handler

// those functions simply unregister an event for a trigger, so it won't fire when the event will be summoned again

function TriggerUnregisterCustomEvent takes trigger whichTrigger, integer EventId returns boolean
function TriggerUnregisterCustomEventString takes trigger whichTrigger, string Event returns boolean

// Those functions works same as the registering ones.
// But they'll return false if the trigger isn't bound or if an error happened
// if an error happens, an EventManagerError will be triggered. Use the function below for more details on the error

function GetEventManagerError takes nothing returns string

// an event is sent, like the one sent by TriggerRegisterCustomEvent :
constant integer TriggerRegisteredAnyEventCode = StringHash("TriggerUnregisteredAnyEvent")
// special event line :
TriggerRegisterCustomEventString(trigger, "TriggerUnregisteredEvent" + I2S(EVENT_ID))
// data functions :
function GetUnregisteringTrigger takes nothing returns trigger
function GetUnregisteredEventId takes nothing returns integer

//-----------------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------

// 3 - function to trigger an event

// those functions cause the system firing all the trigger registered with the specified event id

function TriggerCustomEvent takes integer EventId returns boolean
function TriggerCustomEventString takes string Event returns boolean

// You just give as an argument the event id/name.
// the function will return false if there is no handler for this event

// You may give your own data with globals.

// The following function will trigger a GenericError event, and put message into the string GenericError.
// It's just to trigger easily error, in one meaningful line.
function TriggerError takes string message returns boolean

//-----------------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------

// 4 - checking functions

// those functions allows you to check a register state

// returns true if the trigger has registered the event, false else
function IsRegisteredEvent takes trigger whichTrigger, integer EventId returns boolean
function IsRegisteredEventString takes trigger whichTrigger, string Event returns boolean

// returns true if the event have registered triggers, false else
function HasRegisteredTriggers takes integer EventId returns boolean
function HasRegisteredTriggersString takes string Event returns boolean
JASS:
//! textmacro AutoEnable takes TRIGGER, EVENT, ALLOWDISABLE, DOINIT

scope AutoEnable$TRIGGER$ initializer InitTrig_Auto_Enable_$TRIGGER$

    globals
        private trigger Auto_Enable_$TRIGGER$ = CreateTrigger()
        private trigger Auto_Disable_$TRIGGER$ = CreateTrigger()
    endglobals
    
    function Trig_Auto_Enable_$TRIGGER$_Actions takes nothing returns nothing
        call EnableTrigger(gg_trg_$TRIGGER$)
        call EnableTrigger(Auto_Disable_$TRIGGER$)
        call DisableTrigger(Auto_Enable_$TRIGGER$)
        
        static if $DOINIT$ then
            call InitTrig_$TRIGGER$()
        endif
    endfunction

    function Trig_Auto_Disable_$TRIGGER$_Actions takes nothing returns nothing
        if not HasRegisteredTriggers($EVENT$) then
            call DisableTrigger(gg_trg_$TRIGGER$)
            call DisableTrigger(Auto_Disable_$TRIGGER$)
            call EnableTrigger(Auto_Enable_$TRIGGER$)
        endif
    endfunction

    //===========================================================================
    function InitTrig_Auto_Enable_$TRIGGER$ takes nothing returns nothing
        
        call TriggerRegisterCustomEventString(Auto_Enable_$TRIGGER$, "TriggerRegisteredEvent" + I2S($EVENT$))
        
        call TriggerAddAction( Auto_Enable_$TRIGGER$, function Trig_Auto_Enable_$TRIGGER$_Actions )
        
        static if $ALLOWDISABLE$ then
            call TriggerRegisterCustomEventString(Auto_Disable_$TRIGGER$, "TriggerUnregisteredEvent" + I2S($EVENT$))
        
            call TriggerAddAction( Auto_Disable_$TRIGGER$, function Trig_Auto_Disable_$TRIGGER$_Actions )
            
            if not HasRegisteredTriggers($EVENT$) then
                call DisableTrigger(Auto_Disable_$TRIGGER$)
            endif
        endif
    endfunction

endscope

//! endtextmacro
JASS:
library AnyUnitDamaged requires EventManager

    globals
        unit source = null
        unit target = null
        real amount = 0
        integer AnyUnitDamagedCode = StringHash("AnyUnitDamaged")
    endglobals

    function Trig_AnyUnitDamaged_Actions takes nothing returns nothing
        if GetTriggerEventId() == EVENT_UNIT_DAMAGED then
            set source = GetEventDamageSource()
            set target = GetTriggerUnit()
            set amount = GetEventDamage()
            call TriggerCustomEvent(AnyUnitDamagedCode)
        else
            call TriggerRegisterUnitEvent( gg_trg_AnyUnitDamaged, GetTriggerUnit(), EVENT_UNIT_DAMAGED )
        endif
    endfunction
    
    //===========================================================================
    function InitTrig_AnyUnitDamaged takes nothing returns nothing
        local region r = null
        local group g = null
        local unit u = null
        
        if HasRegisteredTriggers(AnyUnitDamagedCode) then
            set r = CreateRegion()
            set gg_trg_AnyUnitDamaged = CreateTrigger(  )
            
            set g = GetUnitsInRectMatching(bj_mapInitialPlayableArea, null)
            
            loop
                set u = FirstOfGroup(g)
                exitwhen u == null
                call GroupRemoveUnit(g, u)
                call TriggerRegisterUnitEvent( gg_trg_AnyUnitDamaged, u, EVENT_UNIT_DAMAGED )
            endloop
            
            call RegionAddRect(r, bj_mapInitialPlayableArea)
            call TriggerRegisterEnterRegion(gg_trg_AnyUnitDamaged, r, null)
            
            set g = null
            set u = null
            set r = null
            
            call TriggerAddAction( gg_trg_AnyUnitDamaged, function Trig_AnyUnitDamaged_Actions )
        endif
    endfunction
    
endlibrary

//! runtextmacro AutoEnable ("AnyUnitDamaged", "AnyUnitDamagedCode", "false", "true")
JASS:
//! textmacro EventEmulator takes FUNCTION, NAME

scope EventEmulator$NAME$ initializer InitTrig_event_emulator_$NAME$

    globals
        constant integer EmulatedEventId = StringHash("$NAME$")
        constant trigger event_emulator_$NAME$ = CreateTrigger()
    endglobals

    function Trig_event_emulator_$NAME$_Actions takes nothing returns nothing
        call TriggerCustomEvent(EmulatedEventId)
    endfunction

    //===========================================================================
    function InitTrig_event_emulator_$NAME$ takes nothing returns nothing
        call $FUNCTION$
        
        call TriggerAddAction( event_emulator_$NAME$, function Trig_event_emulator_$NAME$_Actions )
    endfunction
    
endscope
//! endtextmacro

Keywords:
Event, Manage, Manager, User event, Custom, Trigger, Triggering, User defined
Contents

Event Manager 1.0f2 (Map)

Reviews
22:14, 2nd Jan 2010 TriggerHappy: This looks like overkill compared to this. And I disagree with the need for a hashtable, but this is approvable.

Moderator

M

Moderator

22:14, 2nd Jan 2010
TriggerHappy:

This looks like overkill compared to this.

And I disagree with the need for a hashtable, but this is approvable.
 
Level 6
Joined
Jun 4, 2009
Messages
91
well, suppose you created a system. Your system doesn't need user intervention when runing (maybe for setup), and do background stuff (I got in mind one of the several equipment system. But this can be used as well with the cooking system I saw time ago).

This system allows you to notice the library's user whenever you do something (and to react) by triggering a custom event. So, the user just need to register your events to his triggers whenever he want (mostly on Init).
Then, everytime you call TriggerCustomEventString(your_event_name), all trigger which registered this event will be fired (when a cook starts/end, for sample). If you want to allow the user having more informations, like which is the unit (or anything else), just use globals.

For further information on how to use, please read the in-game doc.
Read also samples for advanced use tips.

Hope you'll enjoy my system.
 
Level 6
Joined
Jun 4, 2009
Messages
91
there is how to (basically) use in GUI.

  • Custom script: call TriggerCustomEventString("EventName")
  • Custom script: call TriggerRegisterCustomEventString(gg_trg_TRIGGERNAME, "EventName")
Of course, there are more function to be used, but they are explained into the doc.
 
Level 6
Joined
Jun 4, 2009
Messages
91
And please decide another prefix, ROC makes it seem like it's compatible with Reign of Chaos.
It's compatible with Reign of Chaos (extension is .w3m and not .w3x)

* Inline HasRegisteredTriggers, IsRegisteredEvent.
* TriggerList could just be an array.
* You should also check if the passed trigger is null or not.
updated so.

But, I don't see how to use a single array for TriggerList
IsRegisteredEvent would need to swap arguments to work

This looks like overkill compared to this.
This system doesn't do the same job: this system provides static event.
Mine was created with dynamic use in mind. Here are some dynamics event fired by the core:
"TriggerRegisteredEvent" + I2S(EventId)
"TriggerUnregisteredEvent" + I2S(EventId)

You may create a function like this:
JASS:
function LookForUnitToDoSomething takes trigger t, unit u returns boolean
    return TriggerRegisterCustomEventString(t, "Unit"+GetHandleId(u)+"DoSomething")
endfunction

And use this one in your code:
JASS:
call TriggerEventString("Unit"+GetHandleId(unit)+"DoSomething")


In latest version, I also fixed a minor bug with AnyUnitDamaged
 
Level 9
Joined
Nov 4, 2007
Messages
931
I cant for the life of me figure out why I keep getting a compile error in your system, this only happens after I put in the AnyUnitDamaged trigger -
JASS:
//===========================================================================
//TESH.scrollpos=33
//TESH.alwaysfold=0

//textmacro instance: AutoEnable ("AnyUnitDamaged", "AnyUnitDamagedCode", "false", "true")//===========================================================================

// scope AutoEnableAnyUnitDamaged begins

    
    function Trig_Auto_Enable_AnyUnitDamaged_Actions takes nothing returns nothing
        call EnableTrigger(gg_trg_AnyUnitDamaged)
        call EnableTrigger(AutoEnableAnyUnitDamaged___Auto_Disable_AnyUnitDamaged)
        call DisableTrigger(AutoEnableAnyUnitDamaged___Auto_Enable_AnyUnitDamaged)
        
        static if true then //Syntax Error at step 2 Structs on this line
            call Init_AnyUnitDamaged()
        endif
    endfunction

    function Trig_Auto_Disable_AnyUnitDamaged_Actions takes nothing returns nothing
        if not HasRegisteredTriggers(AnyUnitDamagedCode) then
            call DisableTrigger(gg_trg_AnyUnitDamaged)
            call DisableTrigger(AutoEnableAnyUnitDamaged___Auto_Disable_AnyUnitDamaged)
            call EnableTrigger(AutoEnableAnyUnitDamaged___Auto_Enable_AnyUnitDamaged)
        endif
    endfunction

    //===========================================================================

Edit 1: OK now its getting weirder, deleted the map that had the system, downloaded it again, opened editor, saved it onto itself and again got this error, I have no idea whats going on.

Edit 2: Fixed the problem by updating JH.
 
Last edited:
Top