Warrior Block Calculations – Part 2

In the last installment, we calculated expressions for the normalized scale factors $\Delta_i$ that represent the effectiveness of a given stat at reducing damage taken. To finish the job, we need to calculate explicit expressions for the variables $\rho_h$, $\rho_e$, $\rho_s$, $\rho_m$, $\rho_x$, $\rho_d$, and $\rho_p$, which represent how a warrior’s Shield Block cast rate varies with hit, expertise, haste, mastery, crit, dodge, and parry, respectively.

1. Rotation Modeling

The first step in this process is to determine exactly what the warrior rotation looks like. We can make a few assumptions here:

  • The warrior dumps all of their rage into Shield Block
  • We don’t care about DPS, so we’ll use the highest-rage-per-second rotation

The primary source of rage generation is Shield Slam (SS), which generates 10 rage. However, it generates 15 rage if cast during a Sword and Board (SnB) proc. So the rotation will revolve around maximizing SS casts. The most efficient way to do that is with a simple Priority: SS>Revenge>Devastate

In this model, we cast the abilities as soon as they’re available, following the priority order given. If you do that, you can break the rotation down into four possible sub-sequences:

  • 1: SS-Revenge
  • 2: Devastate-SS-Revenge
  • 3: Devastate-Devastate-SS-Revenge
  • 4: SS(SnB)-Devastate-Revenge

This may look funny, but the idea is reminiscent of a Markov chain. Every time we cast Revenge, we get a branch, and #1-4 are the only four possible branches we can enter. For example, we always start with #1. If that Revenge triggers SnB, we always jump to #4 (SS-Rev-SS(SnB)-Dev-Rev), and if it doesn’t we’ll always jump to #3 (SS-Rev-Dev-Dev-SS-Rev). Thus, we can find the steady-state probability of each sequence occurring using the concept of Stochastic (or Markov) matrices. We construct our transition probability matrix P:

In this matrix, each element $P_{ij}$ represents the probability of transitioning from state $i$ to state $j$. To find the steady-state probabilities, we just calculate $P^k$ in the limit as $k \rightarrow \infty$. In fact, we don’t even need to go very high in $k$ – the matrix $P^k$ is identical for $k>2$:

Thus, we have a 24% chance of being in state #2, a 16% chance of being in state #3, and a 60% chance of being in state #4. We can use this information to calculate the generated rage per second. State 2 generates 10 rage in 4.5 seconds, state 3 generates 10 rage in 6 seconds, and state 3 generates 15 rage in 4.5 seconds, giving a net Rage Per Second (RPS) of (10/4.5*0.24 + 10/6*0.16+15/4.5*0.60) = 2.8 rage per second. This is the maximum rage generation rotation for warriors now that Revenge has a 4.5-second cooldown.

There’s an additional complication though – we haven’t accounted for Revenge misses. That reduces the transition probability to state #4 from $0.6$ to $0.6(1-(\mu-h)-(d+p-e))$, and increases the other transition probabilities from $0.4$ to $1-0.6(1-(\mu-h)-(d+p-e))$. Here, $\mu$ is our base chance to miss (7.5% against a boss), $d$ and $p$ are our base chance to be dodged/parried, and $h$ and $e$ are our hit and expertise. Since this term in parentheses (which is our melee success probability) will show up fairly often, let’s define a placeholder for it. While we’re at it, we’ll define one for our spell success probability ($1-(2\mu-h-e)$) as well:

$\Theta = (1-(\mu-h)-(d+p-e))$
$d\Theta = (dh+de)$
$\Theta_s = (1-(2\mu-h-e))$
$d\Theta_s = (dh+de) = d\Theta$

Once we include this, the steady-state probabilities are analytically:

$\Pi_2 = P^k_{i2} = (0.6 \Theta)(1- 0.6 \Theta)$
$\Pi_3 = P^k_{i3} = (1- 0.6 \Theta)^2$
$\Pi_4 = P^k_{i4} = 0.6 \Theta$

and their derivatives are

$d\Pi_2 = 0.6(1-1.2\Theta)d\Theta$
$d\Pi_3 = -1.2(1-0.6\Theta)d\Theta$
$d\Pi_4 = 0.6d\Theta$

We can then represent this rotation by writing down the cast rates for certain abilities.

1.1 Shield Slam cast rates

Starting with the highest priority, Shield Slam:

$R_{\rm SS} = R_{\rm rSS} + R_{\rm SnB}$

We’ve divided this up into rates for “regular” Shield Slams $R_{\rm rSS}$ and Sword and Board Shield Slams $R_{\rm SnB}$. By deconstructing the weighted average we used above, you can show that

$R_{\rm rSS} = \Pi_2/4.5+\Pi_3/6$
$R_{\rm SnB}=\Pi_4/4.5$.

We’ll also want the variation of each of these terms, so let’s calculate them right away:

$dR_{\rm rSS} = d\Pi_2/4.5+d\Pi_3/6 = d\Theta \chi_{\rm rSS}$
$dR_{\rm SnB} = d\Pi_4/4.5 = d\Theta 0.6/4.5 = d\Theta \chi_{\rm SnB}$
$dR_{\rm SS} = dR_{\rm rSS} + dR_{\rm SnB} = d\Theta \chi_{\rm SS}$

with

$\chi_{\rm rSS} = 0.6(1-1.2\Theta)/4.5 -1.2(1-0.6\Theta)/6$
$\chi_{\rm SnB} = 0.6/4.5$
$\chi_{\rm SS} = \chi_{\rm rSS}+\chi_{\rm SnB}$

1.2 Revenge cast rates

We can also quickly figure out Revenge’s cast rate,

$R_{\rm R}=(\Pi_2+\Pi_4)/4.5+\Pi_3/6 = R_{\rm SS}$

using the same technique. Note that we’re assuming here that Revenge is always available, which is a pretty safe assumption if you’re tanking. It turns out we won’t need either of these values, but they’re good to have lying around. The derivatives of $R_{\rm R}$ are identical to that of $R_{\rm SS}$, so

$dR_{\rm R} = d\Theta \chi_{\rm R} = d\Theta \chi_{\rm SS}$.

1.3 Thunder Clap and Battle Shout cast rates

Devastate is a little trickier, because we’ll be replacing some Devastate casts with Battle Shouts and Thunder Claps. So let’s work out those first. Shout is easy – it’s just

$R_{\rm shout} = 1/60$.

Thunder Clap is slightly trickier. Ideally, we would cast it every 30 seconds to keep up the Weakened Blows debuff. However, it’s not automatic. If it misses, we’ll cast it again as soon as it’s available (6 seconds). So the proper way to write it would be:

$R_{\rm TC} = \frac{\Theta_s}{30}+\frac{1-\Theta_s}{6}\large$.

In other words, it’s the weighted average based on hit/miss chances. Note that I’ve assumed it misses as a spell for this rather than as a melee strike. I’m not sure if this is correct, but it’s easy to fix if we find out that assumption is wrong. This simplifies to

$R_{\rm TC} = 1/6 – (2/15)\Theta_s$,

and the derivative is

$dR_{\rm TC} = -\chi_{\rm TC}d\Theta\large$,

with $\chi_{\rm TC}=\frac{2}{15}$.

1.4 Devastate cast rates

Now for Devastate. In the scenarios above, we cast Devastate at a rate of

$R_{\rm D0}=(\Pi_2+\Pi_4)/4.5+2\Pi_3/6$,

with a derivative scaling of

$dR_{\rm D0} = \chi_{\rm D0}d\Theta$,

with

$\chi_{\rm D0} = 0.6(2-1.2\Theta)/4.5 – 1.2(1-0.6\Theta)/3$.

However, we need to subtract off to account for Thunder Clap and Battle Shout:

$R_{\rm D} = R_{\rm D0} – R_{\rm TC} – R_{\rm shout}$

From this we can immediately see that

$dR_{\rm D} = dR_{\rm D0}-dR_{\rm TC} = d\Theta(\chi_{\rm D0}-\chi_{\rm TC})$,

We could substitute in our expressions for $R_{\rm TC}$ and $R_{\rm shout}$, but that doesn’t make the expression too much easier to work with, so we won’t bother. At this point, we have a complete model of the warrior rotation.

If Shield Slam and Battle Shout were a warrior’s only sources of rage, we’d be done here. Rage generation would simply be the rage from Shield Slams plus the rage from Battle Shouts minus the rage used to maintain The Clap. And that would be really simple. But we’re not so lucky, because warriors also generate rage from auto-attacks. And that leads to a number of problems.

First, we need to accurately model melee swings, which means we need to care about parry-hasting. That’s a non-trivial problem, and will be the focus of the second half of this post. The other issue is that Enrage increases rage generation from those auto-attacks during its effect, which means we need an accurate model of Enrage uptime. And to do that, we need to account for all sources of Enrage – critical strikes, critical blocks, and even the interaction of Ultimatum with Glyph of Incite. We’ll deal with the Enrage modeling next time.

2. Parry Hasting

Parry-hasting as a mechanic can be extraordinarily complicated in the general case. I’ve worked on this problem before, and the matlab code has a function that specifically models parry-hasting. If we wanted to treat the problem completely generally, it wouldn’t be possible to come up with a nice analytical formulation. However, we’re going to limit our scope to a single situation – tanking a single raid boss – which makes it possible to analytically represent parry-haste.

The mechanics of parry-haste work like so: When you parry an attack, your swing timer is reduced by 40% of its un-hasted value, unless that would reduce the swing timer to below 20% of that un-hasted value, in which case it reduces the swing timer to 20% exactly. That’s a little clumsy, so let’s consider an example. If I have a 2.00-speed weapon, my swing timer is 2 seconds. If I parry the boss when there’s 1.9 seconds left on my swing timer, it reduces my swing timer by 40% of 2 seconds, which is 0.8 seconds, leaving 1.1 seconds remaining on my swing timer. If I parry when there’s 0.9 seconds left on my swing timer, it can’t reduce my swing timer by the full 40% because that would drop itbelow the 20% threshold (which is 0.4 seconds). So instead, it drops the swing timer to 0.4 seconds exactly, giving me 0.5-seconds of parry-hasting (only 25%, instead of 40%). If I parry an attack when there’s 0.4 seconds or less left on my swing timer, there’s no effect at all.

Thus, the average amount of parry-haste you get from a single parry is 24%. There’s an additional complication, which is something we call “Doubly Degenerate Parry Events” (DDPEs). This is when you parry two attacks in rapid succession, and that ends up causing some attrition in parry (the second parry is less effective, necessarily). However, we’re going to consider a boss with a swing timer between 1.5 and 2.0 seconds, which eliminates the possibility of DDPEs. So we can ignore that problem.

Generally, one would represent parry haste by a set of coupled equations linking the boss attack rate $R_{\rm att}$ to the player auto-attack rate $R_{\rm AA}$. However, since bosses no longer benefit from parry-haste, the equations are considerably simplified, and the coupling is one-way:

$R_{\rm AA} = R_{\rm AA}^{(0)}(1+s)+cR_{\rm att}$

Here, $c$ is the coupling constant that represents the effect of parry-haste. If we ignore DDPEs, we can represent $c$ as:

$c = 0.24*{\rm binopdf}(1,1,P)*({\rm chance~of~1~attack~in~T_{\rm AA}}) \\ + 0.24*[1-{\rm binopdf}(0,2,P)-{\rm binopdf}(2,2,P)]*({\rm chance~of~2~attacks~in~T_{\rm AA}})$

To get some intuition here, ${\rm binopdf(k,N,P)}$ is the binomial probability distribution representing having $k$ successful events out of $N$ trials, with a success chance of $P$. In our case, $P = A_{p0}+A_p$, the chance to parry the incoming attack. Thus, the first term represents the parry-haste we gain if the boss only attacks once during the swing timer and we parry that attack. The second term represents the gain when there are two boss attacks during the swing timer, and the expression in brackets is the probability that we parry exactly one of those attacks (which is 1 minus the probability that we parry neither minus the probability that we parry both).

The text expressions can be converted to analytic expressions if we define

$pho=R_{\rm att}/R_{\rm AA}^{(0)}(1+s)$,

which is the average number of parry-haste opportunities we have in a hasted swing timer. The chance of having one incoming attack is then just $2-pho$, and the chance of having two incoming attacks is $pho-1$. In addition, we can substitute in the exact form of ${\rm binopdf()}$ since our cases are fairly simple. This gives us an expression for $c$ that looks like this:

$c = 0.24 P (2-pho)+0.24 (1-(1-P)^2-P^2) (pho-1) \\ = 0.24 P (pho-2 P pho + 2P)$

and substituting in our expression for $pho$, we finally have:

$c = 0.24 P \left ( \frac{R_{\rm att}}{R_{\rm AA}^{(0)}(1+s)}-\frac{2R_{\rm att}P}{R_{\rm AA}^{(0)}(1+s)}+2P\right )\large$

To give you some idea of how big an effect this is, assume a boss swing timer of 2 seconds, a 2.6-speed weapon, and 10% melee haste. Then $R_{\rm att}=1/2$, $R_{\rm AA}^{(0)}=1/2.6$, $(1+s)=1.1$, and $c=0.0532$. That takes a hasted swing timer of 2.3636 seconds and reduces it to 2.228 seconds, on average, or about 5.74% faster auto-attack speed (i.e. 5.74% haste).

What we’ll need for our derivation, in addition to the expression for $R_{\rm AA}$ and $c$, are their derivatives:

$dR_{\rm AA} = ds R_{\rm AA}^{(0)} + dc R_{\rm att}$

and, saving you some algebra on $dc$:

$dc = -ds (1-P)\frac{0.24*P*R_{\rm att}}{R_{\rm AA}^{(0)}(1+s)^2} \\ + 0.24 (da_p)\Phi_{\rm av} \left [ \frac{R_{\rm att}(1-4P)}{R_{\rm AA}^{(0)}(1+s)}+4P\right ]\large$

If we combine these expressions, and define some abstraction variables, we get

$dR_{\rm AA} = ds\pi_s + da_p\pi_p\large$

where

$\pi_s = R_{\rm AA}^{(0)} – \frac{0.24 P (1-P) R_{\rm att}}{R_{\rm AA}^{(0)}(1+s)^2}\large$
$\pi_p = 0.24 R_{\rm att} \Phi_{\rm av}\left ( \frac{R_{\rm att}(1-4P)}{R_{\rm AA}^{(0)}(1+s)}+4P\right )\large$

Which is what we’ll need to develop our expression for rage generation, which will turn into an equation for the Shield Block cast rate $R_{\rm SB}$.

It’s important to include parry-haste if we want a reasonable expression for $R_{\rm SB}$. Without including parry-hasting, we’d be over-valuing haste by about 10% ($\pi_s \approx 0.3434$, while $R_{\rm AA}^{(0)} \approx 0.3846$) and we wouldn’t have the parry-specific scaling of rage generation that differentiates it from dodge.

In the next post, we’ll tackle the Enrage problem, and tie it together with parry-haste and the warrior rotation developed in this post to complete our expression for rage generation.

This entry was posted in Tanking, Theck's Pounding Headaches, Theorycrafting and tagged , , , , , , , , , , . Bookmark the permalink.

14 Responses to Warrior Block Calculations – Part 2

  1. kalbear says:

    When did they return parry hasting? It’s been out since cata.

  2. Levie says:

    Player parry haste was never removed. They disabled npc parry haste completely in cata, not pc.

  3. Ohgodbees says:

    Wow, I never realized players could be parry hasted. I thought it was just a boss thing. Why is this mechanic still in the game? It seems like the sort of thing that should have been removed long ago.

    • Theck says:

      They turned it off for bosses because it could result in back-to-back melees in less than a second. That’s hard to balance around. It’s not a huge deal if a tank manages to hit a boss twice in rapid succession. There’s nothing inherently wrong with the parry-haste mechanic, it’s just a bit one-sided, which is why we still have it and bosses don’t.

      • Ohgodbees says:

        Not a huge deal, but still an opaque mechanic that you don’t have much control over (other than gearing for parry). I guess I just don’t like legacy mechanics that aren’t obvious at all and can cause strange behaviors in newer systems. :)

  4. Jacob says:

    So much fun. I really enjoyed reading this, with the state machine and the Markov chain! Thanks for the series.

  5. I’m really happy you showing the math for warriors. I only play a protection paladin, but I do care about how other tanks work. More then I care ret or holy paladins.

  6. Coreus says:

    Not to be a stickler or anything, but this type of massive calculation work seems a bit premature to me, considering how radically class mechanics are changing in every Beta patch, not to mention that very little actual balancing of the numbers is likely to be done before the mechanics are anywhere close to final. For example the Revenge ability going from a 9-second CD to a 6-second CD to a 4.5-second CD within only the last month or so.

    • Dan Paladin says:

      I would be willing to bet that the work Theck did for Paladin calculations had a *direct* effect on the recent changes in the Beta. I am assuming Theck is doing these calculations as a favor to his warrior friends in order to see similar changes happen. Plus, I think he kinda enjoys it :D

      • Ohgodbees says:

        I’d imagine it also lays a lot of the groundwork, too. Incorporating changes and recalculating/rerunning everything is a lot easier than building it up from scratch and it can show him (and us!) how those changes had an effect. That plus enjoying it like the Dan said. :P

  7. Pingback: Warrior Block Calculations – Part 3 | Sacred Duty

  8. Pingback: Selective Perfection « Dreadblade

  9. Pingback: L90 Mitigation Stat Weights for Warriors | Sacred Duty

Leave a Reply