Snippet Trigger

Nestharus

o-o
Reaction score
84
Introduction
Essentially does this, but safely, meaning you can't remove triggerconditions from triggers where the triggercondition is actually on a different trigger or something.
JASS:
integer count = 0
trigger t = CreateTrigger()

//onAdd
set count = count + 1
call TriggerAddCondition(t, c)

//onRemove
set count = count - 1
call TriggerRemoveCondition(t, tc)

//onEvaluate
if count > 0 then
    call TriggerEvaluate(t)
endif


So that you can do this to save an evaluation if the trigger doesn't have code in it
JASS:
Trigger t = Trigger.create()
integer tc

//onAdd
set tc = t.add(c)

//onRemove
call t.remove(tc)

//onEvaluate
if (t.hasCode) then
    call t.fire()
endif

JASS:
library Trigger
//v2.0.1.0
//Trigger is used to evaluate a trigger if that trigger has code in it.
//It can safely add/remove code from triggers.
//
//-module TriggerMod
//      Implement this to create your own Trigger struct
//
//      -static method create takes nothing returns thistype
//          Creates a trigger.
//
//      -method destroy takes nothing returns nothing
//          Destroys trigger.
//
//      -method add takes boolexpr c returns integer
//          Adds code to trigger.
//
//      -method remove takes integer c returns nothing
//          Removes code from trigger.
//
//      -method operator hasCode takes nothing returns boolean
//          Returns a boolean determining whether the trigger has code in it or not.
//
//      -method clear takes nothing returns nothing
//          Clears all code out of trigger.
//
//      -method fire takes nothing returns boolean
//          Fires the trigger.
//
//struct Trigger
//  Shared Trigger struct. Implements TriggerMod.
    globals
        private hashtable table = InitHashtable()
        private integer triggerType = 0
    endglobals
    
    module TriggerMod
        private static integer instanceCountE = 0
        private static integer array recycleE
        private trigger t
        private integer countX
        private static integer recycleCountE = 0
        private static integer thisType = 0
        private boolean allocated
        
        private integer instanceCount
        private integer recycleCount
        
        public method operator hasCode takes nothing returns boolean
            return countX != 0
        endmethod
        
        public method fire takes nothing returns boolean
            return TriggerEvaluate(t)
        endmethod
        
        public static method create takes nothing returns thistype
            if (recycleCountE != 0) then
                set recycleCountE = recycleCountE - 1
                set thistype(recycleE[recycleCountE]).allocated = true
                return recycleE[recycleCountE]
            endif
            set instanceCountE = instanceCountE + 1
            set thistype(instanceCountE).allocated = true
            set thistype(instanceCountE).t = CreateTrigger()
            return instanceCountE
        endmethod
        
        public method destroy takes nothing returns nothing
            if (allocated) then
                call TriggerClearConditions(t)
                set countX = 0
                set recycleE[recycleCountE] = this
                set recycleCountE = recycleCountE + 1
                call FlushChildHashtable(table, thisType*8192+this)
                call FlushChildHashtable(table, -thisType*8192-this)
                set instanceCount = 0
                set recycleCount = 0
                set allocated = false
            endif
        endmethod
        
        public method clear takes nothing returns nothing
            if (allocated) then
                set countX = 0
                set instanceCount = 0
                set recycleCount = 0
                call TriggerClearConditions(t)
                call FlushChildHashtable(table, thisType*8192+this)
                call FlushChildHashtable(table, -thisType*8192-this)
            endif
        endmethod
        
        public method add takes boolexpr c returns thistype
            local thistype tc = 0
            if (allocated and c != null) then
                if (recycleCount != 0) then
                    set tc = LoadInteger(table, -thisType*8192-this, recycleCount)
                    set recycleCount = recycleCount - 1
                else
                    set instanceCount = instanceCount + 1
                    set tc = instanceCount
                endif
                
                set countX = countX + 1
                call SaveTriggerConditionHandle(table, thisType*8192+this, tc, TriggerAddCondition(t, c))
            endif
            
            return tc
        endmethod
        
        public method remove takes thistype c returns nothing
            local triggercondition tc = LoadTriggerConditionHandle(table, thisType*8192+this, c)
            if (allocated and tc != null) then
                call TriggerRemoveCondition(t, tc)
                set countX = countX - 1
                call RemoveSavedHandle(table, thisType*8192+this, c)
                call SaveInteger(table, -thisType*8192-this, recycleCount, c)
                set recycleCount = recycleCount + 1
            endif
        endmethod
        
        private static method onInit takes nothing returns nothing
            set thisType = triggerType
            set triggerType = triggerType + 1
        endmethod
    endmodule
    
    struct Trigger extends array
        implement TriggerMod
    endstruct
endlibrary
 

Nestharus

o-o
Reaction score
84
Extremely simple.. lol

JASS:

//Trigger is used to evaluate a trigger if that trigger has code in it
//It has double free protection on code add/removal


so like..

JASS:

if (trig.hasCode) then
    call trig.fire()
endif


and that's about it.

double free on removal talks about removing code from a trigger (like TriggerRemoveCondition()). This means if you remove code that doesn't exist from a trigger, it won't fudge up.

Standard way of doing this lib is something like

JASS:

integer count = 0
trigger t = CreateTrigger()

//onAdd
set count = count + 1
call TriggerAddCondition(t, c)

//onRemove
set count = count - 1
call TriggerRemoveCondition(t, tc)


Then you can add safety by checking if c/tc are null and checking if count > 0 on remove. Obviously that can still cause issues if you are trying to remove a triggercondition from a trigger that doesn't even have that triggercondition.

That is why I made this library : P.
 

kingkingyyk3

Visitor (Welcome to the Jungle, Baby!)
Reaction score
216
I don't think this is useful unless you add ways to kill double free of handles that caused trigger action.
 

Nestharus

o-o
Reaction score
84
I am only going to support triggerconditions as triggeractions should not be used under any circumstance ; D.

trigger actions are slower, they can cause leaks, and etc... they are riddled with problems. I never use them and you shouldn't either : P.
 

Tyman2007

Ya Rly >.
Reaction score
74
I'm not too good with jass.. but wouldn't it be
better to use [ljass]static if (trig.hasCode) then[/ljass] than
[ljass]if (trig.hasCode) then[/ljass] ?

of course I'm talking more about the usage than the system itself..

Meh.. I'm either horribly wrong or showing off my perfectionist..ism.. stuff... Meh I'm just posting for somethint to do :p

but I'm a bit with the others.. Can you post a realistic common example of when this would actually be very useful instead of just cutting back on a couple of seconds of scripting which would probably not happen because of the time to implement the script in the first place..
 

Nestharus

o-o
Reaction score
84
[ljass]static if[/ljass] would not be appropriate because hasCode is not a constant... lol : P...

I actually use this in UnitIndexer ; D.

JASS:
//
        private Trigger onIndex
        private Trigger onDeindex
        private Trigger onReplace


It's used with the custom events. The triggers are only evaluated if they have code on them.

JASS:
//
                if (onDeindex.hasCode) then
                    call onDeindex.fire()
                endif


And add/removal is just stuff like
JASS:
//
    function OnReplaceUnit takes integer index, boolexpr c returns integer
        return onReplace.add(c)
    endfunction
    
    function RemoveOnReplaceUnit takes integer i returns nothing
        call onReplace.remove(i)
    endfunction


I wanted to only evaluate the triggers if they had code on them. I originally was using a counter but I wanted to make it 100% safe on removal, so I created the Trigger snippet to do so. The Trigger snippet actually made Unit Indexer events a lot more simple to code as well : ).

Look through the basic code of this snippet and ask yourself if you'd want to code that from scratch for every single event you did given you want to save a trigger evaluation if the trigger has no code in it. Look at the example on first thread and ask yourself if you'd even want to code that much for every single event. Keep in mind if you don't code it for every single event (not static), it might as well be a little snippet like this to reduce coupling : P.
 

Tyman2007

Ya Rly >.
Reaction score
74
Well, I guess that would be logical, but one thing though..

I don't really know of too many maps that would ever use that many custom events let alone fully Jass triggers :p

It's a neat system, but my maps don't have enough triggers of the sort to use this system. So for that I won't use it, but I will +rep because it still is useful to avid coders.
 

SanKakU

Member
Reaction score
21
glanced over the comments and i have a question. i'm confused about...well...

do you use blank triggers? 'triggers without code in them' - what does that mean?

what do you use them for if you use these blank triggers?
 

Nestharus

o-o
Reaction score
84
v2.0.0.0 is up with more functionality ; ).

Only has one hashtable now and because of the new functionality does not have a USE_HASHTABLE boolean anymore.

edit
glanced over the comments and i have a question. i'm confused about...well...

do you use blank triggers? 'triggers without code in them' - what does that mean?

what do you use them for if you use these blank triggers?

The triggers have trigger conditions added to them, right? This library lets you see if a trigger has trigger conditions in it or not. If a trigger has no trigger conditions, you obviously don't want to evaluate it as nothing would happen : P.

This library lets you check to see if a trigger has trigger conditions in it while safely adding/removing trigger conditions.

Again, look at the example at the very top.

JASS:

if count > 0 then
    call TriggerEvaluate(t)
endif
 

Nestharus

o-o
Reaction score
84
This is totally useless. :(

I use it for everything.. whenever I make custom events, I always check to see if they have conditions in them or not before evaluating them. I don't find that to be useless ; D.

This has actually been a lifesaver for me for all custom events ^.^
 

Jesus4Lyf

Good Idea™
Reaction score
397
Instead of twitching and trying to figure out why you'd
  1. optimise for least common scenario, and degrade performance for most common scenario; and
  2. think this saves any lines of code, which is the real irony, and that...
  3. eyetwitch1.gif
    THIS IS SO INEFFICIENT!
I'm gonna give up, wait for your response to see if it makes anything clearer, and move for graveyarding it. -_-
 

Nestharus

o-o
Reaction score
84
I guess evaluating a trigger every time even when it is empty is ok.. I'll update everything then.
 

Jesus4Lyf

Good Idea™
Reaction score
397
The last benchmark by SFilip portrayed that a TriggerExecute was roughly the same as a DoNothing function, if there were no actions on the trigger. I can't imagine how unsubstantial a TriggerEvalaute is.

Nestharus, do some benchmarking, for goodness' sakes.
eyetwitch1.gif


Edit: Wait, just don't - I'll have to read your benchmark code as well, then. And deal with more of "everything I say is right". =/
On an irrelevant note: Graveyarded. :)
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top