• 🏆 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!

[Spell] armor based damage

Status
Not open for further replies.
Level 23
Joined
Apr 16, 2012
Messages
4,041
calculation is not that complex in reality. There are few scripts on this site in fact, that will return you the armor of unit. If my memory serves me right, it was actually either Dalvengyr or Jad(T. D. W I think is his name now) who proposed one on hive
 
Ok

GetArmor/Damage Library by Malhorne
JASS:
library GetDamage requires Table
    globals
        private HandleTable tab
        private HandleTable damage
        //Set this to true if you want this system to get the attack damage of every unit of your map.
        //But be aware that this may lag.
        //If you let this to false then you will have to use the function Add(unit) to add a unit to this system.
        private constant boolean ALL_UNITS = false
        private constant integer DUMMY_ID = 'd000'
        private constant real ARMOR_CONSTANT = 0.06
    endglobals
    
    static if not ALL_UNITS then
        globals
            private group UNITS = CreateGroup()
        endglobals

        public function Add takes unit u returns nothing
            call GroupAddUnit( UNITS, u )
        endfunction
    endif
    
    public function GetDamage takes unit u returns integer
        return damage[u]
    endfunction
    
    public function GetArmor takes unit u returns real
        local real life = GetWidgetLife( u )
        local real life2
        local real x = GetUnitX( u )
        local real y = GetUnitY( u )
        local unit v = CreateUnit( Player(15), DUMMY_ID, x, y, 0 )
        local real test = 10
        if GetWidgetLife(u) > 200 then
            set test = 100
        endif
        call UnitDamageTarget( v, u, test, true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_NORMAL, null )
        set life2 = life - GetWidgetLife( u )
        call RemoveUnit( v )
        set v = null
        call SetWidgetLife( u, GetWidgetLife( u ) + life2 )
        if ( life2 > test ) then
            return (-1*(test - life2 ) ) / ( life2 * ARMOR_CONSTANT ) 
        else
            return ( test - life2 ) / ( life2 * ARMOR_CONSTANT )
        endif
    endfunction
    
    private struct Damage extends array
        unit attacker
        unit attacked
        trigger t
        thistype recycle
        static integer instanceCount
        static thistype recycleNext
        
        static method cond2 takes nothing returns boolean
            local thistype this
            if tab[GetEventDamageSource()] != 0 then
                set this = tab[GetEventDamageSource()]
                set damage[this.attacker] = R2I(GetEventDamage())
                call tab.flush(this.attacker)
                call DestroyTrigger(this.t)
                set this.attacker = null
                set this.attacked = null
                set this.t = null
                call this.destroy()
            endif
            return false
        endmethod
        
        static method cond takes nothing returns boolean
            local thistype this
            local boolean b = true
            static if not ALL_UNITS then
                if not IsUnitInGroup(GetAttacker(), UNITS) then
                    set b = false
                endif
            endif
            if b then
                if recycle == 0 then
                    set instanceCount = instanceCount + 1
                    set this = instanceCount
                else
                    set this = recycle
                    set recycle = recycle.recycleNext
                endif
                set this.attacker = GetAttacker()
                set this.attacked = GetTriggerUnit()
                set this.t = CreateTrigger()
                set tab[this.attacked] = this
                call TriggerRegisterUnitEvent( this.t, this.attacked, EVENT_UNIT_DAMAGED )
                call TriggerAddCondition( this.t, Condition( function thistype.cond2 ) )
            endif
            return false
        endmethod
        
        method destroy takes nothing returns nothing
            set recycleNext = recycle
            set recycle = this
        endmethod
        
        private static method onInit takes nothing returns nothing
            local trigger t = CreateTrigger()
            call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_ATTACKED )
            call TriggerAddCondition( t, Condition(function thistype.cond) )
            set tab = HandleTable.create()
            set damage = HandleTable.create()
            set instanceCount = 0
            set recycleNext = 0
            set t = null
        endmethod
    endstruct
endlibrary
 
Level 12
Joined
Mar 13, 2012
Messages
1,121
calculation is not that complex in reality. There are few scripts on this site in fact, that will return you the armor of unit. If my memory serves me right, it was actually either Dalvengyr or Jad(T. D. W I think is his name now) who proposed one on hive
There is always that one person saying "it's not that complex". Here are about a dozen reasons why it is: mana shield, damage block, invincibility, unit is dead, unit is illusion, any damage % altering ability like defend/berserk/etc, ethereal state, bad damage trigger config, wrong damage/attack type, damage instance messing things up (units wake up/run around/etc).

And there are even more reasons why getting attack damage fails.
Often it's better to list all abilities/upgrades/buffs/base armor/etc. affecting armor and check for them on the unit to get it.

So even having a complete DDS it might be very complex depending on your map.
 
If you need a pro solution to this problem:

Make all units have 0 armor, then use bonus mod to trigger all armor in your map.


You will eventually come to the point in mapping where you just go with default values for everything (attack speed, attack range, movement speed, attack, armor, etc.) and just use bonusmod to set the individual values.
 
Level 12
Joined
Mar 13, 2012
Messages
1,121
and how can we use that get armor library? lol
The one posted by Mythic? You shouldn't because a lot of wc3's hardcoded mechanics break it, meaning it will return wrong values.
 
Level 12
Joined
Mar 13, 2012
Messages
1,121
I found this but I dont know how to use it

It's uses the same flawed detection and should not be used.

Here is what you could do if you really need it:

a) use a full DDS (or that bonus mod thing mentioned, though I never had a look at it) which manages everything for you
b) you have a data structure with all things that affect armor in your map and check for those buffs/upgrades/etc. when calling the getArmor function
c) you know exactly whats going on in wc3 and your map and use the flawed easy system that damages units to get the armor value (bad because it's very limited and most people will overlook bugs)
 
Level 16
Joined
May 2, 2011
Messages
1,345
It's uses the same flawed detection and should not be used.

Here is what you could do if you really need it:

a) use a full DDS (or that bonus mod thing mentioned, though I never had a look at it) which manages everything for you
b) you have a data structure with all things that affect armor in your map and check for those buffs/upgrades/etc. when calling the getArmor function
c) you know exactly whats going on in wc3 and your map and use the flawed easy system that damages units to get the armor value (bad because it's very limited and most people will overlook bugs)


there should be more clever solution. You want me to get each level of devotion aura? and rings of protection? and agility? meh
________________________________________________________________

just had the thought. If I am intrested about particular units armor, then I dmg that unit for 1 or 100 . Use DDS to detect the reduction. Ratio is the thing im looking for. then I set the dmg to zero.

So basically, the unit we are intrested in is the unit attacked by unit that does damage based on the armor. the thing is, if we can just run the trigger 1 second before we hit it. or maybe we can store the armor for all the units?

by the way, is OPer aware of DDSs
 
Last edited:
Level 12
Joined
Mar 13, 2012
Messages
1,121
just had the thought. If I am intrested about particular units armor, then I dmg that unit for 1 or 100
The thought you had is what those two already posted smaller getArmor libraries are doing.
Ezekiel12 can you pleas explain better why we should not use that system ?
As posted earlier:
Here are about a dozen reasons why it is: mana shield, damage block, invincibility, unit is dead, unit is illusion, any damage % altering ability like defend/berserk/etc, ethereal state, bad damage trigger config, wrong damage/attack type, damage instance messing things up (units wake up/run around/etc).
Every point in there will mess up armor detection based on dealing damage. Therefore the system is bad, as it does not work in so many maps and often the user of the system isn't even aware of it.
 
Level 16
Joined
May 2, 2011
Messages
1,345
I can go about most of these. the list is much shorter than all itm and armor buff list. defend use chaos. berserk multiply. damage block take it into account for the specific units. wrong attack use chaose. etheral use magic attack and will work if etheral units have armor (wait, do they?) mana sheild make it absorb 99% of the dmg

invincibilty as in invulnerabilty? return nothing then XD
 
Status
Not open for further replies.
Top