• 🏆 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!

[Snippet] Trigger Manager

Level 11
Joined
Dec 3, 2011
Messages
366
CHANGELOG
- Now, this system will automatic index actions/conditions handle.
- Change some API.

JASS:
library TriggerManager requires Table
/*
        Credit:
            Bribe - Table ( [url]http://www.hiveworkshop.com/forums/jass-resources-412/snippet-new-table-188084/[/url] )

        Description: A snippet which allows to control triggers easier.
            * Pros:
                + Can set a custom data to trigger.
                + Easy to control trigger actions and conditions.
                + Automatic index actions/conditions handle
                
    ---------------------------------------------------------------------------------------------------------------------------------
    |    struct Trigger
    |        static method create takes integer data returns Trigger
    |           Create the trigger and give it a data
    |            
    |        method destroy takes nothing returns nothing
    |            Destroy it.
    |            
    |        method operator trigger takes nothing returns trigger
    |            Return trigger that you have created.
    |            
    |        method operator data takes nothing returns integer
    |            Return trigger's data.
    |            
    |        static method operator [] takes trigger t returns Trigger
    |            Takes a trigger which have been created by this struct to return Trigger.
    |            
    |        method addAction takes code func returns integer handle
    |            Add action to trigger and return this action handle. This handle will be used on removeAction.
    |
    |        method replaceAction takes code func, integer handle returns nothing
    |            Replace old action with a new action.
    |
    |        method removeAction takes integer handle returns nothing
    |            Remove action.
    |            
    |        method addCondition takes code func returns integer handle
    |            Add condition to trigger and return this condition handle. This handle will be used on removeCondition.
    |            
    |        method replaceCondition takes code func, integer handle returns nothing
    |            Replace old condition with a new condition.
    |
    |        method removeCondition takes integer handle returns nothing
    |            Remove condition.
    |            
    |        method enable takes nothing returns nothing
    |            Turn on the trigger.
    |            
    |        method disable takes nothing returns nothing
    |            Turn off the trigger.
    |            
    |        method clearActions takes nothing returns nothing
    |            Clear all actions.
    |            
    |        method clearConditions takes nothing returns nothing
    |            Clear all conditions.
    |            
    |        method clear takes nothing returns nothing
    |            Clear all actions and conditions.
    ---------------------------------------------------------------------------------------------------------------------------------
*/  
    struct Trigger

        private static Table TriggerTable
        
        private static integer ActionCounter = 0
        private static integer ConditionCounter = 0
        private static integer array ActionRecycler
        private static integer array ConditionRecycler
        
        static method [] takes trigger t returns thistype
            return TriggerTable.integer[GetHandleId(t)]
        endmethod
        
        method operator data takes nothing returns integer
            return TriggerTable.integer[this]
        endmethod
        
        method operator trigger takes nothing returns trigger
            return TriggerTable.trigger[this]
        endmethod
        
        method destroy takes nothing returns nothing
            call DestroyTrigger(trigger)
            call TriggerTable[this].flush()
            call deallocate()
        endmethod
        
        method clearActions takes nothing returns nothing
            call TriggerClearActions(trigger)
        endmethod
        
        method clearConditions takes nothing returns nothing
            call TriggerClearConditions(trigger)
        endmethod
        
        method clear takes nothing returns nothing
            call clearActions()
            call clearConditions()
        endmethod
        
        method replaceAction takes code func, integer i returns nothing
            call TriggerRemoveAction(trigger,TriggerTable[this].triggeraction[i])
            set TriggerTable[this].triggeraction[i] = null
            set TriggerTable[this].triggeraction[i] = TriggerAddAction(trigger,func)
        endmethod
        
        method replaceCondition takes code func, integer i returns nothing
            call TriggerRemoveCondition(trigger,TriggerTable[this].triggercondition[i])
            set TriggerTable[this].triggercondition[i] = null
            set TriggerTable[this].triggercondition[i] = TriggerAddCondition(trigger,Filter(func))
        endmethod
        
        method removeAction takes integer i returns nothing
            set ActionRecycler[0] = ActionRecycler[this]
            set ActionRecycler[0] = this
            call TriggerRemoveAction(trigger,TriggerTable[this].triggeraction[i])
            set TriggerTable[this].triggeraction[i] = null
        endmethod
        
        method removeCondition takes integer i returns nothing
            set ConditionRecycler[0] = ConditionRecycler[this]
            set ConditionRecycler[0] = this
            call TriggerRemoveCondition(trigger,TriggerTable[this].triggercondition[i])
            set TriggerTable[this].triggercondition[i] = null
        endmethod
        
        method addAction takes code func returns integer
            local integer result = ConditionRecycler[0]
            if result == 0 then
                set result = ActionCounter + 1
                set ActionCounter = result
            else
                set ActionRecycler[0] = ActionRecycler[result]
            endif
            set TriggerTable[this].triggeraction[result] = TriggerAddAction(trigger,func)
            return result
        endmethod
        
        method addCondition takes code func returns integer
            local integer result = ConditionRecycler[0]
            if result == 0 then
                set result = ConditionCounter + 1
                set ConditionCounter = result
            else
                set ConditionRecycler[0] = ConditionRecycler[result]
            endif
            set TriggerTable[this].triggercondition[result] = TriggerAddCondition(trigger,Filter(func))
            return result
        endmethod
        
        method enable takes nothing returns nothing
            call EnableTrigger(trigger)
        endmethod
        
        method disable takes nothing returns nothing
            call DisableTrigger(trigger)
        endmethod
        
        static method create takes integer data returns thistype
            local thistype this = allocate()
            
            if TriggerTable[this] == null then
                set TriggerTable[this] = Table.create()
            endif
            
            set TriggerTable.trigger[this] = CreateTrigger()
            
            set TriggerTable.integer[this] = data
            
            set TriggerTable.integer[GetHandleId(trigger)] = this
            
            return this
        endmethod
        
        private static method onInit takes nothing returns nothing
            set TriggerTable = Table.create()
        endmethod
    endstruct
endlibrary

Test map:
View attachment Trigger Manager 1.0 .w3m
 

Attachments

  • Trigger Manager Test Map.w3x
    30.4 KB · Views: 88
  • Trigger Manager Test.w3m
    29.8 KB · Views: 64
Last edited:

Bannar

Code Reviewer
Level 26
Joined
Mar 19, 2008
Messages
3,140
Some of your methods do not wrap trigger's api properly i.e the returned value isn't there.

Also, your sleep method:
JASS:
method sleep takes boolean flag returns nothing
    if ( TriggerTable.boolean[this] != flag ) then
        set TriggerTable.boolean[this] = flag

        if flag then
            call DisableTrigger(trigger)
        else
            call EnableTrigger(trigger)
        endif
    endif
endmethod
Why would you use such trigger wrapper anyway? This provides no additional functionality, just slowers the op due to table involvement.

The idea about referencing actions via integer arguments seems wierd. It's much better to stick with the list.
 
Level 11
Joined
Dec 3, 2011
Messages
366
Some of your methods do not wrap trigger's api properly i.e the returned value isn't there.

Also, your sleep method:
JASS:
method sleep takes boolean flag returns nothing
    if ( TriggerTable.boolean[this] != flag ) then
        set TriggerTable.boolean[this] = flag

        if flag then
            call DisableTrigger(trigger)
        else
            call EnableTrigger(trigger)
        endif
    endif
endmethod
Why would you use such trigger wrapper anyway? This provides no additional functionality, just slowers the op due to table involvement.

The idea about referencing actions via integer arguments seems wierd. It's much better to stick with the list.

The first time I wrote this system I stick with the list but I think it's hard to manage and that's the reason I use integer.

I will separate sleep method into 2 method.

P/s: Thank you :lol:
 

Kazeon

Hosted Project: EC
Level 33
Joined
Oct 12, 2011
Messages
3,449
JASS:
        method addAction takes code func, @integer i@ returns nothing
            call removeAction(i)
            set TriggerTable[this].triggeraction[i] = TriggerAddAction(trigger,func)
        endmethod

Sorry, what kind of integer is that? If user need to set the index by themselves, there will be a huge chance for them to mess things up (e.g. if user use same index as before, node inside the table with that index will be replaced, user can somehow remove the wrong action/condition /even though it's a rarish case/. You know we use a huge amount of triggers action/condition in a map, we can't keep track all of indexes all the time)

So my suggestion is, do the indexing automatically, make the function returns the index:
JASS:
        method addAction takes code func returns integer
            @call removeAction(i)@ // Remove this and make a separated function
            set counter = counter + 1
            set TriggerTable[this].triggeraction[counter] = TriggerAddAction(trigger,func)
            return counter // Return the index
        endmethod

JASS:
        method replaceAction takes integer index, code func returns nothing
            call removeAction(index)
            set TriggerTable[this].triggeraction[index] = TriggerAddAction(trigger,func)
        endmethod


Not sure tho, my suggestion above is about system safety. But you know the system better than me so decision is on you :wink:
 
Level 11
Joined
Dec 3, 2011
Messages
366
JASS:
        method addAction takes code func, @integer i@ returns nothing
            call removeAction(i)
            set TriggerTable[this].triggeraction[i] = TriggerAddAction(trigger,func)
        endmethod

Sorry, what kind of integer is that? If user need to set the index by themselves, there will be a huge chance for them to mess things up (e.g. if user use same index as before, node inside the table with that index will be replaced, user can somehow remove the wrong action/condition /even though it's a rarish case/. You know we use a huge amount of triggers action/condition in a map, we can't keep track all of indexes all the time)

So my suggestion is, do the indexing automatically, make the function returns the index:
JASS:
        method addAction takes code func returns integer
            @call removeAction(i)@ // Remove this and make a separated function
            set counter = counter + 1
            set TriggerTable[this].triggeraction[counter] = TriggerAddAction(trigger,func)
            return counter // Return the index
        endmethod

JASS:
        method replaceAction takes integer index, code func returns nothing
            call removeAction(index)
            set TriggerTable[this].triggeraction[index] = TriggerAddAction(trigger,func)
        endmethod


Not sure tho, my suggestion above is about system safety. But you know the system better than me so decision is on you :wink:

K, I'll try to make some changes in the system. Your ideas is quite good.:ogre_haosis:

Thank you so much :grin:
 
Level 19
Joined
Mar 18, 2012
Messages
1,716
First of all I vote for gy'd this. No extra functionality, Table slows down all operations.
Table API is not used correctly. TriggerActions should be avoided (nearly always),
especially for dynamic triggers.

JASS:
        private static method onInit takes nothing returns nothing
            set TriggerTable = Table.create()
        endmethod
Will not work, when resources using this will use a module initializer.

JASS:
            if TriggerTable[this] == null then
                set TriggerTable[this] = Table.create()
            endif
TriggerTable is a static Table instance, method operator [] takes trigger.
Does this even compile?

JASS:
set TriggerTable.integer[this] = data
I should be able to change trigger data dynamically.
Give me an example where I can use this stored integer.
Why not just fire an Event associated with an event index.
somethin like fire(eventTrigger, 1)



JASS:
set TriggerTable[this].triggeraction[i] = null
Is not a valid hashtable/Table API. You have to use table.handle.remove(this)
This however will remove all handles stored on this instance.
We can use HaveStoredInteger/Real/Boolean/String/Handle

trigger replace condition??

destroy should support clear actions/conditions by default.

I don't see a benefit from this snippet.
 
Top