| 05-08-2009, 08:12 PM | #1 |
ArmorUtils Library Background: This is a library that allows calculation of a unit's armor, it's full damage (before armor reduction), and the reduced damage (after armor reduction). Someone reminded me recently that using Daelin's old system was a pain to use, so I decided to submit this. Daelin's system also didn't account properly for that gameplay constant 'Armor Damage Reduction Multiplier', but this script does. After making my code portable, writing some documentation, and developing a testmap, here it is! Requirements:
Library:library ArmorUtils requires Logarithm, optional IntuitiveDamageSystem //****************************************************************************** //* BY: Rising_Dusk //* //* This is used to get the exact armor of a given unit. It deals damage to the //* unit in order to determine armor, meaning that damage detection systems will //* detect it. If your map has the Intuitive Damage Detection System (IDDS) in //* it, it will use that system's internal ignored damage type for the check. //* Using that removes the need to disable/enable any damage detection triggers //* to avoid infinite loops. //* //* The attacktype constant, ATTACK_TYPE_USED, is by default set to use //* ATTACK_TYPE_CHAOS. Chaos is used because it deals 100% to all types, so if //* you change it in your map, make sure you update the constant to some type //* with 100% damage to all armor types. //* //* This system can also be used as a means to detect if a unit is invulnerable //* or not. If GetUnitArmor returns ARMOR_INVULNERABLE, then the unit is //* invulnerable. The value for it is entirely random and will never be the //* actual armor value for a unit, so there should be no conflicts. //* //* Damage reduction in WC3 due to negative armor is capped at -71%, which has //* an equivalent armor value of -20. If you have a unit with less than -20 //* armor, this system will always return exactly -20. //* //* Default WC3 gameplay constants have the 'Armor Damage Reduction Multiplier' //* set to 0.06. If you change this constant for your map, be sure to adjust the //* ARMOR_REDUCTION_MULTIPLIER constant in this script to match. //* //* Example Usage: //* local real armor = GetUnitArmor(MyUnit) //* //* Two other functions are included in this library. They are used for //* calculating a unit's base damage knowing armor-factoring damage and a unit's //* armor-factoring damage knowing its base damage. These functions do not //* consider armor type in their calculations. If you want armor type damage //* adjusting, it is recommended to trigger it. //* //* Example Usage: //* local real basedmg = GetFullDamage(MyUnit, Armor) //* local real armodmg = GetReducedDamage(MyUnit, Armor) //* //* An objectmerger call is included in this script to automatically generate //* the bonus life ability if necessary. If you do not modify the 'AIlz' ability //* in your map, you can replace the LIFE_BONUS_SPELL_ID constant with it and //* not use the objectmerger call. The //* globals //Values that should be changed for your map private constant real ARMOR_REDUCTION_MULTIPLIER = 0.06 private constant integer LIFE_BONUS_SPELL_ID = 'lif&' private constant attacktype ATTACK_TYPE_USED = ATTACK_TYPE_CHAOS //Values that do not need to be changed constant real ARMOR_INVULNERABLE = 917451.519 private constant real DAMAGE_TEST = 16. private constant real DAMAGE_LIFE = 30. private constant real NATLOG_094 =-0.061875 endglobals ////! external ObjectMerger w3a AIlz lif& anam "GetUnitArmorLifeBonus" ansf "" Ilif 1 30 aite 0 function GetUnitArmor takes unit u returns real local real life = GetWidgetLife(u) local real test = life local real redc = 0. local boolean enab = false local trigger trig = GetTriggeringTrigger() if u != null and life >= 0.405 then if GetUnitState(u, UNIT_STATE_MAX_LIFE) <= DAMAGE_TEST then //Add max life to keep it alive call UnitAddAbility(u, LIFE_BONUS_SPELL_ID) endif if life <= DAMAGE_LIFE then //If under the threshold, heal it for the moment call SetWidgetLife(u, DAMAGE_LIFE) set test = DAMAGE_LIFE endif static if LIBRARY_IntuitiveDamageSystem then //Use the IGNORED type in the IDDS if present so it is 100% ignored call UnitDamageTargetEx(u, u, DAMAGE_TEST, ATTACK_TYPE_USED, DAMAGE_TYPE_IGNORED, true) else if trig != null and IsTriggerEnabled(trig) then //Disable the trigger to prevent it registering with damage detection systems call DisableTrigger(trig) set enab = true endif call UnitDamageTarget(u, u, DAMAGE_TEST, true, false, ATTACK_TYPE_USED, DAMAGE_TYPE_NORMAL, null) if enab then //Re-enable the trigger call EnableTrigger(trig) endif endif set redc = (DAMAGE_TEST-test+GetWidgetLife(u))/DAMAGE_TEST //Remove the max life ability call UnitRemoveAbility(u, LIFE_BONUS_SPELL_ID) call SetWidgetLife(u, life) set trig = null if redc >= 1. then //Invulnerable return ARMOR_INVULNERABLE elseif redc < 0. then //Negative Armor return -Log(redc+1.)/NATLOG_094 else //Positive Armor return redc/(ARMOR_REDUCTION_MULTIPLIER*(1.-redc)) endif endif set trig = null return 0. endfunction function GetReducedDamage takes real baseDamage, real armor returns real if armor >= 0. then return baseDamage*(1.-((armor*ARMOR_REDUCTION_MULTIPLIER)/(1.+ARMOR_REDUCTION_MULTIPLIER*armor))) else return baseDamage*(2.-Pow(0.94,-armor)) endif endfunction function GetFullDamage takes real damage, real armor returns real if armor >= 0. then return damage/(1.-((armor*ARMOR_REDUCTION_MULTIPLIER)/(1.+ARMOR_REDUCTION_MULTIPLIER*armor))) else return damage/(2.-Pow(0.94,-armor)) endif endfunction endlibrary Function List: This library gives the following armor and damage manipulating functions.
|
| 05-08-2009, 08:17 PM | #2 |
GetUnitArmor shouldn't returns an integer instead of a real ? |
| 05-08-2009, 08:18 PM | #3 |
Heroes can have non-integer armor values. They display an integer, but for calculations they use the actual real value. |
| 05-08-2009, 08:33 PM | #4 | |
Quote:
For example you get 1.5236 with your function GetUnitArmor(), does it really takes 1.5236 or 1.524 when the unit receive damages ? Maybe it's irrelevant in the result, just a thought. |
| 05-08-2009, 08:42 PM | #5 | |
Quote:
|
| 05-08-2009, 08:53 PM | #6 | |
Quote:
|
| 05-08-2009, 09:10 PM | #7 |
I have never heard of it rounding at all, so I'm not worried. I have dinner and a movie to go to, so test it yourself if you care. :p |
| 05-08-2009, 09:14 PM | #8 |
It doesn't round up, but in text messages it does only display 3 digits after the comma. |
| 05-08-2009, 09:16 PM | #9 | |
Quote:
@Rising_Dusk : I will test it myself later, good evening. |
| 05-09-2009, 07:35 AM | #10 |
Thank god my bugging made you post this, next up is hero selection system :) |
| 05-09-2009, 10:33 AM | #11 |
theres no way to modify the damage increase when a units armor is less than 0. Its hardcoded to 0.06, and hardcapped at seventy something percent damage increase, iirc. |
| 05-09-2009, 10:53 AM | #12 |
You could use Vex's Logartihm to detect armor below 0. |
| 05-09-2009, 11:35 AM | #13 |
I've tested, and sometimes the actual damage is exactly the same as the calculated damage and sometimes not, but the imprecision is for the eight number under the digit, so it doesn't really matter (at all). |
| 05-09-2009, 12:20 PM | #14 |
You should probably include a note that changes to Chaos Damage in Gameplay Constants will break this. |
| 05-09-2009, 07:13 PM | #15 | |
Did I not? I thought I did in that massive documentation. Huh, guess I didn't. Thanks for bringing it to my attention. Quote:
|
