1. Updated Resource Submission Rules: All model & skin resource submissions must now include an in-game screenshot. This is to help speed up the moderation process and to show how the model and/or texture looks like from the in-game camera.
    Dismiss Notice
  2. DID YOU KNOW - That you can unlock new rank icons by posting on the forums or winning contests? Click here to customize your rank or read our User Rank Policy to see a list of ranks that you can unlock. Have you won a contest and still havn't received your rank award? Then please contact the administration.
    Dismiss Notice
  3. Travel to distant realms and encounter scenes unknown to the common folk. The Greatest of Adventures is upon us with the 8th Cinematic Contest. Join in on a fun ride.
    Dismiss Notice
  4. The 18th Icon Contest is ON! Choose any ingame unit and give him/her Hero abilities. Good luck to all.
    Dismiss Notice
  5. The Secrets of Warcraft 3 have revealed interesting works. The RESULTS for Abelhawk's Mini-Mapping Contest #15 have come out!
    Dismiss Notice
  6. Contestants are to create a scene set in the Stone Age. Come and see what you can come up with. We wish you the best of luck!
    Dismiss Notice
  7. Colour outside the lines! Techtree Contest #13 is a go. The contest is optionally paired.
    Dismiss Notice
  8. Night Rider gained several songs for his journey. The poll for the 12th Music Contest has started. Check it out!
    Dismiss Notice
  9. Greetings cerebrates, our Swarm needs new spawners that will have numerous children. Join the HIVE's 31st Modeling Contest - Spawners and Spawned! The contest is optionally paired.
    Dismiss Notice
  10. Check out the Staff job openings thread.
    Dismiss Notice
Dismiss Notice
60,000 passwords have been reset on July 8, 2019. If you cannot login, read this.

[Snippet] DamageEvent

Discussion in 'Graveyard' started by Nestharus, Jan 8, 2011.

  1. Nestharus

    Nestharus

    Joined:
    Jul 10, 2007
    Messages:
    6,149
    Resources:
    8
    Spells:
    3
    Tutorials:
    4
    JASS:
    1
    Resources:
    8
    Code (vJASS):

    library DamageEvent /* v3.1.2.0
    *************************************************************************************
    *
    *   Simple light damage detection. Will not run 0 damage events as only invalid attacks and spells can cause these.
    *   Can instance spells and attacks with fireSpell and fireAttack methods.
    *
    *************************************************************************************
    *
    *   */
    uses/*
    *
    *       */
    UnitIndexer      /*      hiveworkshop.com/forums/jass-functions-413/unit-indexer-172090/
    *       */
    PriorityEvent    /*      hiveworkshop.com/forums/submissions-414/snippet-priority-event-213573/
    *       */
    BinaryHeap       /*      hiveworkshop.com/forums/jass-resources-412/snippet-binary-heap-199353/
    *
    ************************************************************************************
    *
    *   SETTINGS
    */

    globals
        /*************************************************************************************
        *
        *   How many units can refresh at a given moment (when a trigger is rebuilt).
        *   larger size means less triggers but harder refreshes.
        *
        *************************************************************************************/

        private constant integer TRIGGER_SIZE = 80
    endglobals
    /*
    *************************************************************************************
    *
    *   struct DamageEvent extends array
    *
    *       Fields
    *       ------------------
    *       static constant PriorityEvent ANY
    *
    *       readonly static UnitIndex targetId
    *       readonly static UnitIndex sourceId
    *       readonly static unit target
    *       readonly static unit source
    *       readonly static real amount
    *       readonly static integer depth
    *           -   if depth == 1, then current damage is the original attack, not a modifier
    *
    *       static boolean enabled
    *
    *       readonly static integer damageType
    *           -   useful for custom attack types (spell, hero, chaos, etc)
    *       readonly static integer damageId
    *           -   useful for things like ability ids
    *       readonly static integer instance
    *           -   useful for passing in a struct
    *
    *       Methods
    *       ------------------
    *       static method allocateAttack takes integer damageType, integer damageId, integer instance returns nothing
    *
    *************************************************************************************
    *
    *   module ExtendDamageEvent extends DamageEvent, AdvDamageEvent (if exists)
    *
    *   module DamageEvent extends DamageEvent, AdvDamageEvent (if exists)
    *
    *       Interface
    *       ------------------
    *           private static constant method PRIORITY takes nothing returns integer       (optional)
    *               -   without this declared, the priority will be set to 0 (no priority)
    *           private static method onDamage takes nothing returns nothing                (optional)
    *           private static method filter takes nothing returns boolean                  (optional)
    *
    *************************************************************************************/

        private struct DamageEventProperties extends array
            static method operator target takes nothing returns unit
                return GetUnitById(DamageEvent.targetId)
            endmethod
            static method operator source takes nothing returns unit
                return GetUnitById(DamageEvent.sourceId)
            endmethod
        endstruct

        //! runtextmacro optional ADV_DAMAGE_EVENT_EXT_CODE()
       
        globals
            private boolexpr damageCondition
        endglobals
       
        private struct DamageTrigger extends array
            private static integer instanceCount = 0
       
            private thistype first
            private thistype next
            private thistype prev
            readonly thistype parent
           
            private integer inactiveUnits
            readonly integer activeUnits
           
            private trigger damageTrigger
           
            private method registerUnit takes UnitIndex whichUnit returns boolean
                if (activeUnits < TRIGGER_SIZE) then
                    call TriggerRegisterUnitEvent(damageTrigger, GetUnitById(whichUnit), EVENT_UNIT_DAMAGED)
                    set activeUnits = activeUnits + 1
                   
                    return true
                endif
               
                return false
            endmethod
            private method unregisterUnit takes UnitIndex whichUnit returns nothing
                set inactiveUnits = inactiveUnits + 1
                set activeUnits = activeUnits - 1
            endmethod
           
            private method createTrigger takes nothing returns nothing
                set damageTrigger = CreateTrigger()
                call TriggerAddCondition(damageTrigger, damageCondition)
            endmethod
            private method remakeTrigger takes nothing returns nothing
                call DestroyTrigger(damageTrigger)
                call createTrigger()
            endmethod
            private method rebuildTrigger takes nothing returns nothing
                local thistype current = first
               
                call remakeTrigger()
               
                /*
                *   Iterate over all units registered to the trigger and reregister them
                */

                set current.prev.next = 0
                loop
                    exitwhen 0 == current
                    call TriggerRegisterUnitEvent(damageTrigger, GetUnitById(current), EVENT_UNIT_DAMAGED)
                    set current = current.next
                endloop
                set first.prev.next = current
            endmethod
           
            private method remake takes nothing returns nothing
                if (inactiveUnits == TRIGGER_SIZE) then
                    set inactiveUnits = 0
                    call rebuildTrigger()
                endif
            endmethod
           
            private method addToList takes thistype whichUnit returns nothing
                set whichUnit.parent = this
           
                if (0 == first) then
                    set first = whichUnit
                    set whichUnit.next = whichUnit
                    set whichUnit.prev = whichUnit
                else
                    set this = first
                   
                    set whichUnit.prev = prev
                    set whichUnit.next = this
                    set prev.next = whichUnit
                    set prev = whichUnit
                endif
            endmethod
            method add takes thistype whichUnit returns boolean
                if (0 == this) then
                    return false
                endif
           
                if (registerUnit(whichUnit)) then
                    call addToList(whichUnit)
                   
                    return true
                endif
               
                return false
            endmethod
           
            private method removeFromList takes thistype whichUnit returns nothing
                set whichUnit.parent = 0
           
                set whichUnit.prev.next = whichUnit.next
                set whichUnit.next.prev = whichUnit.prev
               
                if (first == whichUnit) then
                    set first = whichUnit.next
                    if (first == whichUnit) then
                        set first = 0
                    endif
                endif
            endmethod
            static method remove takes thistype whichUnit returns nothing
                local thistype this = whichUnit.parent
           
                call removeFromList(whichUnit)
                call unregisterUnit(whichUnit)
                call remake()
            endmethod
           
            private static method allocate takes nothing returns thistype
                set instanceCount = instanceCount + 1
                return instanceCount
            endmethod
            static method create takes nothing returns thistype
                local thistype this = allocate()
               
                call createTrigger()
               
                return this
            endmethod
        endstruct
       
        private struct DamageTriggerHeapInner extends array
            private static method compare takes DamageTrigger trig1, DamageTrigger trig2 returns boolean
                return trig1.activeUnits <= trig2.activeUnits
            endmethod
            implement BinaryHeap
        endstruct
       
        private struct DamageTriggerHeap extends array
            private static DamageTriggerHeapInner array parent
           
            static method add takes UnitIndex whichUnit returns nothing
                local DamageTrigger damageTrigger = DamageTriggerHeapInner.root.value
               
                if (not damageTrigger.add(whichUnit)) then
                    set damageTrigger = DamageTrigger.create()
                    call damageTrigger.add(whichUnit)
                    set parent[damageTrigger] = DamageTriggerHeapInner.insert(damageTrigger)
                else
                    call parent[damageTrigger].modify(damageTrigger)
                endif
            endmethod
            static method remove takes UnitIndex whichUnit returns nothing
                local DamageTrigger damageTrigger = DamageTrigger(whichUnit).parent
                call DamageTrigger.remove(whichUnit)
                call parent[damageTrigger].modify(damageTrigger)
            endmethod
        endstruct
       
        private module DamageEventMod
            readonly static PriorityEvent ANY
            readonly static UnitIndex targetId
            readonly static UnitIndex sourceId
            readonly static real amount
            static boolean enabled
           
            private static integer array damageType_p
            private static integer array damageId_p
            private static integer array instance_p
            private static integer runInstanceCount_p
            private static integer runAttackCount_p
           
            static method allocateAttack takes integer damageType, integer damageId, integer instance returns nothing
                if (enabled) then
                    set runInstanceCount_p = runInstanceCount_p + 1
                    set damageType_p[runInstanceCount_p] = damageType
                    set damageId_p[runInstanceCount_p] = damageId
                    set instance_p[runInstanceCount_p] = instance
                endif
            endmethod
           
            static method operator damageType takes nothing returns integer
                return damageType_p[runInstanceCount_p]
            endmethod
            static method operator damageId takes nothing returns integer
                return damageId_p[runInstanceCount_p]
            endmethod
            static method operator instance takes nothing returns integer
                return instance_p[runInstanceCount_p]
            endmethod
            static method operator depth takes nothing returns integer
                return runAttackCount_p
            endmethod
           
            //! runtextmacro optional DAMAGE_TYPE_EXT_FIELDS()
           
            private static delegate DamageEventProperties damageEventProperties = 0
           
            private static method damage takes nothing returns boolean
                local integer previousTargetId
                local integer previousSourceId
                local real previousAmount
                //! runtextmacro optional ADV_DAMAGE_EVENT_LOC_BEFORE()
                //! runtextmacro optional DAMAGE_TYPE_EXT_LOCALS()
               
                if (enabled and 0 != GetEventDamage()) then
                    /*
                    *   Setup spell
                    */

                    if (runAttackCount_p == runInstanceCount_p) then
                        set runInstanceCount_p = runInstanceCount_p + 1
                    endif
                    set runAttackCount_p = runAttackCount_p + 1
               
                    /*
                    *   Store previous amounts
                    */

                    set previousTargetId = targetId
                    set previousSourceId = sourceId
                    set previousAmount = amount
                   
                    /*
                    *   Update amounts to new amounts
                    */

                    set targetId = GetUnitUserData(GetTriggerUnit())
                    set sourceId = GetUnitUserData(GetEventDamageSource())
                    set amount = GetEventDamage()
                   
                    /*
                    *   Fire event
                    */

                    //! runtextmacro optional DAMAGE_TYPE_EXT()
                    //! runtextmacro optional ADV_DAMAGE_EVENT_EXT()
                    call ANY.fire()
                   
                    /*
                    *   Restore previous amounts
                    */

                    set targetId = previousTargetId
                    set sourceId = previousSourceId
                    set amount = previousAmount
                    //! runtextmacro optional ADV_DAMAGE_EVENT_LOC_AFTER()
                    //! runtextmacro optional DAMAGE_TYPE_EXT_RESET()
                   
                    /*
                    *   Remove spell
                    */

                    set damageType_p[runInstanceCount_p] = 0
                    set damageId_p[runInstanceCount_p] = 0
                    set instance_p[runInstanceCount_p] = 0

                    if (runAttackCount_p == runInstanceCount_p) then
                        set runInstanceCount_p = runInstanceCount_p - 1
                    endif
                    set runAttackCount_p = runAttackCount_p - 1
                endif
               
                return false
            endmethod
            private static method index takes nothing returns boolean
                call UnitIndex(GetIndexedUnitId()).lock()
                call DamageTriggerHeap.add(GetIndexedUnitId())
                return false
            endmethod
            private static method deindex takes nothing returns boolean
                call DamageTriggerHeap.remove(GetIndexedUnitId())
                call UnitIndex(GetIndexedUnitId()).unlock()
                return false
            endmethod
           
            private static method onInit takes nothing returns nothing
                set enabled = true
                set runInstanceCount_p = 0
                set runAttackCount_p = 0
               
                set damageCondition = Condition(function thistype.damage)

                set ANY = PriorityEvent.create()
               
                call RegisterUnitIndexEvent(Condition(function thistype.index), UnitIndexer.INDEX)
                call RegisterUnitIndexEvent(Condition(function thistype.deindex), UnitIndexer.DEINDEX)
               
                set targetId = 0
                set sourceId = 0
                set amount = 0
            endmethod
        endmodule
       
        struct DamageEvent extends array
            implement DamageEventMod
        endstruct
       
        module ExtendDamageEvent
            static if AdvDamageEvent_p.onDamage_p_core.exists then
                private static delegate AdvDamageEvent advDamageEvent = 0
            else
                private static delegate DamageEvent damageEvent = 0
            endif
        endmodule
       
        module DamageEvent
            implement ExtendDamageEvent
           
            static if thistype.onDamage.exists then
                private static method onDamage_p takes nothing returns boolean
                    static if thistype.filter.exists then
                        if (filter()) then
                            call onDamage()
                        endif
                    else
                        call onDamage()
                    endif
                    return false
                endmethod
               
                private static method onInit takes nothing returns nothing
                    static if thistype.PRIORITY.exists then
                        call DamageEvent.ANY.register(Condition(function thistype.onDamage_p), PRIORITY())
                    else
                        call DamageEvent.ANY.register(Condition(function thistype.onDamage_p), 0)
                    endif
                endmethod
            endif
        endmodule
    endlibrary
     
     
    Last edited: Jan 11, 2013
  2. Nestharus

    Nestharus

    Joined:
    Jul 10, 2007
    Messages:
    6,149
    Resources:
    8
    Spells:
    3
    Tutorials:
    4
    JASS:
    1
    Resources:
    8
    Updated to 2.0.0.0 to support the AdvDamageEvent extension.

    Also changed one portion of the API-
    static constant Event EVENT


    to

    static constant Event ANY
     
  3. Nestharus

    Nestharus

    Joined:
    Jul 10, 2007
    Messages:
    6,149
    Resources:
    8
    Spells:
    3
    Tutorials:
    4
    JASS:
    1
    Resources:
    8
    Updated with a slightly changed API and changed code
     
  4. Bribe

    Bribe

    Joined:
    Sep 26, 2009
    Messages:
    8,004
    Resources:
    25
    Maps:
    3
    Spells:
    10
    Tutorials:
    3
    JASS:
    9
    Resources:
    25
    Unless Blizzard makes a native event for "player unit takes damage", this is the absolute best way to go.
     
  5. Nestharus

    Nestharus

    Joined:
    Jul 10, 2007
    Messages:
    6,149
    Resources:
    8
    Spells:
    3
    Tutorials:
    4
    JASS:
    1
    Resources:
    8
    Updated as I fudged up the unit indexing registration ; P. Now it should work properly. I registered with the events directly, which is bad with the UnitIndexer. Have to use the RegisterUnitIndexEvent ;D.
     
  6. PurgeandFire

    PurgeandFire

    Code Moderator

    Joined:
    Nov 11, 2006
    Messages:
    7,427
    Resources:
    18
    Icons:
    1
    Spells:
    4
    Tutorials:
    9
    JASS:
    4
    Resources:
    18
    Code (vJASS):
    call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, GetUnitName(GetIndexedUnit()))
    //...
    call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "ran 1")
    //...
    call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "ran 2")
     


    Lol. You left those there. :p
     
  7. Nestharus

    Nestharus

    Joined:
    Jul 10, 2007
    Messages:
    6,149
    Resources:
    8
    Spells:
    3
    Tutorials:
    4
    JASS:
    1
    Resources:
    8
    My bad, I'll get them out ;P
     
  8. PurgeandFire

    PurgeandFire

    Code Moderator

    Joined:
    Nov 11, 2006
    Messages:
    7,427
    Resources:
    18
    Icons:
    1
    Spells:
    4
    Tutorials:
    9
    JASS:
    4
    Resources:
    18
    Atm this isn't working for me.
    Code (vJASS):
    static if not LIBRARY_AdvDamageEvent then
                    local integer prev = targetId
                    local integer prev2 = sourceId
                    local real prev3 = amount
                else
                    local integer targetId = GetUnitUserData(GetTriggerUnit())
                    local integer sourceId = GetUnitUserData(GetEventDamageSource())
                    local real amount = GetEventDamage()
                    local real life
                endif


    prev, prev2, prev3 are all null if you aren't using AdvDamageEvent?? Or at least, that is what it returns in my map. Try testing it out without AdvDamageEvent, because I think there is something wrong it. ;p
     
  9. Nestharus

    Nestharus

    Joined:
    Jul 10, 2007
    Messages:
    6,149
    Resources:
    8
    Spells:
    3
    Tutorials:
    4
    JASS:
    1
    Resources:
    8
    Fixed
    Code (vJASS):

                static if not LIBRARY_AdvDamageEvent then
                    local integer prev = targetId
                    local integer prev2 = sourceId
                    local real prev3 = amount
                    set targetId = GetUnitUserData(GetTriggerUnit())
                    set sourceId = GetUnitUserData(GetEventDamageSource())
                    set amount = GetEventDamage()
                else
                    local integer targetId = GetUnitUserData(GetTriggerUnit())
                    local integer sourceId = GetUnitUserData(GetEventDamageSource())
                    local real amount = GetEventDamage()
                    local real life
                endif
     
     
  10. Nestharus

    Nestharus

    Joined:
    Jul 10, 2007
    Messages:
    6,149
    Resources:
    8
    Spells:
    3
    Tutorials:
    4
    JASS:
    1
    Resources:
    8
    Update
    Code (vJASS):

                static if not LIBRARY_AdvDamageEvent then
                    local integer prev = targetId
                    local integer prev2 = sourceId
                    local real prev3 = amount
                    set targetId = GetUnitUserData(GetTriggerUnit())
                    set sourceId = GetUnitUserData(GetEventDamageSource())
                    set amount = GetEventDamage()
                else
                    local integer targetId = GetUnitUserData(GetTriggerUnit())
                    local integer sourceId = GetUnitUserData(GetEventDamageSource())
                    local real amount = GetEventDamage()
                    local real life
                    local boolean update = false
                    local integer i = eventCount
                endif
     
     
  11. themerion

    themerion

    Joined:
    Jan 27, 2010
    Messages:
    132
    Resources:
    0
    Resources:
    0
    Why remake the trigger already at 15?

    You should perhaps use the same precaution as in Light Leakless Damage Detect. Destroying triggers is taboo (because of possible instability).
     
  12. Nestharus

    Nestharus

    Joined:
    Jul 10, 2007
    Messages:
    6,149
    Resources:
    8
    Spells:
    3
    Tutorials:
    4
    JASS:
    1
    Resources:
    8
    Actually, the only thing you need to clear out from a trigger are the actions (destroying a trigger with actions on it will leak the trigger actions, but apparently not the trigger conditions). I haven't personally tested this, but yar.

    And actually, you made me see a possible bug in this =o. The destruction should be on a 0 second timer.

    And please don't link wc3c code to me as a suggestion. Just about all of it is crap.

    I'll update when I can ; ). Gotta update AdvDamageEvent to fix its issues too.
     
  13. themerion

    themerion

    Joined:
    Jan 27, 2010
    Messages:
    132
    Resources:
    0
    Resources:
    0
    Yeah, so I have heard too. This is not an issue with minor leaks. Scripts would stop functioning altogether.

    In my opinion, a lot of it is pretty good, and has quite high standards. Vexorian's JASSHelper, and the optimizer are quite neat tools. Also they are pretty good at making readable and flexible oop code.

    The trigger bug was quite serious and very difficult to reproduce. The precaution Cpt. Griffen used in his damage detection system was to Disable the current trigger and swap to a new one; destroying the disabled trigger at the next trigger swap.
     
    Last edited: Apr 18, 2011
  14. Nestharus

    Nestharus

    Joined:
    Jul 10, 2007
    Messages:
    6,149
    Resources:
    8
    Spells:
    3
    Tutorials:
    4
    JASS:
    1
    Resources:
    8
    It'll work just fine after 0 seconds >.>, but whether the trigger needs to be disabled or not, need to ponder that.

    I'd have to know whether events are queued up before timers run or if they are just done as the stuff is checked. If it's done as the stuff is checked, trigger doesn't need to be disabled. If it isn't, the trigger needs to be disabled as soon as it runs into destroy.

    It's very easy to check the order at which things run. As I said, I'll get to it when I can.

    edit
    On another note, the standards at wc3c are horrible. The code is bad, just everything is bad. And jasshelper is horrible too.
     
  15. themerion

    themerion

    Joined:
    Jan 27, 2010
    Messages:
    132
    Resources:
    0
    Resources:
    0
    Aah! I see. You seem to think that World Edit and Wc3 play nice and follow the rules. This is not necessarily the case. Logic doesn't always work on the editor; sometimes it does unexpected and random stuff. DestroyTrigger has been considered a huge problem for the stability of the entire map; why take chances? You gain nothing and lose stability.

    Yeah... the code contains comments! YUCK! And it's flexible. YUCK! And it has "slowness" which can never be an overhead! YUCK! :D

    Seriously, I'd love to debate this in a PM or something. Pick some "bad" code from wc3c and tell me why it's bad (and please stick to the more known names. I believe there are one or two code samples left from 2007 by noname).

    You think JassHelper is horrible? Then I suggest you stop coding for wc3 immediately ;P There must be something you can work with that is more pleasant than a HORRIBLE compilator ^^
     
  16. Nestharus

    Nestharus

    Joined:
    Jul 10, 2007
    Messages:
    6,149
    Resources:
    8
    Spells:
    3
    Tutorials:
    4
    JASS:
    1
    Resources:
    8
    Bribe's planning to update jasshelper and a lot of the vets are asking him to totally rewrite it because it's coded so horribly and is such a horrible language, lol ;D.

    And, look at http://www.wc3c.net/showthread.php?t=101309 as a prime example of horrible scripting. You can compare it to the GetUnitCollision resource in submission section page 2 at THW. Also, you can compare vex's timer queue deal (super timers or w/e) to timer queue written by me, lol... (links to it at wc3c in submission section under Timer Queue thread).

    Anyways, I haven't seen instability with triggers since before the patch that fixed H2I, so the only thing that needs to be fixed is the instant trigger destruction for reasons other than stability.
     
  17. tooltiperror

    tooltiperror

    Joined:
    Jun 3, 2010
    Messages:
    45
    Resources:
    1
    Tutorials:
    1
    Resources:
    1
    >You think JassHelper is horrible? Then I suggest you stop coding for wc3 immediately ;P There must be something you can work with that is more pleasant than a HORRIBLE compilator ^^
    kid thinks he got it all figured out
     
  18. themerion

    themerion

    Joined:
    Jan 27, 2010
    Messages:
    132
    Resources:
    0
    Resources:
    0
    Well, aight. If you are certain it's gone and will never cause trouble to anyone. After all this is a pretty low-level system in a map; and it would be a pity if it started to cause trouble to an unknowing map maker. The problem with proving it's definitely gone is of course that it was so slippery and difficult to reproduce to begin with...

    I'll go compare the scripts :grin:
     
  19. themerion

    themerion

    Joined:
    Jan 27, 2010
    Messages:
    132
    Resources:
    0
    Resources:
    0
    Regarding Get Unit Collision Size:

    First of all, your function can cause ALL KINDS of odd errors with unit enters/leaves region-events. Secondly, it can return negative values (uncodumented). Lastly, Vexorian's function is more accurate in the test case provided at your submission page.

    I also think that your function would break channelings. Not sure, don't need to test to make my point.

    You could also compare the code. I find Vexoiran's code to be easier to read, because of the spacing and indentation. Of course, this is just my personal opinion.

    -----------------------

    Regarding the timers queues, I'm not quite sure which resource you mean...
     
    Last edited: Apr 18, 2011
  20. Dirac

    Dirac

    Joined:
    Jun 20, 2011
    Messages:
    249
    Resources:
    3
    JASS:
    3
    Resources:
    3
    If i intended to know which is the damage type of the damage registered on the event when fired which is the best way to go?

    Also, i would change the API of the event from "ANY" to "REGISTER"

    DamageEvent.REGISTER sounds more correct