Updated Diminishing Returns Coefficients – All Tanks

A few weeks ago, Taser contacted me about calculating the avoidance diminishing returns coefficients for monks to greater accuracy.  As you might remember, we managed to do this for paladins a little less than a year ago by using an addon called Statslog.  Prior to that post, we had already determined coefficients for PaladinsDruids and Brewmaster Monks, but via a less rigorous data collection method (the character sheet) that gave less accurate estimates of the true value of these constants.

For example, we were able to peg the k-factor for monks at $k=1.422$, but the dodge and parry caps had a much wider range of possible values.  The best we could do for those were:
$C_p = 91 \pm 7$
$C_d = 505 \pm 25$

That’s not super-accurate, and while they give reasonable enough results, it’s always nice to have better accuracy.  We’re also aided by the fact that we now know the exact conversion rates of strength to parry and agility to dodge for all five tanking classes, which eliminates some unknowns.

I asked Taser to collect a data set for me using Statslog so that I could perform a more accurate analysis on monks, and he graciously agreed.  After calculating the results and updating Simcraft, I realized that we may as well cover the other three tanks, so I collected data sets for druids, death knights, and warriors.

I also spent some time updating my methods for performing these fits.  In the past, calculating these fits generally meant spending a bunch of time in MATLAB hand-arranging the data and then working with the curve fitting toolbox GUI.  It also means that every time I sit down and do these calculations, I end up with slightly different methods.  Thus, I had a folder full of MATLAB files from different months, all doing the same thing in slightly different ways.

I decided it was time to streamline, so I cleaned up all of that mess and built an efficient system that I can use for all five classes.  Now all I need to do is change the text file containing the data, and the various functions I’ve written to parse, arrange, and fit the data do all the hard work for me.

Monk

This is Taser’s data, which was rather extensive.  He was very clever and used the Steadfast Talisman of the Shado-Pan Assault to achieve incredible coverage of the dodge surface, which led to an excellent fit.  Below are the plots, followed by the fitting data.  After the goodness-of-fit information, I’ve given the values for $C$ and $k$ to roughly the accuracy that the fit allows.

Monk dodge surface fit generated from Taser's 5.4 PTR data

Monk dodge surface fit generated from Taser’s 5.4 PTR data

Monk dodge surface residuals (deviation of fit from measured values)

Monk dodge surface residuals (deviation of fit from measured values)

 

##### Dodge Fit #####

     General model:
     dfit(x,y) = 3+111/951.158596+(x/951.158596+y)/((x/951.158596+y)/C+k)
     Coefficients (with 95% confidence bounds):
       C =       501.3  (501.3, 501.3)
       k =       1.422  (1.422, 1.422)

           sse: 1.0609e-010
       rsquare: 1.0000
           dfe: 151
    adjrsquare: 1.0000
          rmse: 8.3822e-007

 C = 501.25348 +/- 0.00032
 k = 1.422000108 +/- 0.000000038
Monk parry surface fit using Taser's 5.4 PTR data.

Monk parry surface fit using Taser’s 5.4 PTR data.

Monk parry surface residuals  (deviation between fit and measured values)

Monk parry surface residuals (deviation of fit from measured values)

 

##### Parry Fit #####

     General model:
     pfit(x,y) = 8+95/10000.000000+(x/10000.000000+y)/((x/10000.000000+y)/C+k)
     Coefficients (with 95% confidence bounds):
       C =       90.64  (90.64, 90.64)
       k =       1.422  (1.422, 1.422)

           sse: 4.0761e-011
       rsquare: 1.0000
           dfe: 151
    adjrsquare: 1.0000
          rmse: 5.1956e-007

 C = 90.64244 +/- 0.00014
 k = 1.42200013 +/- 0.00000018

As you can see, this method does a LOT better.  We’ve confirmed our $k$ value to more decimal places and have narrowed down the range on $C_p$ and $C_d$ to almost 4 decimal places.

To summarize the results:

$k = 1.422000(13) \pm 0.00000018$
$C_d = 501.253(48) \pm 0.00032$
$C_p =90.642(44) \pm 0.00014$

Monks also get 1% parry from 10000 strength and 1% dodge from 951.158596 agility.

Druid

This is data that I collected using a pre-made character on the PTR.  Thus, I didn’t have access to the valor trinket, but I made up for it by using the free T16 gear (thanks Flaskataur!) and trying lots of reforge and gemming configurations to try and cover as much of the surface as possible.  We also don’t need to worry about parry for the druids, since that’s identically zero.

This time I’ll link the residuals plots, but not show them explicitly.

Druid dodge surface using 5.4 PTR data.

Druid dodge surface using 5.4 PTR data.

residuals

##### Dodge Fit #####

     General model:
     dfit(x,y) = 5+99/951.158596+(x/951.158596+y)/((x/951.158596+y)/C+k)
     Coefficients (with 95% confidence bounds):
       C =       150.4  (150.4, 150.4)
       k =       1.222  (1.222, 1.222)

dgof = 

           sse: 6.4926e-011
       rsquare: 1.0000
           dfe: 115
    adjrsquare: 1.0000
          rmse: 7.5138e-007

 C = 150.375938 +/- 0.000041
 k = 1.222000009 +/- 0.000000045

Again, this gives a better confidence interval than our previous attempt.  Last time, we were only certain of the dodge cap to $\pm 0.2$.  This time, we’re accurate to $\pm 0.000041$.  To summarize

$k = 1.2220000(09) \pm 0.000000045$
$C_d =150.3759(38) \pm 0.000041$

Druids also get 1% dodge from 951.158596 agility, and obviously gain no parry from strength.

Death Knight

Again, this is my own data set, using a pre-made character and buying all of the T16 gear.  This time I used both DPS and Tanking sets to try and get wider coverage of both surfaces.

Death Knight dodge surface using 5.4 PTR data.

Death Knight dodge surface using 5.4 PTR data.

residuals

##### Dodge Fit #####

     General model:
     dfit(x,y) = 5+131/10000.000000+(x/10000.000000+y)/((x/10000.000000+y)/C+k)
     Coefficients (with 95% confidence bounds):
       C =       90.64  (90.64, 90.64)
       k =       0.956  (0.956, 0.956)

dgof = 

           sse: 9.8586e-012
       rsquare: 1.0000
           dfe: 129
    adjrsquare: 1.0000
          rmse: 2.7645e-007

 C = 90.642574 +/- 0.000010
 k = 0.956000090 +/- 0.000000018
Death Knight parry surface using 5.4 PTR data.

Death Knight parry surface using 5.4 PTR data.

residuals

##### Parry Fit #####

     General model:
     pfit(x,y) = 3+209/951.158596+(x/951.158596+y)/((x/951.158596+y)/C+k)
     Coefficients (with 95% confidence bounds):
       C =       237.2  (237.2, 237.2)
       k =       0.956  (0.956, 0.956)

pgof = 

           sse: 1.9542e-010
       rsquare: 1.0000
           dfe: 129
    adjrsquare: 1.0000
          rmse: 1.2308e-006

 C = 237.18614 +/- 0.00015
 k = 0.956000019 +/- 0.000000055

Again, excellent accuracy.  Here’s the summary:

$k = 0.9560000(90) \pm 0.000000018$
$C_d = 90.6425(74) \pm 0.000010$
$C_p = 237.186(14) +/- 0.00015$

I could probably improve the parry fit a little by grabbing more points in the high-parry-rating, low-strength region, but this is good enough to give exact character sheet results.

Death Knights also get 1% parry from 951.158596 strength and 1% dodge from 10000 agility.

Warrior

Warriors took the longest because there’s block to consider.  So I had to gem/gear for strength, then convert to dodge, then parry, then mastery.  And then write another fitting function for the block fit.  However, I’m quite pleased with the results.

Warrior dodge surface using 5.4 PTR data

Warrior dodge surface using 5.4 PTR data

residuals

##### Dodge Fit #####

     General model:
     dfit(x,y) = 5+133/10000.000000+(x/10000.000000+y)/((x/10000.000000+y)/C+k)
     Coefficients (with 95% confidence bounds):
       C =       90.64  (90.64, 90.64)
       k =       0.956  (0.956, 0.956)

dgof = 

           sse: 8.2286e-012
       rsquare: 1.0000
           dfe: 164
    adjrsquare: 1.0000
          rmse: 2.2400e-007

 C = 90.6425465 +/- 0.0000052
 k = 0.956000078 +/- 0.000000011
Warrior parry surface using 5.4 PTR data

Warrior parry surface using 5.4 PTR data

residuals

##### Parry Fit #####

     General model:
     pfit(x,y) = 3+206/951.158596+(x/951.158596+y)/((x/951.158596+y)/C+k)
     Coefficients (with 95% confidence bounds):
       C =       237.2  (237.2, 237.2)
       k =       0.956  (0.956, 0.956)

pgof = 

           sse: 7.6114e-011
       rsquare: 1.0000
           dfe: 164
    adjrsquare: 1.0000
          rmse: 6.8126e-007

 C = 237.186091 +/- 0.000057
 k = 0.956000014 +/- 0.000000022
Warrior block curve using 5.4 PTR data.  Block only depends on one independent variable (mastery), so it's not a surface.

Warrior block curve using 5.4 PTR data. Block only depends on one independent variable (mastery), so it’s not a surface.

residuals

##### Block Fit #####
Warning: Ignoring extra legend entries. 
> In legend at 294
  In blockFit at 58
  In warrior at 28

pfit = 

     General model:
     pfit(x) = 13+1/(1/C+k/round(128*x)*128)
     Coefficients (with 95% confidence bounds):
       C =       150.4  (150.4, 150.4)
       k =       0.956  (0.956, 0.956)

pgof = 

           sse: 9.6280e-011
       rsquare: 1.0000
           dfe: 164
    adjrsquare: 1.0000
          rmse: 7.6621e-007

 C = 150.37568 +/- 0.00015
 k = 0.955999849 +/- 0.000000067

The block fit was sort of irritating, because I found out during data processing that the game doesn’t re-calculate block immediately. I had some data points where I had exactly the same mastery but different block values. After looking at the timestamps and the stat changes, it was clear that this is just a reporting error on the game’s part. For example, I’d find two time-adjacent data points that had different mastery rating values but identical block chances. The next data point has the same mastery rating value as the previous one, but the block chance had finally updated.

It’s curious because I didn’t see this effect with any of the other stats – dodge and parry always updated immediately.  It may be that block is calculated less frequently, or done server-side, or some other oddity.  I’m not really sure.  I ended up omitting these obviously-errant data points before performing the fit.  They were easy to find, since they were all extremely far off of the curve created by the rest of the points.

So, to summarize for Warriors:

$k = 0.9560000(78) \pm 0.000000011$
$C_d = 90.64254(65) \pm 0.0000052$
$C_p=237.1860(91) \pm 0.000057$
$C_b =150.375(68) \pm 0.00015$

Warriors also get 1% parry from 951.158596 strength and 1% dodge from 10000 agility.

Summary Table For All Classes

Since it might be convenient to have everything in one place, here’s a table listing the different coefficients for each class.  The paladin data is from last year’s post.

Since it’s pretty clear that the $k$ values are nearly exact to three digits, I’m going to make the assumption that they are, as it has no significant effect on the results.

Class $k$ $C_d$ $C_p$ $C_b$
Death Knight $0.956$ $90.6425(74) \pm 0.000010$ $237.186(14) \pm 0.00015$ -
Druid $1.222$ $150.3759(38) \pm 0.000041$ - -
Monk $1.422$ $501.253(48) \pm 0.00032$ $90.642(44) \pm 0.00014$ -
Paladin $0.886$ $66.56744(62) \pm 0.0000060$ $237.1860(40)\pm 0.000055$ $150.3759(469)\pm 0.0000094$
Warrior $0.956$ $90.64254(65) \pm 0.0000052$ $237.1860(91) \pm 0.000057$ $150.375(68) \pm 0.00015$

In this arrangement, it’s easy to see that the plate tanks all share the same parry cap $C_p$.  Death Knights and warriors have the same dodge cap $C_d$ and $k$ value, but paladins differ slightly in both departments.  The block cap $C_b$ is the same for both blocking classes.  Druids and monks both do their own thing, though the monk parry cap is identical to the warrior/DK dodge cap.

Here’s a second table listing the strength-to-parry and dodge-to-agility conversions for each class.  This is sort of obvious, since you get 1% avoidance from 951.158596 of your primary stat, and 1% avoidance from 10000 of your non-primary stat, but I’m including it for completeness.

Class Str->Parry Agi->Dodge
Death Knight 951.158596 10000
Druid 0 951.158596
Monk 10000 951.158596
Paladin 951.158596 10000
Warrior 951.158596 10000
This entry was posted in Tanking, Theck's Pounding Headaches, Theorycrafting and tagged , , , , , , , , , , , , , , . Bookmark the permalink.

10 Responses to Updated Diminishing Returns Coefficients – All Tanks

  1. Jackinthegreen says:

    Have these more accurate numbers been implemented in SimC for all the tanks yet?

  2. Draquoe says:

    Hi Theck,

    First of all I’m a huge fan of your work and thanks for all the things you have done to the tanking community. I’d like to have a few questions, though. I’m a protection warrior, so I will use the warrior numbers.

    Just a side-note that I don’t really agree with the current design of the avoidance stats, as it requires too deep understanding from people to master their characters. I mean, not everyone can have a degree in science :-S

    As far as I understand lot of people actually misunderstand your work and refers to it as an ultimate reason not to go for avoidance stats because of the huge diminishing returns. I personally were sitting on that train, too, but the recent changes (Riposte) made me think about it a bit more. I ended up with a macro to calculate dodge and parry after diminishing returns (I did not find such a macro on the web):

    /run bd,bp,cd,cp,k=5.01,3.22,90.6425,237.1860,0.956 d,p=GetDodgeChance(),GetParryChance() pd,pp=d-bd,p-bp ad,ap=bd+1/(1/cd+k/pd),bp+1/(1/cp+k/pp) DEFAULT_CHAT_FRAME:AddMessage(“\nDodge: “..d..”=>”..ad..”\nParry: “..p..”=>”..ap..”\n”)

    The results for my warrior are:

    Stat before DR after DR
    Dodge: 16.28% 15.44%
    Parry: 34.37% 31.87%

    So the first questions: can this be accurate or am I missing some point?

    If the above calculation is OK then I think dodge and parry are not hit by that hard from diminishing returns as it is stated (without any numbers) on the WoW forums and parry/dodge build can be viable to reduce damage taken. Of course we need to manage the spikes with active mitigation, for example with Shield Barrier instead of Shield Block with the warrior.

    • Theck says:

      I haven’t checked your math (i.e. plugging in numbers), but the process you’re using in the macro looks correct. And the numbers seem in the right ballpark to me – about 10% average reduction at normal avoidance values. Should easily be able to check by seeing if the post-DR values match your character sheet.

      Keep in mind that it’ll get worse as you stack more avoidance. That’s the whole point, in fact – if you add a little more dodge or parry, you’ll only be getting e.g. 70% of what the rating conversion should be thanks to the DR.

      Whether that makes an avoidance build viable for warriors is a different question entirely (and one to which I don’t have an answer). The fact that avoidance gives solid damage reduction doesn’t necessarily make it a great stat. It’s the best damage reduction stat for a paladin, too. But we avoid it because it leaves us open to large damage spikes in ways that haste and mastery don’t.

      In other words, keep in mind that total damage reduction isn’t generally a useful stat for tanks, so optimizing for it usually isn’t a good way to gear.

  3. Pingback: TC101: Experimental Design | Sacred Duty

  4. Booi says:

    Theck,

    You list the base parry as 3%, but my naked warrior has a parry of 2.97% on the character sheet. Is this a bug/rounding issue on their paper doll, or is the base 2.97%?

    • Theck says:

      It sounds like a bug. On my human, the character sheet reads 3.22% and a quick macro gives us even more precision:
      /script print(GetParryChance())
      3.2165780067444

      This is exactly consistent with 3.00% base plus the contribution from base strength (206/951.158596). To within about seven decimal places:

      >> 3.2165780067444-206/951.158596
      ans =

      3.0000000345

      Obviously that will depend somewhat on race, since base strength varies, but it should never be less than 3.00.

      Things will be changing slightly in WoD, in that base strength will no longer grant parry (or more accurately, it still grants it, but the game will subtract off an equal amount automatically), so you should have exactly 3.00 at level 100. There was a bug on beta where it was subtracting the wrong amount, leaving you with 0.25% base parry, but that has supposedly been fixed. (Note that this isn’t speculation, I’ve been told directly the intent is for base parry to be 3.00%).

      It’s working properly on my L90 human warrior:
      http://gyazo.com/42910c5d1243adc02615675670adfc3e
      And for a L100 human warriors:
      http://gyazo.com/0be7c2736581ae2ae692bf36579cd168
      A L100 orc warrior has 3.02%, so it’s not quite working properly for all races:
      http://gyazo.com/f15719d93bd4a6431e51812ee79b6209
      Likewise for dwarves (3.03%):
      http://gyazo.com/31ef981619d30adc4c0df910e4d4c573

  5. Booi says:

    Whether or not it is intended, it is tarting to make sense.

    Humans have no bonus strength (1455)
    Orcs have +3 Strength (1458)
    My gnome has -5 Strength (1450)

    /script print(GetParryChance())
    2.9720702171326

    http://imgur.com/a2DTTYq

    • Booi says:

      Missed the thread trace, but I will note that this is level a level 100 character on beta – 6.01 (18566)

      • Theck says:

        Yeah, I got 2.97% on a L100 gnome test character on beta as well. I think you’re right, and that it’s subtracting the base strength you have before racial base strength bonuses are applied, leading to an over-subtraction for gnomes and an under-subtraction for Orcs, Draenei, Dwarves, etc.

        I posted about it in the Theorycrafting thread for Celestalon to comment on:
        http://us.battle.net/wow/en/forum/topic/13087818929?page=21#420

Leave a Reply