System GTrigger Event System

Discussion in 'Systems and Snippets' started by Jesus4Lyf, Mar 30, 2009.

  1. Romek

    Romek Super Moderator Staff Member

    Ratings:
    +961 / 0 / -0
    Will this see 'Any Unit Events'.. Ever? :p
     
  2. Tru_Power22

    Tru_Power22 You can change this now in User CP.

    Ratings:
    +144 / 0 / -0
    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.
     
  3. Troll-Brain

    Troll-Brain You can change this now in User CP.

    Ratings:
    +85 / 0 / -0
    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.
     
  4. Jesus4Lyf

    Jesus4Lyf Good Idea™

    Ratings:
    +394 / 0 / -0
    You mean wrappers?
    Warcraft III supports something better natively - adding/removing trigger conditions or actions to a single trigger...
     
  5. Deaod

    Deaod Member

    Ratings:
    +6 / 0 / -0
    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).

    Now guess why i put "proper" into quotes.

    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.

    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.

    Want me to comment on that one?
     
  6. kingkingyyk3

    kingkingyyk3 Visitor (Welcome to the Jungle, Baby!)

    Ratings:
    +216 / 0 / -0
    That claim depends on the number of collisions
    Rawcodes are big. >< I did not faced collision problem for modulo hashing it so far.
     
  7. Jesus4Lyf

    Jesus4Lyf Good Idea™

    Ratings:
    +394 / 0 / -0
    I was referring to function interfaces, really.
    Feedback is always appreciated, if it can bring about improvements... :D
     
  8. kingkingyyk3

    kingkingyyk3 Visitor (Welcome to the Jungle, Baby!)

    Ratings:
    +216 / 0 / -0
    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 ("SpellEffectEvent", "EVENT_PLAYER_UNIT_SPELL_EFFECT", "GetSpellAbilityId()")
        
        private function Init takes nothing returns nothing
            call InitSpellEffectEvent()
        endfunction
    endlibrary

    Hmm, I came up with this idea. :p
     
  9. Jesus4Lyf

    Jesus4Lyf Good Idea™

    Ratings:
    +394 / 0 / -0
    implementation*

    JASS:
        function Register$NAME$Action takes integer abilId, code func returns nothing
            call TriggerAddCondition($NAME$Trig,Condition(func))
        endfunction

    That fails.

    That's GTrigger in hashtable form (mostly). Doesn't make it better...
     
  10. kingkingyyk3

    kingkingyyk3 Visitor (Welcome to the Jungle, Baby!)

    Ratings:
    +216 / 0 / -0
    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 ("Cast", "CAST")
        //! runtextmacro Spell ("EndCast", "ENDCAST")
        //! runtextmacro Spell ("Channel", "CHANNEL")
        //! runtextmacro Spell ("Effect", "EFFECT")
        //---------------------
        
        //---------------------
        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
     
  11. Jesus4Lyf

    Jesus4Lyf Good Idea™

    Ratings:
    +394 / 0 / -0
    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.
     
  12. kingkingyyk3

    kingkingyyk3 Visitor (Welcome to the Jungle, Baby!)

    Ratings:
    +216 / 0 / -0
    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
     
  13. Jesus4Lyf

    Jesus4Lyf Good Idea™

    Ratings:
    +394 / 0 / -0
    I think you misunderstood me - I'm saying how useless what you did is if it's only 8% faster and totally insecure and missing simple features.
     
  14. Romek

    Romek Super Moderator Staff Member

    Ratings:
    +961 / 0 / -0
    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.
     
  15. Azlier

    Azlier Old World Ghost

    Ratings:
    +461 / 0 / -0
    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.
     
  16. Troll-Brain

    Troll-Brain You can change this now in User CP.

    Ratings:
    +85 / 0 / -0
    But this script doesn't fix lame natives spells responses events, right ?
     
  17. Jesus4Lyf

    Jesus4Lyf Good Idea™

    Ratings:
    +394 / 0 / -0
    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...
     
  18. Troll-Brain

    Troll-Brain You can change this now in User CP.

    Ratings:
    +85 / 0 / -0
    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.
     
  19. SanKakU

    SanKakU Member

    Ratings:
    +21 / 0 / -0
    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...
    (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...
    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.
     
  20. Deaod

    Deaod Member

    Ratings:
    +6 / 0 / -0
    Indeed. Thats why its called SpellEvent. Because it only offers spell event responses.

    Consider it considered.

    Yes, i (probably) do. And im thankful for that. Makes me think im useful for something.

    And here i was, thinking it was the other way 'round. I guess thats normal when arguing and defending your position.

    Just say that you cant follow. Or go look it up on wikipedia. He (Jesus4Lyf) seems to understand me.

    You missed the point. Read again. It doesnt matter if its not a big deal. Its counter intuitive.
     

Share This Page