[Snippet] DamageEvent

Level 30
Joined
Jul 10, 2007
Messages
6,307
JASS:
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:

PurgeandFire

Spell Moderator
Level 43
Joined
Nov 11, 2006
Messages
7,502
Atm this isn't working for me.
JASS:
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
 
Level 30
Joined
Jul 10, 2007
Messages
6,307
Fixed
JASS:
            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
 
Level 30
Joined
Jul 10, 2007
Messages
6,307
Update
JASS:
            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
 
Level 30
Joined
Jul 10, 2007
Messages
6,307
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.
 
Level 4
Joined
Jan 27, 2010
Messages
133
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.

Yeah, so I have heard too. This is not an issue with minor leaks. Scripts would stop functioning altogether.

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.

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:
Level 30
Joined
Jul 10, 2007
Messages
6,307
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.
 
Level 4
Joined
Jan 27, 2010
Messages
133
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.

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.

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

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 ^^
 
Level 30
Joined
Jul 10, 2007
Messages
6,307
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 ^^

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.
 
Level 4
Joined
Jan 27, 2010
Messages
133
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.

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:
 
Level 4
Joined
Jan 27, 2010
Messages
133
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:
Level 6
Joined
Jun 20, 2011
Messages
249
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
 
Level 6
Joined
Jun 20, 2011
Messages
249
So i wrote this down to have an "unit deals damage event" it's pretty useful and safe.
JASS:
library OUD uses DamageEvent, UnitIndexer

/*
    function OnUnitDamage takes unit whichUnit, boolexpr condition returns nothing
*/

    globals
        private trigger array e
    endglobals
    private function onDamage takes nothing returns boolean
        local integer i=GetUnitUserData(DamageEvent.source)
        if not(null==e[i]) then
            call TriggerEvaluate(e[i])
        endif
        return false
    endfunction
    private function onRemoval takes nothing returns boolean
        call DestroyTrigger(e[GetIndexedUnitId()])
        return false
    endfunction
    function OnUnitDamage takes unit whichUnit, boolexpr condition returns nothing
        local integer i=GetUnitUserData(whichUnit)
        if null==e[i] then
            set e[i]=CreateTrigger()
        endif
        call TriggerAddCondition(e[i],condition)
    endfunction
    private module Init
        private static method onInit takes nothing returns nothing
            call RegisterEvent(Condition(function onDamage),DamageEvent.ANY)
            call RegisterUnitIndexEvent(Condition(function onRemoval),UnitIndexer.DEINDEX)
        endmethod
    endmodule
    private struct InitStruct extends array
        implement Init
    endstruct
endlibrary
What do you guys think
 
JASS:
private function onDamage takes nothing returns boolean
        local integer i=GetUnitUserData(DamageEvent.source)
        if not(null==e[i]) then
            call TriggerEvaluate(e[i])
        endif
        return false
    endfunction
->
JASS:
    private function onDamage takes nothing returns boolean
        if not(null==e[DamageEvent.sourceId]) then
            call TriggerEvaluate(e[DamageEvent.sourceId])
        endif
        return false
    endfunction

OnUnitDamage -> RegisterUnitDamageEvent

Also, when it comes to practical application, I find your snippet useful if we
have many units that we want to keep track of. (The Frozen Throne in DotA for example)
 
Level 34
Joined
Sep 26, 2009
Messages
8,435
You could use TriggerClearConditions and let the trigger recycle upon removal, but that's up to you.

OnUnitDamage is fine, RegisterUnitDamageEvent is not accurate here as you are registering a boolexpr. Maybe RegisterOnUnitDamage would be the most proper, but the keyword Register is kind of redundant here imvho.
 
Level 6
Joined
Jun 20, 2011
Messages
249
For the event refreshing, this system should include UntiList as a requirement instead of having it's own linked list of units. Also, would you be interested in a textmacro that allows specific unit trigger evaluations? (like my damage system on the helper)
 
Level 30
Joined
Jul 10, 2007
Messages
6,307
For the event refreshing, this system should include UntiList as a requirement instead of having it's own linked list of units. Also, would you be interested in a textmacro that allows specific unit trigger evaluations? (like my damage system on the helper)

I wouldn't be interested in that textmacro, no.


I already told you why >.>.
 
Level 6
Joined
Jun 20, 2011
Messages
249
You did say that you're not interested in adding more options to this system as it currently is, because there's no point in it, and there isn't. What i'm asking you is to implement a list of optional textmacros in it (the same way you do with adv damage) for people who are interested in it.

As for the UnitList idea you haven't commented anything.
 
Level 30
Joined
Jul 10, 2007
Messages
6,307
Updated

One thing I didn't like about the old version was that it could cause spikes whenever it remade the triggers. When playing Guilds of Hyppos, I noticed spikes whenever the damage detection system refreshed. Rather than making everything run on 1 trigger, I decided to make everything run on many small triggers of certain sizes ;p. This minimizes the trigger count while getting rid of the spikes ; ).

With a trigger size of of 15, the most units that will ever be refreshed in a given moment will be 15 units ;p.


So now this has the best of both worlds ; ). Less triggers and better performance, ;D.


This no longer supports AdvDamageEvent as the wc3 engine has too many problems for that resource to ever be useful.


Who here is into the way I code now btw? lol... the way I'm coding now is how I code normally (w/o the comments because mass comments and method headers annoy me).
 
Last edited:
Level 30
Joined
Jul 10, 2007
Messages
6,307
Updated this again...

I've officially destroyed backwards compatibility with a new resource called PriorityEvent. Don't fret though, you can do so much more with this now than you ever could before =).

I also rereleased Advanced Damage Event so that it just supports the blocking damage stuff. All of this with PriorityEvent just gives you super powers ; D.

edit
fixed a debug thing, had commented out some stuff for testing ;p
 
Last edited:
Level 9
Joined
May 27, 2009
Messages
494
ohhh D:
anyways i'll gonna use Dirac's DamageId

btw, can you optimize the code more? i mean reduce too much of some recycle stuffs or check...
it keeps on creating fatal errors if an "unintentional execution" happened like multiple damage detection of every unit in a map lol D:
and such and such that might cause the system's trigger to crash

i tried it in mag's ass system o.o
 
Level 30
Joined
Jul 10, 2007
Messages
6,307
hmmm?

I got 0 of these fatal crashes when I had hundreds of units all fighting each other with texttags + 20 executions per unit.


The code is more optimal than Dirac's or j4l's or whatever's on wc3c, I can tell you right now. The recycling is extremely optimal as it uses an algorithm none of the others use. You can't make the recycler any more optimal. The algorithm recycles minimally + causes minimal memory leaks in between recycling the triggers. Also, each recycle is very small. In the old version of DamageEvent, recycling might be registering 100 units on to the trigger. In the new version, only 80 units at most are registered to a given trigger and you have a variety of triggers running. This is so that you don't have spikes.

Some damage systems have 1 trigger for every unit (tons of memory usage + overhead on creation and destruction). Others have 1 for the entire system (minimal memory, but spikes when remaking the trigger). This one goes in between both to make normally 1 trigger for every 80 units. It registers units to triggers with the fewest units currently registered to them as well (hence why there is minimal recycling). This gets rid of spikes, lowers how often triggers are created/destroyed and lowers total memory. As I said, this is by far the most efficient and optimal of all of the damage systems out there, including Dirac's =).

The only system I have out there right now that I wouldn't count as super optimal is Damage Modification Effect. You can count on everything else being extremely optimal and modular, running off of normally much better algorithms than you will find in any other system on any other site. The trade off for this is that some of these algorithms are much more complex to code, meaning that you may run into bugs in some systems if the version number is low. This one doesn't have said bugs, but I do still have one system out there right now that is known to have 1 bug =P. BigInt also had 1 bug in the division algorithm (which was handcrafted by me and somewhat complex, but super fast).

Also, if you compare my damage resources to Dirac's, mine are much more simple and much more modular. In 4 libraries, I did what Dirac did in all of his + much more.

Also, that 80 units can be changed to whatever value you want by modifying the TRIGGER_SIZE constant.
 
Level 9
Joined
May 27, 2009
Messages
494
Nestharus is just so awesome

I have written this poem in dedication to nes nes

Nes Nes is awesome
By Nes Nes

Nes Nes is so awesome
That I wrote this awesome poem
How awesome
o.o

at least fix that 1 bug >:D
i hope you can just put in windows calculator in world editor.. that would be awesome for BigInt lol

lol you might want to create an extension like DamageId wherein the buff and life bonus isn't that too much noticeable... unlike the old version of AdvDamageEvent D:
just for differentiating attacks (melee and range) from spells and custom attacks

i think the best way to do is use the old fashioned jass damage detection system which icefrog did.. if you'll see his map's code in his website.. even though it's already optimized
 
Top