System Precise Damage Counter

Furby

Current occupation: News poster
Reaction score
144
@13lade619

You got some scripts? I would want to see it.. can't imagine right now..
 

Laiev

Hey Listen!!
Reaction score
188
JASS:
//  |===========================================================================================|
//  |*******************************************************************************************|
//  |*****                             PRECISE DAMAGE COUNTER                              *****|
//  |***                             ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯                              ****|
//  |**                                      v1.4 by Furby                                   ***|
//  |*****                                   v1.5 by 13lade619                             *****|
//  |*******************************************************************************************|
//  |                                   - 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

    private struct DamageCount
        real healhp = 0
        real prevhp = 0
        real dmg = 0
        real hpbase = 0
        
        player  who 
        thistype next
        thistype prev
        private method onDestroy takes nothing returns nothing
            set hpbase = 0
            set healhp = 0.0
            set prevhp = 0.0
            set dmg = 0.0
            set who = null
        endmethod
    endstruct

    private struct VictimUnit extends array
        //! runtextmacro AIDS()
        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
                exitwhen(dc.next == dc or dc == 0)
                call dc.destroy()
                set dc = dc.next
            endloop
        endmethod
                
        private static method onDamage takes nothing returns nothing
            local unit u = GetTriggerUnit()
            local thistype this = VictimUnit<u>
            local player p = GetOwningPlayer(GetEventDamageSource())
            local real hp = GetWidgetLife(u)
            local real dealt = GetEventDamage()
            
            local DamageCount dc = 0
            local DamageCount temp = 0
            
            if dealt &gt; hp then
                set dealt = hp
            endif
            
            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 dc.prev = last
                    set last = dc
                endif
            else
                set dc = DamageCount.create()
                set first = dc
                set dc.next = dc
                set dc.prev = dc
                set last = dc
                set dc.hpbase = GetUnitState(u, UNIT_STATE_MAX_LIFE)
            endif
            
            set dc.who = p
            set dc.dmg = dc.dmg+dealt
            
            //call BJDebugMsg(GetUnitName(u))
            //call BJDebugMsg(&quot;PREV &quot;+R2S(dc.prev.prevhp))
            //call BJDebugMsg(&quot;DAMG &quot;+R2S(dealt))
            //call BJDebugMsg(&quot;THIS &quot;+R2S(hpbeforedamage))
            if (hp+dealt)&gt;dc.prev.prevhp and dc.prev.prevhp!=0 then
                //call BJDebugMsg(&quot;HEAL &quot;+R2S(hp+dealt-dc.prev.prevhp)+&quot;\n\n&quot;)
                set dc.healhp = dc.healhp + (hp+dealt-dc.prev.prevhp)
            endif
            set dc.next.prevhp = hp
            
            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 damages = 0
        local real maxlife = 0
        local real regenhp = 0
        local real percentage = 0
        loop
            set maxlife = maxlife + dc.hpbase
            set regenhp = regenhp + dc.healhp
            if dc.who == whatPlayer then
                set damages = damages + dc.dmg
            endif
            exitwhen(dc.next == dc or dc == 0)
            set dc = dc.next
        endloop
        return (damages/(maxlife+regenhp))*100
    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>


The code inside the demomap.

Edit:

Well...

First Test:

Laiev has done - 25.441% of damage
Player 2 has done - 28.046% of damage
Player 3 has done - 28.731% of damage

= 82.218%

Second Test:

Laiev has done - 33.695% of damage
Player 2 has done - 38.291% of damage
Player 3 has done - 21.154% of damage

= 93.14%

Third Test:

Laiev has done - 13.305% of damage
Player 2 has done - 23.462% of damage
Player 3 has done - 20.783% of damage

= 57.55%

This make LOTS of difference, the results varies a lot.
 

Furby

Current occupation: News poster
Reaction score
144
So the problem is together it doesn't make 100%? Well, maybe unit damages itself somehow or there is another player? Or there is bug in that system..
 

Weep

Godspeed to the sound of the pounding
Reaction score
401
Admittedly, I don't really understand the goal of this system or what it does, but...

The stated goal is to track the % damage dealt to a unit by each player. Why all the shenanigans with tracking the unit's life and healing? By definition, the sum of all damage dealt by a player divided by the total damage dealt by anything is the fraction of the damage dealt by that player, regardless of health changes. If the unit heals, that will be reflected in the total damage being higher than the unit's max life. If the unit's HP changes, that will be reflected in the total damage being appropriately higher/lower than the max life used to be.

The only thing you might want to do custom is to cap the damage values to the current life of the unit, since "overdamaging" something doesn't really count.

Unless I'm missing something, all this system needs to be is a hashtable, a damage event with a little code, and some wrapper functions to retrieve the data from the hashtable.
 

Furby

Current occupation: News poster
Reaction score
144
Imagine an AoS, using the system you described.

I damage Blue player like 20 times but goes back a little heals or regenerates but he doesn't die. Those 20 times you hit him would kill him like 5 times already.. Then he goes back to base, heals and goes to another lane, where he dies by two hits from your ally and you would have an assistance.. that's not right.
 

muzk

Member
Reaction score
3
Oh lol I dont unterstand the code :p!
Anyways, I didnt see something like this, it could work idk, just an idea...

Store players that have been damaged a unit (UNIT) ... so if UNIT regenerates X (when (hp+dealt)>dc.prev.prevhp) then substract X/(Number of players that damaged that unit) to the total damage dealt by those players to that unit.

JASS:
struct damageArray
real array damageDealt [16]
endstruct

So, de index of damageDealt is the id of players.

PS: Srry if you didnt understand, my english suckz :(
 

Weep

Godspeed to the sound of the pounding
Reaction score
401
I damage Blue player like 20 times but goes back a little heals or regenerates but he doesn't die. Those 20 times you hit him would kill him like 5 times already.. Then he goes back to base, heals and goes to another lane, where he dies by two hits from your ally and you would have an assistance.. that's not right.
OK. Now, imagine a boss fight, where it's regenerating and casting heals upon itself. The DPS hits it the whole time, wearing it down and causing it to expend its mana. Then, the nukers rush in and finish it off. Should the DPS not receive credit because its their damage that was healed away? That's not right. :p

Precise Damage Counter 1.5

As far as actual bugs, it strikes me that your system has the potential to create a lot of structs, since each occurrence of damage by alternating players is stored for every registered unit as long as that unit exists. Perhaps you should consider using Table (or just a hashtable...) In an AOS (as you gave as your example), it is basically guaranteed to overrun the struct limit if the game is of a certain length.

These lines:
JASS:
//...
            if (hp+dealt)&gt;dc.prev.prevhp and dc.prev.prevhp!=0 then
                set dc.healhp = dc.healhp + (hp+dealt-dc.prev.prevhp)

...seem to me like they should be:
JASS:
//...
            if hp&gt;dc.prev.prevhp-dc.prev.dealt and dc.prev.prevhp!=0 then
                set dc.healhp = dc.healhp + (hp+dc.prev.dealt-dc.prev.prevhp)

...because its previous HP minus the previous damage dealt will be the health it had after the last damage, and is the value which is the starting point for any healing since. Remember, [ljass]GetWidgetLife(u)[/ljass] upon a damage event is the value before damage is applied.

As such, I suspect (have not tested; don't have NewGen) that it won't recognize when a unit loses its health due to death and "heals" by coming back to life, despite the "prevHP != 0" condition.

Also, if a unit acquires and loses a +HP ability (eg. Khadgar's Gem of Health), their health scales proportionally to their maximum HP. The increase would be registered here as healing, but the decrease would not be registered as damage. This may also be true for adding str.

Your calculation in GetDamagePercentUnit doesn't make a lot of sense to me:
  • It assumes the unit started with full HP since maxlife is comprised of dc.hpbase which is taken from the unit's maximum possible life. (For that matter, why are you summing it for every dc struct, if that value is only ever saved in .first?)
  • You are comparing the damage to the unit's starting (assumed max) life plus healing, meaning the players' percents won't add to 100% unless the unit is dead, at which point the distribution will equal what I suggested, since by definition the unit will be dead if the total damages dealt equal its starting+regenerated HP.

In my opinion, your system needs a complete reworking with a carefully-considered rethinking of how you want to weight the value of damage done. Since it's near-impossible to tell whether healing was done by consuming mana or using potion, or done by a separate unit, or just regenerated naturally, it's therefore hard to judge whether the healing should offset the value of damage done beforehand.

It seems to me like some kind of devaluing-over-time approach with configurable scale is possible. Older instances of damage should be valued less if healed afterward, although they should not be devalued if the target has been engaged in combat the whole time (some soft cutoff of how long between damage instances is permitted before they start devaluing.)
 

Furby

Current occupation: News poster
Reaction score
144
Since I don't mod wc3 anymore, I have no mood to get into this again so you can either take this, remake it, no need for crediting or just graveyard it.

Thank all of you for your time and opinions. :)
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top