System GTrigger Event System

Romek

Super Moderator
Reaction score
963
Will this see 'Any Unit Events'.. Ever? :p
 

Tru_Power22

You can change this now in User CP.
Reaction score
144
Thats not an advantage.
Why would you EVER want to remove an event?

To prevent leaks?

If your attaching event to units that enter the map, they will leak unless you can remove them. This provides an easy way of doing that.
 

Troll-Brain

You can change this now in User CP.
Reaction score
85
We can't simply press SHIFT and then edit and type a space then press ok? At least for somethings that work like names. There used to be tests done in which you can actually code straight from the object editor pretty much, but it just did not turn out too well.

You can define your own rawcode with newgen when you create a custom object on the object editor (unit,item,ability and so one ...), but you have to use 4 ASCII characters and can't use all of them, including NULL.
Transform the object file in a .slk and edit it doesn't help.
So therefore you can make mathematics links between rawcodes but not easy ones, at least only annoying ones.
 

Deaod

Member
Reaction score
6
To prevent leaks?
Seeing as this registers events ONCE and runs all functions registered to that event off of that one, this is void. You dont actually prevent any leaks (at least not the ones you think it does).

Portraying highly opinionated comments as absolute truth leads to flame wars (please don't).
Now guess why i put "proper" into quotes.

I consider this proper - I provide an intuitive (JASS style) event interface
Well, ive forgotten the function key word used in code variables very often (even before i knew about function interfaces), so id venture to say that function interfaces are more intuitive (let me stress that this is my POV). Also, having to return false inside the registered functions looks counter intuitive to me.

which is more efficient than the alternative interface you propose.
Well. You use simple modulo hashing. That claim depends on the number of collisions. I think that already a single collision could make your way slower than simply using hashtables (for the colliding abilities, and even there only for the one added later). So its probably (marginally) faster most of the time.

You should be looking at SpellStruct
Want me to comment on that one?
 

kingkingyyk3

Visitor (Welcome to the Jungle, Baby!)
Reaction score
216
That claim depends on the number of collisions
Rawcodes are big. >< I did not faced collision problem for modulo hashing it so far.
 

Jesus4Lyf

Good Idea™
Reaction score
397
I think that already a single collision could make your way slower than simply using hashtables
I was referring to function interfaces, really.
Want me to comment on that one?
Feedback is always appreciated, if it can bring about improvements... :D
 

kingkingyyk3

Visitor (Welcome to the Jungle, Baby!)
Reaction score
216
JASS:
library Test initializer Init

    globals
        private constant integer MAX_TRIGGERS = 8191
    endglobals
    
    private struct Node[MAX_TRIGGERS]
        thistype prev
        thistype next
        trigger trig
        
        static method create takes nothing returns thistype
            local Node this = Node.allocate()
            set .prev = this
            set .next = this
            return this
        endmethod
    endstruct 
    
    globals
        private integer Pid = 0 //locals
        private hashtable LinkedListDatabase
    endglobals
    
    //! textmacro Test_Register takes NAME, EVENT, OBJECT
    globals
        private key $NAME$Key
        private trigger $NAME$Trig
    endglobals
    
    function Register$NAME$ takes integer abilId, trigger trig returns trigger
        local Node head = LoadInteger(LinkedListDatabase,$NAME$Key,abilId)
        local Node node
        if head == 0 then
            set head = Node.create()
            call SaveInteger(LinkedListDatabase,$NAME$Key,abilId,head)
        endif
        set node = Node.create()
        set node.prev = head.prev
        set head.prev.next = node
        set head.prev = node
        set node.trig = trig
        return trig
    endfunction
    
    function Register$NAME$Action takes integer abilId, code func returns nothing
        call TriggerAddCondition($NAME$Trig,Condition(func))
    endfunction
    
    private function $NAME$Handler takes nothing returns boolean
        local Node head = LoadInteger(LinkedListDatabase,$NAME$Key,$OBJECT$)
        loop
            set head = head.next
        exitwhen head == 0
            if TriggerEvaluate(head.trig) then
                call TriggerExecute(head.trig)
            endif
        endloop
        return false
    endfunction
    
    private function Init$NAME$ takes nothing returns nothing
        set $NAME$Trig = CreateTrigger()
        set Pid = 0
        loop
            call TriggerRegisterPlayerUnitEvent($NAME$Trig,Player(Pid),$EVENT$,null)
            set Pid = Pid + 1
        exitwhen Pid == bj_MAX_PLAYER_SLOTS
        endloop
    endfunction
    //! endtextmacro
    //! runtextmacro Test_Register (&quot;SpellEffectEvent&quot;, &quot;EVENT_PLAYER_UNIT_SPELL_EFFECT&quot;, &quot;GetSpellAbilityId()&quot;)
    
    private function Init takes nothing returns nothing
        call InitSpellEffectEvent()
    endfunction
endlibrary

Hmm, I came up with this idea. :p
 

Jesus4Lyf

Good Idea™
Reaction score
397

kingkingyyk3

Visitor (Welcome to the Jungle, Baby!)
Reaction score
216
JASS:
function Register$NAME$Action takes integer abilId, code func returns nothing
        call TriggerAddCondition($NAME$Trig,Condition(func))
    endfunction

Yep ><.


JASS:
library Spell initializer Init
    
    //----------------
    //! textmacro Spell takes TYPE, EVENT
    globals
        private trigger array Spell$TYPE$Trig
    endglobals
    public function $TYPE$ takes integer id, code act returns nothing
        set id = id - (id / 8191) * 8191
        if Spell$TYPE$Trig[id] == null then
            set Spell$TYPE$Trig[id] = CreateTrigger()
        endif
        call TriggerAddAction(Spell$TYPE$Trig[id],act)
    endfunction
    private function $TYPE$Cond takes nothing returns boolean
        call TriggerExecute(Spell$TYPE$Trig[GetSpellAbilityId() - (GetSpellAbilityId() / 8191) * 8191])
        return false
    endfunction
    private function $TYPE$Init takes nothing returns nothing
        local trigger trig = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ(trig,EVENT_PLAYER_UNIT_SPELL_$EVENT$)
        call TriggerAddCondition(trig,Condition(function $TYPE$Cond))
    endfunction
    //! endtextmacro
    //! runtextmacro Spell (&quot;Cast&quot;, &quot;CAST&quot;)
    //! runtextmacro Spell (&quot;EndCast&quot;, &quot;ENDCAST&quot;)
    //! runtextmacro Spell (&quot;Channel&quot;, &quot;CHANNEL&quot;)
    //! runtextmacro Spell (&quot;Effect&quot;, &quot;EFFECT&quot;)
    //---------------------
    
    //---------------------
    globals
        private trigger array SpellLearnTrig
    endglobals
    public function Learn takes integer id, code cond, code act returns nothing
        set id = id - (id /8191) * 8191
        set SpellLearnTrig[id] = CreateTrigger()
        call TriggerAddCondition(SpellLearnTrig[id],Condition(cond))
        call TriggerAddAction(SpellLearnTrig[id],act)
    endfunction
    private function LearnCond takes nothing returns boolean
        local integer id = GetLearnedSkill()
        set id = id - (id / 8191) * 8191
        if TriggerEvaluate(SpellLearnTrig[id]) then
            call TriggerExecute(SpellLearnTrig[id])
        endif
        return false
    endfunction
    private function LearnInit takes nothing returns nothing
        local trigger trig = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ(trig,EVENT_PLAYER_HERO_SKILL)
        call TriggerAddCondition(trig,Condition(function LearnCond))
    endfunction
    //-----------------------
    
    private function Init takes nothing returns nothing
        call CastInit()
        call EndCastInit()
        call ChannelInit()
        call EffectInit()
        call LearnInit()
    endfunction
endlibrary

Hmm, I have this in my map. It serves me well for over 50 abilities. Just benchmarked it. It is faster than GT by 8%. I know it's functionality is bad and the interface is limited. :p
 

Jesus4Lyf

Good Idea™
Reaction score
397
It is faster than GT by 8%.
Holy crap, I didn't know GT was that good. You don't even have collision detection, or multiple event responses for each spell implemented. Just goes to show the power of hard coding.

On the other hand I don't trust your benchmarks as far as I can throw them.
 

kingkingyyk3

Visitor (Welcome to the Jungle, Baby!)
Reaction score
216
Hehe, I knew I'm evil. :)

On the other hand I don't trust your benchmarks as far as I can throw them.
I used the benchies that you posted in this thread. xD

You don't even have collision detection
I shall fix it when collision is found. So far, it serves me very well. :D
 

Romek

Super Moderator
Reaction score
963
You people are insane.. Caring about the speed of something called (mostly) at Map Init, and never frequently.
If it was 50% faster, you still probably wouldn't shave off 10 milliseconds from the loading time.
 

Azlier

Old World Ghost
Reaction score
461
GT's speed comes from how it makes firing the correct function for a spell O(1). Initialization is probably faster, but meh. Runtime speed is more important.

After all, shaving 0.0005 nanoseconds off of every spell cast is the most important thing you can do. Equivalent to saving the world three times.
 

Jesus4Lyf

Good Idea™
Reaction score
397
But this script doesn't fix lame natives spells responses events, right ?
You can't do that without allocating some place to store things like the casting unit (and remember, you can cast two spells at once - turn on immolation during starfall, for example?). This is meant to be lightweight - efficiency focus. If you want that fixed, see SpellStruct.

To be honest, those things not being "fixed" was never a problem for me in mapping...
 

Troll-Brain

You can change this now in User CP.
Reaction score
85
I have the need for the "cancel" spell event (spell was interrupted without end of cast) and "endcast" event but anyway i use my own code :p

I mean for me SpellStruct is far more useful than this.
 

SanKakU

Member
Reaction score
21
What advantage does this have over SpellEvent by Anitarf? Why doesnt this use function interfaces? Why doesnt it use Table to map AbilityIDs to triggers/functions (which would, now that we have hashtables, be the faster way)?

well...don't know much about spellevent but i think GT has more triggerregister options...last i checked spellevent only has 5?

also...PLEASE DO NOT POST LIKE YOU DID IN RESPONDING to Jesus4Lyf...It's very hard to read what you write when it's all broken up like that between so many of his quotes(it's the same post that you quoted over and over again for crying out loud...what you did is not only more difficult for you, but for the onlookers as well)...plus it's annoying to look at and makes you look like you have a too high opinion of yourself...

at least do that thing where they do this...

>Quote
Response

that way at least there isn't all that crazy extra space and boxes... but this is just my preference...just letting you know, i'm probably not going to read those kinds of posts because after awhile they get boring since about 50 percent of it i've already read. and almost another 50 percent seems to be useless information as i get partway through it. probably because you're not paying enough attention to what he says...
Portraying highly opinionated comments as absolute truth leads to flame wars (please don't).
(he said that in response to something about API)
not only that but i recommend you explain what an acronym is before you start using it...
Well, ive forgotten the function key word used in code variables very often (even before i knew about function interfaces), so id venture to say that function interfaces are more intuitive (let me stress that this is my POV). Also, having to return false inside the registered functions looks counter intuitive to me.
while i don't know what you're talking about in regards to the function interfaces and so on this part about returning false is not such a big deal...
if you can't do it, then use the redundant triggers provided. if you can, good for you. you win either way.
 

Deaod

Member
Reaction score
6
i think GT has more triggerregister options...last i checked spellevent only has 5?
Indeed. Thats why its called SpellEvent. Because it only offers spell event responses.

PLEASE DO NOT POST LIKE YOU DID IN RESPONDING to Jesus4Lyf
Consider it considered.

you look like you have a too high opinion of yourself
Yes, i (probably) do. And im thankful for that. Makes me think im useful for something.

probably because you're not paying enough attention to what he says
And here i was, thinking it was the other way 'round. I guess thats normal when arguing and defending your position.

i recommend you explain what an acronym is before you start using it...
Just say that you cant follow. Or go look it up on wikipedia. He (Jesus4Lyf) seems to understand me.

this part about returning false is not such a big deal
You missed the point. Read again. It doesnt matter if its not a big deal. Its counter intuitive.
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top