System Precise Damage Counter

Furby

Current occupation: News poster
Reaction score
145
auwqh4.png

v1.4

1p787q.png
v1.4 - 5.19.2010
- Fixed an issue when GetMostDamagePlayer function was returning wrong player​

Older update:
v1.3 - 5.15.2010
- Minor edit​

v1.2 - 5.15.2010
- Removed some unnecessary nulling
- Changed name of the library
- Changed names of functions​

v1.1 - 5.15.2010
- Fixed an issue when system was creating unnecessary links, when damaged by same player more times
- Fixed an issue when system was counting more percent when the unit was damaged for more than actual hit points
- Both system structs privatized​

v1.0 - 5.14.2010
- First release​

s30ppt.png
This damage counting will never fail, it won't fail when target is healed nor when target's maximum hp has been changed. It's great for preventing kill stealing in AoS games, but also for many other purposes.

Here's explanation how the system works.

ap89at.jpg

vgnec6.png

2ue1rg0.png
  • Make new trigger.
  • Rename it to Precise Damage Counter or whatever you want.
  • Edit -> Convert to custom text.
  • Replace the whole trigger with the code.

2a6nw1t.png
JASS:
//  |===========================================================================================|
//  |*******************************************************************************************|
//  |*****                             PRECISE DAMAGE COUNTER                              *****|
//  |***                             ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯                              ****|
//  |**                                      by Furby                                        ***|
//  |*****                                    v1.4                                         *****|
//  |*******************************************************************************************|
//  |                                   - Requirements -                                        |
//  |                                        AIDS                                               |
//  |                                       Damage                                              |
//  |*******************************************************************************************|
//  |                                   - Functions -                                           |
/*  |      PDC_GetDamagePercentUnit takes unit whatUnit, player whatPlayer returns real         |*/
//  |       - returns damage done to the unit in percent                                        |
/*         PDC_GetMostDamagePlayer takes unit whatUnit returns player                           |*/
//  |       - returns player who done the most damage to unit                                   |
//  |*******************************************************************************************|
//  |                            more info at thehelper.net                                     |
//  |===========================================================================================|
library PDC requires AIDS, Damage

    // If this function will return true, unit will be counted as valid
    private function ValidUnit takes unit u returns boolean
        return true
    endfunction

    // If this function will return true, damage will be counted as valid
    // uses the usual damage event responses
    private function ValidDamage takes nothing returns boolean
        return true
    endfunction

    // = = = = = = = = = = = = = = = = = = = = = = = = = = = = 
    //  DO NOT TOUCH BELOW UNLESS YOU KNOW WHAT'RE YOU DOING!
    // = = = = = = = = = = = = = = = = = = = = = = = = = = = =

    private struct DamageCount
        real percent
        player  who
        thistype next
        private method onDestroy takes nothing returns nothing
            set percent = 0.0
            set who = null
        endmethod
    endstruct

    private struct VictimUnit extends array
        //! runtextmacro AIDS()
        real done
        DamageCount first
        DamageCount last
        private static method AIDS_filter takes unit u returns boolean
            return ValidUnit(u)
        endmethod   
        
        private method AIDS_onDestroy takes nothing returns nothing
            local DamageCount dc = first
            loop
                call dc.destroy()
                exitwhen(dc.next == dc or dc == 0)
                set dc = dc.next
            endloop
        endmethod
        
        private method AIDS_onCreate takes nothing returns nothing
            set done = 0.0
        endmethod
        
        private static method onDamage takes nothing returns nothing
            local unit u = GetTriggerUnit()
            local thistype this = VictimUnit<u>
            local real dmgPercent = 100.0 * (GetEventDamage() / GetUnitState(u, UNIT_STATE_MAX_LIFE))
            local player p = GetOwningPlayer(GetEventDamageSource())
            local real over = dmgPercent - (100 - done)
            local DamageCount dc = 0
            local DamageCount temp = 0
            if GetEventDamage() &gt; GetWidgetLife(u) then
                set dmgPercent = 100.0 * (GetWidgetLife(u) / GetUnitState(u, UNIT_STATE_MAX_LIFE))
                set over = dmgPercent - (100 - done)
            endif
            if over &gt; 0 then
                set dc = first
                loop
                    exitwhen(over &lt;= 0.0 or dc == 0)
                    if dc.percent - over &gt; 0.0 then
                        set dc.percent = dc.percent - over
                        set over = 0.0
                    else
                        set over = over - dc.percent
                        set temp = dc
                        if dc.next &gt; 0 then
                            set dc = dc.next
                        endif
                        call temp.destroy()
                    endif
                endloop
                if dc &gt; 0 then
                    set first = dc
                endif
                if last.who == p then
                    set dc = last
                else
                    set dc = DamageCount.create()
                    set dc.next = dc
                    set last.next = dc
                    set last = dc
                endif
            else
                if first &gt; 0 then
                    if last.who == p then
                        set dc = last
                    else
                        set dc = DamageCount.create()
                        set last.next = dc
                        set dc.next = dc
                        set last = dc
                    endif
                else
                    set dc = DamageCount.create()
                    set first = dc
                    set dc.next = dc
                    set last = dc
                endif
            endif
            set dc.percent = dc.percent + dmgPercent
            set dc.who = p
            set done = done + dmgPercent
            set u = null
        endmethod
        
        private static method AIDS_onInit takes nothing returns nothing
            local trigger t = CreateTrigger()
            call Damage_RegisterEvent(t)
            call TriggerAddCondition(t, Condition(function ValidDamage))
            call TriggerAddAction(t, function thistype.onDamage)
        endmethod
    endstruct
    
    public function GetDamagePercentUnit takes unit whatUnit, player whatPlayer returns real
        local DamageCount dc = VictimUnit[whatUnit].first
        local real total = 0
        loop
            if dc.who == whatPlayer then
                set total = total + dc.percent
            endif
            exitwhen(dc.next == dc or dc == 0)
            set dc = dc.next
        endloop
        return total
    endfunction
    
    public function GetMostDamagePlayer takes unit whatUnit returns player
        local real temp = 0
        local player result = null
        local integer i = 0
        loop
            exitwhen(i&gt;15)
            if GetDamagePercentUnit(whatUnit, Player(i)) &gt; temp then
                set result = Player(i)
                set temp = GetDamagePercentUnit(whatUnit, Player(i))
            endif
            set i = i + 1
        endloop
        return result
    endfunction
    
endlibrary</u>


2hcqpg9.png
  • What does this do?
    - It counts percent of damage done to any unit on the map by all players.
  • Why would I need that?
    - If you use anything related to bounty, this should help you.
  • Why not just count damage done and then calculate percent when unit dies?
    - That would count healed units two times.
  • Hmm.
    - Aha?
  • I will use it for my map.
    - Ok? That's why it's here.
  • Do you want some credits?
    - Sure, why not.
  • I need to edit it to fit my map!
    - Go ahead, I don't care.
  • I don't understand vJass
    - So?
 

Attachments

  • PreciseDamageCounterDEMOMAP.w3x
    63.1 KB · Views: 378
That is a really cool premise. There is one problem. How do you factor in regen?

In an AoS or something, heroes often get away and heal. The one who deserves the kill is the one who dealt all the damage since they last healed. There are ways to accomplish this - they're not that hard.

When a unit is damaged, store their missing health, after the damage is dealt ([LJASS]GetUnitState(unit,UNIT_STATE_MAX_LIFE)-(GetWidgetLife(unit)-GetEventDamage())[/LJASS]). Then, next time they are damage, check their missing health ([LJASS]GetUnitState(unit,UNIT_STATE_MAX_LIFE)-GetWidgetLife(unit)[/LJASS]). Find [LJASS](nowMissingHealthBeforeActuallyDealingThisDamage/prevMissingHealth)[/LJASS] which is then a value you can multiply every damage count by to reduce it by the percentage regenerated since when it was last damaged. This will factor in every heal and everything. :)

Also, I'm not sure what you're doing in your loops as I haven't read it yet, but I bet I could write this thing without loops... (except for the regen part).
 
-> Privatelize DamageCount and VictimUnit.
-> Just remove the usage of LinkedList, you should use array in this case, since the players number are fixed. It is faster too.
Jasshelper will pop up error if you put arrayed member(s) in array struct, use dynamic array/hashtable to solve it.
JASS:
type DamageCount extends real array [16]
private struct VictimUnit
    DamageCount dc
    
    method AIDS_onCreate takes nothing returns nothing
        set .dc = DamageCount.create()
    endmethod

//.dc[GetPlayerId(GetOwningPlayer(GetEventDamageSource))] += GetEventDamage
 
That is a really cool premise. There is one problem. How do you factor in regen?

In an AoS or something, heroes often get away and heal. The one who deserves the kill is the one who dealt all the damage since they last healed. There are ways to accomplish this - they're not that hard.

When a unit is damaged, store their missing health, after the damage is dealt ([LJASS]GetUnitState(unit,UNIT_STATE_MAX_LIFE)-(GetWidgetLife(unit)-GetEventDamage())[/LJASS]). Then, next time they are damage, check their missing health ([LJASS]GetUnitState(unit,UNIT_STATE_MAX_LIFE)-GetWidgetLife(unit)[/LJASS]). Find [LJASS](nowMissingHealthBeforeActuallyDealingThisDamage/prevMissingHealth)[/LJASS] which is then a value you can multiply every damage count by to reduce it by the percentage regenerated since when it was last damaged. This will factor in every heal and everything. :)
I think this system takes care of it. :thup:
Also, I'm not sure what you're doing in your loops as I haven't read it yet, but I bet I could write this thing without loops... (except for the regen part).
Do tell. :)
-> Privatelize DamageCount and VictimUnit.
Oh, thanks. Done.
-> Just remove the usage of LinkedList, you should use array in this case, since the players number are fixed. It is faster too.
Jasshelper will pop up error if you put arrayed member(s) in array struct, use dynamic array/hashtable to solve it.
JASS:
type DamageCount extends real array [16]
private struct VictimUnit
    DamageCount dc
    
    method AIDS_onCreate takes nothing returns nothing
        set .dc = DamageCount.create()
    endmethod

//.dc[GetPlayerId(GetOwningPlayer(GetEventDamageSource))] += GetEventDamage
Eww.. you misunderstood my system, if it was working as you said, it would not be precise. :)

Ok, I think none of you understood my system correctly, here's how it works:

ap89at.jpg

___________________

Released version 1.1. Check the change log.
 
Furby, maybe shorter functions, like PreciseDamageCounter_GetUnitPlayerDamage
DamageCounter_Damage
Or PDC_GUPD
 
Just the normal function names would do good... Otherwise, just make your library an abbreviation (PDC) and leave the functions public. This way is more user friendly. :thup:
 
> Or PDC_GUPD
Christ, no.

From a brief look, method [ljass]validDamage[/ljass] could be removed, and you could just [ljass]ValidDamage[/ljass] directly. You could also state somewhere that it uses the usual damage event responses. :p
 
> Or PDC_GUPD
Christ, no.
I don't even like current one with "PDC". xD It looks ugly, but otherwise it would be just too long.
From a brief look, method [ljass]validDamage[/ljass] could be removed, and you could just [ljass]ValidDamage[/ljass] directly. You could also state somewhere that it uses the usual damage event responses. :p
Oh, yeah. Thanks. Fixed. :)
 
Also, struct members doesn't need to be nulled either, right ? :S
(Or am I crazy to believe I've heard this ? XD)

And also, put [ljass]GetEventDamageSource()[/ljass] into a unit variable (Which also needs to be nulled later) and you should also null that player variable ;)
 
> Also, struct members doesn't need to be nulled either, right ? :S
Right (they're likely to be overwritten). Though it doesn't hurt to, I'd imagine.

> null that player variable
Players don't need to be nulled.
 
....., linked list is really not needed, as I mentioned it before.
2d array/hashtable is enough for it.
Linked list is slower when the node is deep inside the list.
GetDamagePercent unit will faster if you remove linked list because O(n) search in linked list is not really fast.
 
....., linked list is really not needed, as I mentioned it before.
2d array/hashtable is enough for it.
Linked list is slower when the node is deep inside the list.
GetDamagePercent unit will faster if you remove linked list because O(n) search in linked list is not really fast.

You don't get it, do you? :rolleyes:

Have you seen picture with explanation? ;)

Show me how you gonna do it with arrays.. :thup:
 
set i = i + 1 o_O
If you want to add some temporary data, just use the other slots to do so.
 
I would have to move all indexes of array after each damage overwrite.
 
Released version 1.4!

Fixed one pretty major bug and reworked demo map! :thup:
 
General chit-chat
Help Users
  • No one is chatting at the moment.
  • V-SNES V-SNES:
    Happy Friday!
    +1
  • The Helper The Helper:
    News portal has been retired. Main page of site goes to Headline News forum now
  • The Helper The Helper:
    I am working on getting access to the old news portal under a different URL for those that would rather use that for news before we get a different news view.
  • Ghan Ghan:
    Easily done
    +1
  • The Helper The Helper:
    https://www.thehelper.net/pages/news/ is a link to the old news portal - i will integrate it into the interface somewhere when i figure it out
  • Ghan Ghan:
    Need to try something
  • Ghan Ghan:
    Hopefully this won't cause problems.
  • Ghan Ghan:
    Hmm
  • Ghan Ghan:
    I have converted the Headline News forum to an Article type forum. It will now show the top 20 threads with more detail of each thread.
  • Ghan Ghan:
    See how we like that.
  • The Helper The Helper:
    I do not see a way to go past the 1st page of posts on the forum though
  • The Helper The Helper:
    It is OK though for the main page to open up on the forum in the view it was before. As long as the portal has its own URL so it can be viewed that way I do want to try it as a regular forum view for a while
  • Ghan Ghan:
    Yeah I'm not sure what the deal is with the pagination.
  • Ghan Ghan:
    It SHOULD be there so I think it might just be an artifact of having an older style.
  • Ghan Ghan:
    I switched it to a "Standard" article forum. This will show the thread list like normal, but the threads themselves will have the first post set up above the rest of the "comments"
  • The Helper The Helper:
    I don't really get that article forum but I think it is because I have never really seen it used on a multi post thread
  • Ghan Ghan:
    RpNation makes more use of it right now as an example: https://www.rpnation.com/news/
  • The Helper The Helper:
  • The Helper The Helper:
    What do you think Tom?
  • tom_mai78101 tom_mai78101:
    I will have to get used to this.
  • tom_mai78101 tom_mai78101:
    The latest news feed looks good

      The Helper Discord

      Staff online

      • Ghan
        Administrator - Servers are fun

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top