in this blog post I'd like to present you a method that allows us to determine the damage type distributions, both in relative proportions to each other and in absolute magnitude, of enemies, without requiring their weapons being available as player weapons.
The restriction to this method is that it only supports damage type distributions consisting of up to three different damage types and they must vary in their modifiers to player health-and-armor, armor and shields. Fortunately, this condition is complied for all weapons or damage sources that we know of, as they all consist either of a distribution of the three physical damage types, or of only one elemental damage type, with the so far singular exception of the Mire. As the solution for only one damage type is trivial, we will focus on distributions over the three physical damage types.
Purpose and Significance
The motivation to tackle this issue mostly comes from the optimization problems around defensive measures in Warframe. The easiest: Redirection vs Vitality? To properly answer such questions in marginal cases, one should consider how many effective hitpoints one actually gains from these mods against the enemies one is going to face. In the past, this has often been done in disregard of enemy damage type modifiers. A prime example of how elusive this can be is the very common Detron-armed Crewman. Disregarding type modifiers, a rank 30 Valkyr with Steel Fiber and Vitality expects to have 3,848 effective health. Against the damage of these Crewmen, however, her effective health is only ~866.6 - less than a fourth of what she expected. This may lead to nasty surprises in some situations. While the effect is alleviated by the presence of other enemies with less extreme modifiers, there is a general systematic trend of modifiers in the various factions, and some differences between the various types of the same faction which should be regarded situationally, as this makes these enemy types more or less threatening whether the damage is taken by shields or by health.
These were just some quick examples of how the damage type distributions of enemies we face should matter to us. Beyond the proportions and average modifiers, the method presented here allows us to actually quantify absolute enemy (base) damage values to put them into perspective.
A remaining issue not treated in this article is the status effects mechanics and values of enemies, as especially Bleed procs are often a significant part of the enemy damage potential, but this can not be covered here.
The described and explained method can be used by anyone to determine the base damage type distributions of any enemy type with relative metrological ease.
Premise: What damage types are present?
One indicator to answer this question is the status effects triggered by the examined enemy on the players. Any status effect occuring means that its corresponding damage type must be present in the damage type distribution. In the case of enemies using weapons who can also be obtained by the player, we can simply look at that weapon's stats directly, which also gives us the damage type proportions already. In this case, this method could be used as a check on whether the values have been changed from the enemy to player variant of the weapon, and to determine the absolute values for the enemy variant.
Heuristically, we simply assume any weapon to have a damage type distribution consisting of Impact, Puncture and Slash (physical damage), unless that weapon has shown to proc elemental status effects, in which case we assume it to only deal this elemental damage type. We will then later see whether our assumption of damage types present in the distribution can explain our measurement data or not. False negatives to this are impossible, but false positives are not. So, while the method not giving a reaonsable solution does certainly disprove the possibility of the assumed damage types comprising the distribution, the method giving a reasonable solution does not necessarily prove that the assumed damage types are the actual damage types present. Other combinations may also pass the test. When in doubt, this has to be checked independently.
For practically all cases however, we do know what damage types are present, as it's usually the three physical or any one elemental type identified by its status effect.
From now on, we assume an examined enemy damage source to be comprised of the three physical damage types, since the single elemental solutions are, as mentioned earlier, trivial.
The measurements on which the test is based are surprisingly simple.
- You should unequip your companion and equip a warframe capable of slowing down enemies, e.g. Nova Prime. Note your armor value.
- Start an Exterminate mission in Solo where the enemy type to be examined occurs. Find him, slow him, single him out by killing all other enemies in the room. Note its level.
- Let it hit your shields and note the damage it dealt to them with one hit. It is your shield value before minus your shield value after the hit.
- When your shields are depleted, let it hit your health and note the damage it dealt to it with one hit. It is your health value before minus your health value after the hit.
- Cancel the mission, equip or unequip Steel Fiber depending on whether or not you got it equipped earlier, note your new armor value.
- Restart the mission, find another of the examined enemy type at the same level as the previous one. Same procedure.
- This time you only need to note the damage it deals to your health with one hit.
As a result, you got the following measurement data:
- Damage to your shield.
- Damage to your health at armor value #1.
- Damage to your health at armor value #2.
- Enemy level.
These will all be used in the following analysis.
To give a rough outline:
- We will be using the measured information on how our known change to armor changed the received damage to extrapolate the armor modifier of the received damage distribution.
- We will then proceed to rule out the impact of our armor value and get the ratio of damage to warframe shield and damage to warframe armored health at 0 armor (while retaining the armor type's damage modifiers).
- Taking into consideration that our damage distribution only consists of three different types of damage, we can then solve a system of three equations with three variables, the proportions of each of the three physical damage types, to determine each of them.
- This allows us to calculate the armored health modifier and shield modifier.
- Applying this to the original values of received damage, we get the absolute total gross damage of the enemy at its level, which also gives us the absolute gross damage of each type with the known proportions.
- Finally, we can remove the level scaling factor to obtain the base level values.
A short recapitulation: The armor modifier is a quantity dependent on the damage type distribution of the applied damage that defines how the armor value of the target (in this case the player) affects the incoming damage. There are two ways to numerically define this quantity, which must not be confused: Either as armor multiplier AMu in the sense of AD=1+Ar*AMu/300 or as armor mitigation AMi in the sense of AD=1+Ar*(1-AMi)/300. AMu=1-AMi and AMi=1-AMu. As an example, pure Slash damage against Alloy armor has AMu=1.5 which indicates that armor counts 1.5 times for the reduction of its damage, and AMi=-0.5, indicating that it mitigates -50% of the target's armor, meaning that the armor is +50% more effective towards this damage. As you can see, the information is equivalent, the one contains no information that is not also contained in the other, and you can arbitrarily transform one into the other, you just must not confuse them.
Back to our analysis. The damage modification is expressed by the formula:
- DHi = GD * AHM / ADi with ADi = 1 + Ari * AMu / 300
- DHi is the net damage to armored health at armor value indexed i
- GD is the gross damage.
- AHM is the armored health modifier
- ADi is the armor divisor at armor value indexed i.
- AMu is the armor modifier in the sense of armor multiplier.
- Ari is the armor value indexed i.
We have two couples of values for Ari and DHi. GD and AHM are constant. We can therefore transform and equate these for both pairs of values:
- DHi * ADi = GD * AHM , therefore DH1 * AD1 = DH2 * AD2
We can now insert the armor divisors with our known armor values and solve the equation for the armor multiplier:
- DH1 * ( 1 + Ar1 * AMu / 300 ) = DH2 * ( 1 + Ar2 * AMu / 300 ) <=>
- DH1 + DH1 * Ar1 * AMu / 300 = DH2 + DH2 * Ar2 * AMu / 300 <=>
- DH1 * Ar1 * AMu / 300 - DH2 * Ar2 * AMu / 300 = DH2 - DH1 <=>
- ( DH1 * Ar1 - DH2 * Ar2 ) / 300 * AMu = DH2 - DH1 <=>
- AMu = 300 * ( DH2 - DH1 ) / ( DH1 * Ar1 - DH2 * Ar2 )
So we got the exact value for the armor multiplier of the entire damage distribution. We also know that this is the weighted arithmetic mean of the armor multipliers of the damage types comprising it, weighted by their proportions of the total damage. Formulating the mitgation instead of the multiplier in this case has the advantage that the impact proportion is omitted, as it has no direct effect on the armor mitigation, only indirectly through scaling down the other proportions:
- AMi = 0.25 * ppun - 0.5 * psla with
- AMi = 1 - 300 * ( DH2 - DH1 ) / ( DH1 * Ar1 - DH2 * Ar2 )
This is the first of the connections comprising our equation system to solve later on, so we will come back to it.
Armored Health Modifier to Shield Modifier Ratio
For the second information, we compare the damage that was inflicted to shields to the damage that was inflicted to health after ruling out the influence of the armor divisor. We know that the two have the same cross damage and just differ in their damage modifiers to account for the difference in inflicted damage, which is another two connections which we can equate for their constant proportion:
- DS = GD * SM <=> DS / SM = GD and DH = GD * AHM / AD <=> DH * AD / AHM = GD
- therefore DS / SM = DH * AD / AHM <=> AHM / SM = DH * AD / DS
We know all factors of the right side of the last equation, therefore we know the value of this ratio, but not the actual values of AHM and SM individually, yet.
Similar to our procedure with the armor mitigation, we can apply that AHM and SM are the weighted averages of the multipliers of each damage type weighted by their proportions of the total damage. Note that we use the multipliers this time, not the difference from neutrality (one).
- AHM / SM = ( 0.75*pimp + 1.25*ppun + 0.625*psla ) / ( 1.5*pimp + 0.75*ppun + psla )
This is the second equation for the equation system. "0.625" here is the product of the Slash modifiers to warframe health and armor, 1.25 * 0.5 = 0.625.
Closure of the Distribution
This piece of information is implicitly self-explaining, but its value may not be immediately obvious. We know (or at least assume) that the distribution is comprised only of the three physical damage types. These three taken together makes the distribution complete:
- pimp + ppun + psla = 1
The three proportions are all greater than or equal to zero and smaller than or equal to 1, with their total being equal to 1. This is the third and last equation comprising the equation system. We can now start solving it.
Damage Type Proportions - Solving the Equation System
It is opportune to start with armor mitigation equation, as it is already reduced to only two of our three variables, ppun and psla. It allows us to express either of the two through the other and some values which we already calculated earlier.
- AMi = 0.25 * ppun - 0.5 * psla <=>
- AMi + 0.5 * psla = 0.25 * ppun <=>
- 4 * AMi + 2 * psla = ppun
We can now insert the expression to replace ppun into the third equation:
- pimp + ppun + psla = 1 <=>
- pimp + ( 4 * AMi + 2 * psla ) + psla = 1 <=>
- pimp + 4 * AMi + 3 * psla = 1 <=>
- pimp = 1 - 4 * AMi - 3 * psla
By inserting both of these expressions into the second equation, we get one equation with only one variable, which we can finally solve exactly:
- AHM / SM = ( 0.75*pimp + 1.25*ppun + 0.625*psla ) / ( 1.5*pimp + 0.75*ppun + psla ) <=>
- AHM / SM = ( 0.75*(1-4*AMi-3*psla) + 1.25*(4*AMi+2*psla) + 0.625*psla ) / ( 1.5*(1-4*AMi-3*psla) + 0.75*(4*AMi+2*psla) + psla ) <=>
- AHM / SM = ( 0.75 - 3*AMi - 2.25*psla + 5*AMi + 2.5*psla + 0.625*psla ) / ( 1.5 - 6*AMi - 4.5*psla + 3*AMi + 1.5*psla + psla) <=>
- AHM / SM = ( 0.75 + 2*AMi + 0.875*psla ) / ( 1.5 - 3*AMi - 2*psla ) <=>
- AHM / SM * ( 1.5 - 3*AMi - 2*psla ) = 0.75 + 2*AMi + 0.875*psla <=>
- 1.5*AHM/SM - 3*AMi*AHM/SM -2*AHM/SM*psla = 0.75 + 2*AMi + 0.875*psla <=>
- 1.5*AHM/SM - 3*AMi*AHM/SM - 0.75 - 2*AMi = 0.875*psla + 2*AHM/SM*psla <=>
- AHM/SM * ( 1.5 - 3*AMi ) - 0.75 - 2*AMi = ( 2*AHM/SM + 0.875 ) * psla <=>
- psla = ( AHM/SM * ( 1.5 - 3*AMi ) - 0.75 - 2*AMi ) / ( 2 * AHM/SM + 0.875 )
By re-inserting this into the equations for pimp and ppun, we can determine these respective proportions as well:
- ppun = 4*AMi + ( AHM/SM * ( 3 - 6*AMi ) - 1.5 - 4*AMi ) / ( 2 * AHM/SM + 0.875 )
- pimp = 1 - 4*AMi - ( AHM/SM * ( 4.5 - 9*AMi ) - 2.25 - 6*AMi ) / ( 2 * AHM/SM + 0.875 )
Now we know the exact relative proportions of each of the three physical damage types in the damage distribution that we got attacked with, which may already be what we wanted, but we can get even more out of it.
Armored Health Modifier and Shield Modifier
As you may remember, we were able to tell the ratio of armored health modifier to shield modifier, but not there actual values. Since the proportions of the damage distribution are now known, we can calculate these:
- AHM = 0.75 * pimp + 1.25 * ppun + 0.625 * psla
- SM = 1.5 * pimp + 0.75 * ppun + psla
Total Gross Damage
With the modifiers now known, we can come back at the absolute magnitude of the damage taken:
- GD = DS / SM and GD = DH * AD / AHM
should both yield the same result. I am currenly not sure if this would give the exact same result or if the rounding error of DS and DH expresses itself in a slight deviation here, but even if it does, it should be miniscule and the result almost equal. This is a nice quick check if anything went terribly wrong during the calculation.
Total Base Level Damage
Since we noted the level of the enemy who inflicted the damage and its base level and the damage scaling formula are established, we can remove the influence of the level scaling factor to determine the base damage of the enemy.
- GD = BD * ( 1 + 0.013 * ( cl - bl )^1.6 ) <=> BD = GD / ( 1 + 0.013 * ( cl - bl )^1.6 )
Base Level Damage Type Distribution
To conclude the analysis, we can use the calculated total base damage and damage type proportions to determine the base level damage type distribution in its absolute values. This last step is quite trivial.
- Base Impact Damage = BD * pimp
- Base Puncture Damage = BD * ppun
- Base Slash Damage = BD * psla
Which is ultimately everything we hoped to get out of this, rejoice!
Accuracy, Reliability and Limits of the Test
As mentioned earlier, this method relies on you knowing beforehand what damage types are present. If it yields funny results like negative proportions and proportions greater than one, you know for sure that the observed shield damage to health damage ratio can not be explained as a result of the assumed damage types. Just conversely, you can not take reasonable result as a definite proof that the assumed damage types are the actual ones of the examined damage type distribution - technically.
As mentioned in the beginning, proof of the presence of a certain damage type can be the occurence of its status effect. If a damage type assumed to be in the distribution actually is not, it will not deteriorate the results in any way, because the test will simply output 0 for its proportion - only the opposite case will, when a damage type is assumed not to be in the distribution but actually is, because its influence on the modifiers will be falsely attributed to other damage types.
Regardless of assumed damage types, the determination of the armor modifier will always be reliable, and so will be the AHM to SM ratio. At this point, you can already check beforehand if a physical damage distribution is eligible, as physical damage can only produce AHM/SM ratios from 0.5 (for pure impact damage) to 1.(6) (for pure puncture damage). Every damage type has its own definite AHM/SM ratio and armor modifier against warframes:
Thereby you can identify what damage type is used in the case of pure, single-type damage. It shows that Heat, Blase and Corrosive damage are indistinguishable based on their damage to warframes, they can only be identified by their status effects, or, if this isn't possible either, by turning other enemies against the ones examined by the use of confusing or charming abilities (Mind Control, Chaos, Shadows of the Dead, Radiation damage status effect, etc.).
The table doesn't replace the thorough calculation because it only accounts for a single damage type being present, whereas the whole purpose of the calculation was the unravel a distribution of up to three.
The calculation was done specifically for the three physical damage types. A generalization is probably possible for any three given damage types which are distinguishable in AMu and AHM/SM. To encompass more than three damage types, more information is required. For example, Toxin or Finisher damage could be isolated from the distribution by measuring the damage to health while shields are intact, with the to being distinguishable against each other through their armor modifier (less damage at higher armor -> Toxin, same damage -> Finisher). The remaining damage can then be analyzed exactly as above.
Without any evidence of a non-player-controlled source of mixed elemental damage (not to be confused with combined elemental damage - I mean a distribution of more than one elemental or combined elemental damage type), there is no need to elaborate further on this subject.
A much more serious practical problem for the accuracy of this method is that of damage rounding. As damage to your health or shield is rounded to an integer and most enemies deal rather low damage with each hit, the relative error introduced with rounding is quite significant, especially since the calculated value for AMu and AMi is really sensitive towards small changes in the parameters. You should generally perform the procedure multiple times, each time picking the upper or lower limit of each value, and see how it affects the range of possible results. Another problem associated with this is finding the limits of the prior value from the posterior rounded integer, because the exact rounding procedue of the game engine is still a bit unclear (previous research data was shown to be obsolete; more on this problem here). Regardless of the rounding mechanic used, the proper way to alleviate the influence of rounding errors on the calculated values is obtaining large measurement values to reduce the relative error on these values from rounding. This means, taking damage from enemies at levels as high as possible and choosing two armor value far apart from each other for the armor modifier, then using the one at the low armor value as basis for the AHM/SM calculation.
I hope that I managed to present the topic as understandable as possible at its complexity, and that I could share some excitement about the situation that we, the Warframe community, without any decompilation of game code or much info from the developers, have claimed the ability to extract such valuable hidden information from the game. It will allow us to refine our target priorities against each faction under any specific circumstances, and to more accurately evaluate the utility of defensive measures of many kinds, from choosing defensive warframe mods to choosing specters.
I am looking forward to any feedback and contributions, the former showing which chapters or abstracts need clarification or rework, the latter employing the presented method to actually gain info on the various enemy types' damage potentials. Please share your thoughts and results in the comments.