• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Precise Damage Counter

Level 4
Joined
Feb 18, 2008
Messages
69
auwqh4.png

v1.4

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

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() > GetWidgetLife(u) then
                set dmgPercent = 100.0 * (GetWidgetLife(u) / GetUnitState(u, UNIT_STATE_MAX_LIFE))
                set over = dmgPercent - (100 - done)
            endif
            if over > 0 then
                set dc = first
                loop
                    exitwhen(over <= 0.0 or dc == 0)
                    if dc.percent - over > 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 > 0 then
                            set dc = dc.next
                        endif
                        call temp.destroy()
                    endif
                endloop
                if dc > 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 > 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>15)
            if GetDamagePercentUnit(whatUnit, Player(i)) > temp then
                set result = Player(i)
                set temp = GetDamagePercentUnit(whatUnit, Player(i))
            endif
            set i = i + 1
        endloop
        return result
    endfunction
    
endlibrary

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: 213
Last edited:

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
Why do you have both actions and conditions? Just use one or the other.

Instead of onDestroy, override the destroy method and use .deallocate(). Otherwise you are looking at a trigger evaluation and duplication of the method in the compiled code.

For the same reason, move the AIDS macro to the bottom of the struct.

The functions don't need to be prefixed with PDC_, which is bad convention anyway. If you want prefixes just make them struct methods.

Edit: Oh wait, you havent been online in almost a year. Well, to the graveyard with this then. Maybe we'll see it re-written.
 
Top