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
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).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
The one posted by Mythic? You shouldn't because a lot of wc3's hardcoded mechanics break it, meaning it will return wrong values.and how can we use that get armor library? lol
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)
The thought you had is what those two already posted smaller getArmor libraries are doing.just had the thought. If I am intrested about particular units armor, then I dmg that unit for 1 or 100
As posted earlier:Ezekiel12 can you pleas explain better why we should not use that system ?
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.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).