5.1 Warrior Simulations – Part 3 – Stat Priorities

In case you missed the previous entries, in part one we detailed the model and analyzed a few basic queues that used either Shield Block or Shield Barrier exclusively.  In part two, we analyzed a number of other queues that tried to combine the two spells.  From that analysis, we narrowed down our choices to three different queues: Shield Block spam (“SB”), Shield Barrier spam (“SBr*”), and a first-come first-serve strategy with a high-rage bleed valve (“F-110″).  For more information on how those queues work, please consult part two of this series.

As the title suggests, in this installment we’re going to take a look at how different stat configurations affect the results of the simulation.  You may recall that I posted some simple TDR stat weights for warriors last September.  I received a lot of feedback on that post, varying from surprise to insistence that those weights must be completely wrong – in fact, as I mentioned in part one, that was part of the impetus for returning to these simulations.  Today we’ll have enough detail to see whether the criticism was warranted.

However, unlike the last round, we have much more sophisticated data and metrics to work with.  In addition to looking at how the stats affect TDR, we can analyze smoothness metrics.  One of the arguments that many people have put forth, myself included, was that hit and expertise were likely to have a very strong effect on damage smoothing much like they do for paladins.  So while they were distant last-place entries for TDR, they may still end up being a very high priority for survivability because they make your intake more predictable.

There’s always the additional argument that hit and expertise are great for DPS, but it’s incredibly difficult to draw a numerical comparison there.  Exactly how much survivability is it worth giving up to boost DPS?  There’s no simple answer.  That’s going to vary based on the needs of your raid team and your level of comfort with your own tanking.  So it’s not something we can analyze with a simulation like this.  However, if the stats give us a significant defensive benefit, stacking them becomes a win/win situation in both departments.

Files:

I’m using two new files in this post, but both are just scripts that call the workhorse function warr_mc.m, which is unchanged from the previous installment.  The scripts are

warr_mc_stats.m – performs the stat analysis for our queues
warr_mc_stats2.m – detailed hit/expertise level analysis

Gear Sets:

First, let’s look at the gear configurations we’ll be using for this simulation.  I’ve chosen to use gear sets that are very similar to the ones I used in the paladin simulations, which approximate an average item level of 496.  The sets each have 11k Strength, 63500 armor, and 17150 rating worth of secondary stats distributed amongst parry, dodge, mastery, hit, and expertise.  This is enough rating to cap hit and expertise and still have 9500 left over for avoidance and mastery.  Just as with the paladin setups, I’ve enforced a minimum of 2000 dodge and parry and 1500 mastery to account for the fact that we rarely get complete control over our stat allocation.  That still leaves 4000 points for us to shift around at our leisure. The stats are summarized on the table below.

|    Set: |  C/Ma |  C/Av | C/Bal | C/Bal-NC | Avoid | Av/Mas | Mas/Av |
|     Str | 11000 | 11000 | 11000 |    11000 | 11000 |  11000 |  11000 |
|   Armor | 63500 | 63500 | 63500 |    63500 | 63500 |  63500 |  63500 |
|   Parry |  2000 |  4000 |  3167 |     3167 |  7325 |   6000 |   4000 |
|   Dodge |  2000 |  4000 |  3167 |     3167 |  7325 |   6000 |   4000 |
| Mastery |  5500 |  1500 |  3166 |     3366 |  1500 |   4150 |   8150 |
|     Hit |  2550 |  2550 |  2550 |     2450 |   500 |    500 |    500 |
|     Exp |  5100 |  5100 |  5100 |     5000 |   500 |    500 |    500 |

We start with four “control” gear sets that prioritize hit and expertise cap before anything else.  Control/mastery (“C/Ma”) prefers to stack mastery with the excess 4000 points, while control/avoidance (“C/Av”) splits that extra rating between dodge and parry.  I also have a control/balance (“C/Bal”) set that tries to keep equal amounts of dodge, parry, and mastery.  And finally, there’s a second version of control/balance (“C/Bal-NC”) that shifts 100 hit and 100 expertise into mastery to see whether being about half a percent below hit and expertise caps has a significant effect on survivability.

At the other extreme, we have the avoidance-based sets.  These drop all but 500 hit and 500 expertise, freeing up additional stat allocation.  Thus, we have 10650 rating to allocate with these sets.  The pure avoidance set (“Avoid”) takes all of that and splits it between dodge and parry.  The avoidance/mastery (“Av/Mas”) set sheds a little of that avoidance to bring mastery up to 4150, while the mastery/avoidance (“Mas/Av”) set shifts the majority of that itemization into mastery, pushing it all the way to 8150.

Metrics:

We’ll use all of the same metrics as before to evaluate these gear sets.  Since I’ve covered these in the last installment, I’ll just quote myself:

S% is our Shield Block uptime in decimal form
mean is our mean damage intake in percentage of maximum DTPS
std is the standard deviation of damage intake for a 5-attack moving average
SBr(k) is the total number of Shield Barrier casts, in thousands
SBr<60(k) is the number of Shield Barrier casts at less than 60 rage, in thousands

RPS is our rage generation rate (i.e. X rage per second)
xsR(k) is the amount of excess rage, in thousands

80% is the percentage of spikes that are above 80% maximum throughput
90% is the percentage of spikes that are above 90% maximum throughput

If you see me use shorthand like “90% events for 4-attack strings,” it means we’re looking at what percentage of all 4-attack strings fell above 90% of maximum throughput – in other words, how many times did we take 4 attacks in a row that summed to 90% of 4 full hits.

Also note that the 90% metric is a subset of the 80% metric.  In other words, the 80% category tells us about all of the events above 80% throughput, which necessarily includes all of the 90% events too.  If we want to know how many events fall between 80% and 90%, we have to subtract the number in the “90%” row from the number in the “80%” row.

Shield Block Queue (SB):

The first of our three queues is the simplest: “spam Shield Block.”  We have a few expectations for how this queue will perform already.  Since it ends up wasting a lot of rage due to the Shield Block charge mechanism, it shouldn’t gain a large benefit from hit or expertise above what’s necessary to maintain Shield Block.  On paper, that’s 6.667 rage per second, but due to discretization and RNG we expect to need an average that’s a little higher than that to improve smoothing.  And Shield Block’s synergy with mastery should make mastery builds stronger than avoidance builds.  Let’s see how many of those expectations show up in the data:

|      Set: |     C/Ma |     C/Av |    C/Bal | C/Bal-NC |    Avoid |   Av/Mas |   Mas/Av |
|        S% |   0.6667 |   0.6667 |   0.6667 |   0.6667 |   0.6637 |   0.6657 |   0.6665 |
|      mean |   0.5841 |   0.5849 |   0.5857 |   0.5837 |   0.5372 |   0.5361 |   0.5350 |
|       std |   0.1340 |   0.1440 |   0.1393 |   0.1394 |   0.1611 |   0.1538 |   0.1431 |
|       RPS |   8.2311 |   7.9791 |   8.0795 |   8.0686 |   6.9497 |   7.1282 |   7.3737 |
|    xsR(k) | 938.5090 | 787.2990 | 847.5390 | 841.0140 | 187.7190 | 282.4960 | 425.3690 |
|    ------ |    --- 2 |   Attack |   Moving |  Average |   ------ |   ------ |   ------ |
|       80% |  22.4295 |  24.0775 |  23.4485 |  23.1582 |  20.2805 |  19.3815 |  17.7728 |
|       90% |   8.1348 |   7.8957 |   7.9970 |   7.9205 |   7.4148 |   7.1505 |   7.0875 |
|    ------ |    --- 3 |   Attack |   Moving |  Average |   ------ |   ------ |   ------ |
|       80% |   8.4790 |   9.7037 |   9.2218 |   9.0358 |   8.0490 |   7.2245 |   5.9550 |
|       90% |   0.0000 |   0.0003 |   0.0000 |   0.0000 |   1.0903 |   0.5763 |   0.1998 |
|    ------ |    --- 4 |   Attack |   Moving |  Average |   ------ |   ------ |   ------ |
|       80% |   6.6083 |   8.9138 |   7.9930 |   7.6997 |   6.9833 |   5.6407 |   3.8593 |
|       90% |   0.0000 |   0.0000 |   0.0000 |   0.0000 |   1.2390 |   0.6270 |   0.2055 |
|    ------ |    --- 5 |   Attack |   Moving |  Average |   ------ |   ------ |   ------ |
|       80% |   4.5538 |   7.2175 |   6.1227 |   5.8265 |   5.4863 |   4.0145 |   2.2655 |
|       90% |   0.0000 |   0.0000 |   0.0000 |   0.0000 |   0.4768 |   0.2352 |   0.0798 |
|    ------ |    --- 6 |   Attack |   Moving |  Average |   ------ |   ------ |   ------ |
|       80% |   0.0000 |   0.0000 |   0.0000 |   0.0000 |   1.1093 |   0.5568 |   0.1750 |
|       90% |   0.0000 |   0.0000 |   0.0000 |   0.0000 |   0.1623 |   0.0907 |   0.0290 |
|    ------ |    --- 7 |   Attack |   Moving |  Average |   ------ |   ------ |   ------ |
|       80% |   0.8303 |   1.4797 |   1.1968 |   1.1203 |   1.6803 |   0.9902 |   0.4093 |
|       90% |   0.0000 |   0.0000 |   0.0000 |   0.0000 |   0.1500 |   0.0823 |   0.0275 |

First, let’s look at the TDR metric (“mean”).  There’s not a lot of variation amongst the different control strategies, at least not enough to draw statistically significant conclusions about mastery and avoidance.  But there’s a very clear drop in damage taken when shifting to the avoidance gear strategies.  Shifting 6650 rating from hit and expertise into dodge and parry reduces damage taken by a little over 8%.  The difference between pure avoidance and avoidance/mastery isn’t that large either, but there seems to be a slight decrease in damage taken as we shift more of that avoidance into mastery.

So this simulation suggests that for TDR mastery is a little ahead of avoidance and both are far ahead of hit and expertise.  In other words:

mastery>avoidance>>hit/expertise.

How does that compare with our results from September?  Well, to refresh your memory…

N=50, tau=10000, stat=1500

|          |  dodge |  parry |    hit |    exp | mastery |
|     mean | 0.8957 | 0.9008 | 0.0556 | 0.0438 |  1.0000 |
|      std | 0.0626 | 0.0675 | 0.0677 | 0.0544 |  0.0580 |
| std_mean | 0.0088 | 0.0095 | 0.0096 | 0.0077 |  0.0082 |

…. we see again here the weakness of hit and expertise, and the dominance of mastery/dodge/parry for TDR

Yup, pretty much exactly the same.  Mastery ahead of dodge and parry, hit and expertise trailing far behind.  So we can feel pretty confident that those results were correct.  And they aren’t hard to rationalize either – the excess hit and expertise isn’t doing much for TDR because the change in Shield Block uptime isn’t very large.  We’re well over the 6.667-rage minimum required for Shield Block maintenance in the Avoidance gear set despite having minute amounts of hit and expertise, so we’re losing less than 0.1% of our uptime. That just doesn’t translate into a significant TDR cost.  We just generate less of the excess rage that we’d be wasting anyway.

What it does cost us is smoothness.  The control strategies do a much better job of eliminating 90% spikes. The avoidance gear sets do well for 2-attack strings, but we start to see lingering 90% spikes for 3+ attacks, and as the number of attacks goes up the pure avoidance set falls behind in 80% spikes as well.  And all of it is due to inconsistent rage generation, leading to periods of extended Shield Block downtime.

Within the different control sets, control/mastery  is clearly ahead of control/avoidance and control/balance.  Apart from 2-attack strings, which we generally disregard anyway, control/mastery consistently provides the lowest spike presence.  Curiously, the “uncapped” control/balance set is an improvement over the regular control/balance set.  This suggests that being exactly at or over cap isn’t as critical for warriors as it is for paladins, who saw a noticeable loss in this same comparison.  We’ll touch on that in more detail very shortly.

It’s worth noting that the mastery/avoidance set performs surprisingly well.  While it doesn’t completely eliminate 90% spikes, it has a significant advantage in overall spike presence.  In many cases, it experiences half as many spikes as the control/mastery set.  In a situation where an 80% spike is enough to kill you, the mastery/avoidance gear set is arguably the best choice, especially for the 4- to 5-attack strings we generally focus on.

You may have noticed that the avoidance gear sets are in the vicinity of 7 rage per second, which is above the theoretical 6.667 Shield Block threshold.  And despite that, we’re still seeing this gapping effect that leads to 90% spikes.  That and our interesting results for the uncapped control/balance set lead us to ask, “Exactly how much rage generation is optimal?”  We need to be a bit more precise than that if we want numbers though.

In particular, what we’re really interested in is how much hit and expertise we really need to maintain Shield Block.  We know that 6.667 is the theoretical limit, but we also know that it isn’t sufficient in practice because rage generation isn’t a nice, smooth, continuous thing.  So let’s try and determine exactly how much hit and expertise it takes to push 90% spikes below an acceptable threshold – let’s say 0.001%.  To do that, we’ll take the control/balance gear set and just hack away rating until we get to zero.  Technically we’d be able to allocate that itemization somewhere else (say, mastery), but for this calculation we’ll pretend that we can’t, and that we’re simply losing itemization.  Maybe it’s being shifted to Stamina, for example.  The reason is that it will give us a better “worst-case” estimate on our hit and expertise needs.  Since the 4-attack moving average seems to have the worst time with 90% spikes in the avoidance gear set, we’ll use that.

If we perform that calculation, it looks something like this:

Spike damage presence vs. combined hit and expertise percentage.  The inset shows an expanded view of the results above 15% combined hit and expertise.

Spike damage presence vs. combined hit and expertise percentage. The inset shows an expanded view of the results above 15% combined hit and expertise.  The dotted line on the inset is 0.001%.

With no hit or expertise, our spike presence (the percentage of events exceeding 90% throughput) is a little over 3.5%.  It drops fairly dramatically with hit and expertise up until about 10% on the x-axis, where it’s starting to slow down in effectiveness.  The surprising part here is just how much hit and expertise it takes to eliminate those spikes.  Even at 15% combined hit and expertise (5% hit, 10% expertise), about 0.03% of all events exceed the 90% spike threshold.  While that’s certainly not a lot of spikes, it’s still well above our self-imposed 0.001% limit.  It isn’t until around 21% combined hit and expertise (7% hit, 14% exp) that we consistently drop below 0.001% spike presence, and it’s only above 22.3% hit and expertise that we finally hit zero.  The behavior in that final section of the x-axis is a little easier to see on this semilog plot, for those that are interested.

So while it’s not critical to be exactly at hit/exp cap, this plot tells us that we start opening ourselves up to 90% spikes if we’re even 1% shy of the cap.  It also suggests that warrior rage generation is “bursty” enough that it pays to be well above the theoretical minimum rage threshold for Shield Block, because a missed Shield Slam at the wrong time is all it takes to create a dangerous spike event.  As such, it’s probably not a bad argument to maintain caps if you’re going with a control strategy.

In summary, this data seems to suggest two viable gearing paths for the “Shield Block spam” finisher queue.  We either stack hit and expertise to cap and then focus heavily on mastery (the standard Hit/Exp > Mastery >> Avoidance control strategy), or we try and push mastery sky-high with a side of avoidance (the Mastery >> Avoidance > Hit/Exp strategy).  Either of those two gives a pretty good result, with one being better at eliminating the high 90% spikes and the other being better at minimizing spikes above 80%.  I also wouldn’t be surprised if a Mastery >> Hit/Exp > Avoidance strategy would perform as well as the mastery/avoidance strategy – the high mastery value seems to be the key component of that queue’s performance.

Shield Barrier Queue (SBr*):

We expect the Shield Barrier queue to tell us a very different story.  Since Shield Barrier isn’t limited by a charge system the way Shield Block is, we should be able to take advantage of rage generation much more effectively.  That should make hit and expertise much more powerful stats than they are for the Shield Block queue.  Mastery will likely suffer a bit given the lack of guaranteed blocks, while avoidance should get stronger because it doesn’t compromise the Shield Barrier absorb mechanic.  Let’s see if the data confirms those predictions:

|      Set: |     C/Ma |     C/Av |    C/Bal | C/Bal-NC |   Avoid |  Av/Mas |  Mas/Av |
|        S% |   0.0000 |   0.0000 |   0.0000 |   0.0000 |  0.0000 |  0.0000 |  0.0000 |
|      mean |   0.4254 |   0.4044 |   0.4137 |   0.4155 |  0.3935 |  0.4087 |  0.4257 |
|       std |   0.2002 |   0.2044 |   0.2030 |   0.2054 |  0.2180 |  0.2164 |  0.2123 |
|    SBr(k) | 100.0000 | 100.0000 | 100.0000 |  99.9620 | 98.1860 | 98.1530 | 98.2380 |
| SBr<60(k) |  66.2540 |  65.9270 |  66.2830 |  66.3450 | 73.8420 | 74.0180 | 73.6990 |
|       RPS |   7.3601 |   7.3745 |   7.3637 |   7.3252 |  6.3873 |  6.3768 |  6.4139 |
|    xsR(k) |   0.0000 |   0.0000 |   0.0000 |   0.0000 |  0.0000 |  0.0000 |  0.0000 |
|    ------ |    --- 2 |   Attack |   Moving |  Average |  ------ |  ------ |  ------ |
|       80% |  17.6300 |  16.7297 |  17.2497 |  17.2058 | 15.4113 | 16.2243 | 16.7793 |
|       90% |   8.9105 |   8.1948 |   8.4980 |   8.5545 |  8.5440 |  9.0595 |  9.5497 |
|    ------ |    --- 3 |   Attack |   Moving |  Average |  ------ |  ------ |  ------ |
|       80% |   5.7390 |   5.3152 |   5.5655 |   5.5515 |  5.0933 |  5.4630 |  5.6943 |
|       90% |   4.1412 |   3.8148 |   3.9960 |   3.9415 |  3.6448 |  3.8937 |  4.1227 |
|    ------ |    --- 4 |   Attack |   Moving |  Average |  ------ |  ------ |  ------ |
|       80% |   2.3103 |   2.1128 |   2.1852 |   2.4530 |  4.0907 |  4.3530 |  4.5382 |
|       90% |   0.0000 |   0.0000 |   0.0000 |   0.0090 |  0.4575 |  0.4857 |  0.4927 |
|    ------ |    --- 5 |   Attack |   Moving |  Average |  ------ |  ------ |  ------ |
|       80% |   2.1305 |   1.8900 |   2.0082 |   2.3093 |  3.3967 |  3.6865 |  3.8115 |
|       90% |   0.0000 |   0.0000 |   0.0000 |   0.0025 |  0.1555 |  0.1677 |  0.1752 |
|    ------ |    --- 6 |   Attack |   Moving |  Average |  ------ |  ------ |  ------ |
|       80% |   1.1298 |   0.9695 |   1.0538 |   1.2115 |  1.7618 |  1.9700 |  2.0035 |
|       90% |   0.0000 |   0.0000 |   0.0000 |   0.0005 |  0.0513 |  0.0598 |  0.0610 |
|    ------ |    --- 7 |   Attack |   Moving |  Average |  ------ |  ------ |  ------ |
|       80% |   0.4732 |   0.3762 |   0.4383 |   0.5012 |  1.1652 |  1.3668 |  1.4605 |
|       90% |   0.0053 |   0.0040 |   0.0032 |   0.0080 |  0.1808 |  0.2100 |  0.2143 |

The TDR stats are a little surprising.  The control strategies certainly compete much better here, but they’re still slightly behind what one accomplishes with the Avoidance gear set.  So hit and expertise have improved considerably, but they still fall behind avoidance in terms of TDR.  Mastery suffers as predicted, with avoidance/mastery and mastery/avoidance falling behind the pure avoidance set.  This disparity is mirrored in the difference between control/mastery and control/avoidance.  In fact, mastery has fallen behind hit and expertise in this data; going from the control/avoidance set to the mastery/avoidance set, which is equivalent to shifting 6650 hit/exp into mastery, gives us a net increase in damage taken.  So our TDR priorities seem to be fairly simple in the Shield Barrier queue: Avoidance > Hit/Expertise > Mastery.

The smoothness metrics are a little different though.  There isn’t a whole lot of difference between the gearing results for 2- and 3-attack strings, though avoidance has a slight edge there as usual.  But as we start looking at longer strings, the control strategies rapidly pull ahead in both 80% and 90% categories.  Control/avoidance performs better than control/mastery, which isn’t too surprising since an avoid extends the life of a Shield Barrier bubble.  But any of the control schemes are a better choice than the avoidance ones for smoothness.  Thus, our smoothness stat priorities would be Hit/Exp >> Avoidance > Mastery.

It’s clear from this that mastery is the odd man out for Shield Barrier spamming.  While it’s not a bad stat, it just doesn’t stand out when you eliminate one of it’s main synergies (Shield Block leading to more critical blocks).  The TDR differences are relatively small compared to the differences we see in the smoothness metrics, so if we want to come up with a general set of stat priorities for this finisher queue I think hit and expertise “win.”  Overall, I’d go with Hit/Exp > Avoidance > Mastery if I were spamming Shield Barrier.

First-come first-serve queue (F-110):

This one’s a little harder to make predictions for.  Since it uses both Shield Barrier and Shield Block, it’s got a weird mix of mechanics.  Shield Block makes mastery strong and weakens avoidance, while Shield Barrier does exactly the opposite.  The only thing that I think I can successfully predict here is that hit and expertise will be strong for smoothness metrics since they seem to always be strong for smoothness. My guess is that they’ll probably fall behind significantly in the TDR department, though, because they’re only a little better for TDR with SBr* and a lot worse for TDR with SB.  Let’s see what the data says:

|      Set: |    C/Ma |    C/Av |   C/Bal | C/Bal-NC |   Avoid |  Av/Mas |  Mas/Av |
|        S% |  0.4255 |  0.4024 |  0.4123 |   0.4126 |  0.2749 |  0.2846 |  0.3067 |
|      mean |  0.4776 |  0.4746 |  0.4763 |   0.4759 |  0.4453 |  0.4534 |  0.4600 |
|       std |  0.1562 |  0.1642 |  0.1619 |   0.1617 |  0.1861 |  0.1835 |  0.1770 |
|    SBr(k) | 57.4520 | 59.7650 | 58.7690 |  58.7180 | 71.0220 | 70.1040 | 68.0820 |
| SBr<60(k) | 55.8980 | 58.8670 | 57.6260 |  57.5240 | 70.8290 | 69.7730 | 67.5520 |
|       RPS |  7.9169 |  7.7466 |  7.8128 |   7.7934 |  6.6260 |  6.6983 |  6.8472 |
|    xsR(k) |  0.0060 |  0.0030 |  0.0150 |   0.0010 |  0.0000 |  0.0010 |  0.0000 |
|    ------ |   --- 2 |  Attack |  Moving |  Average |  ------ |  ------ |  ------ |
|       80% | 14.1575 | 14.5208 | 14.5025 |  14.2623 | 14.5012 | 14.8190 | 14.6805 |
|       90% |  5.2595 |  5.3152 |  5.3080 |   5.3175 |  6.9227 |  7.1638 |  7.1575 |
|    ------ |   --- 3 |  Attack |  Moving |  Average |  ------ |  ------ |  ------ |
|       80% |  5.6348 |  5.8228 |  5.8165 |   5.6595 |  5.2422 |  5.4765 |  5.3887 |
|       90% |  3.3908 |  3.4208 |  3.3955 |   3.3407 |  3.3657 |  3.5343 |  3.5292 |
|    ------ |   --- 4 |  Attack |  Moving |  Average |  ------ |  ------ |  ------ |
|       80% |  1.6260 |  2.0728 |  1.9735 |   2.0240 |  3.7503 |  3.8285 |  3.6620 |
|       90% |  0.0915 |  0.1422 |  0.1265 |   0.1265 |  0.4427 |  0.4622 |  0.4025 |
|    ------ |   --- 5 |  Attack |  Moving |  Average |  ------ |  ------ |  ------ |
|       80% |  1.3987 |  1.8645 |  1.7230 |   1.8560 |  3.1955 |  3.2955 |  3.0950 |
|       90% |  0.0000 |  0.0000 |  0.0000 |   0.0025 |  0.1138 |  0.1293 |  0.1172 |
|    ------ |   --- 6 |  Attack |  Moving |  Average |  ------ |  ------ |  ------ |
|       80% |  0.6168 |  0.8048 |  0.7702 |   0.8377 |  1.5735 |  1.6660 |  1.5755 |
|       90% |  0.0000 |  0.0000 |  0.0000 |   0.0013 |  0.0398 |  0.0473 |  0.0415 |
|    ------ |   --- 7 |  Attack |  Moving |  Average |  ------ |  ------ |  ------ |
|       80% |  0.3443 |  0.4570 |  0.4295 |   0.4820 |  1.1385 |  1.2465 |  1.1983 |
|       90% |  0.0003 |  0.0005 |  0.0017 |   0.0065 |  0.1555 |  0.1620 |  0.1470 |

It looks like I was partly right about the TDR metrics.  Control falls behind avoidance, suggesting that in this mixed queue avoidance is significantly ahead of hit and expertise.  But the disparity is not as great as I expected, either.  I attribute part of that to the sheer efficiency of Shield Barrier – in terms of raw TDR it just eliminates more damage per rage than Shield Block can, and that makes up for a lot of ground.  We see that the mastery/avoidance gear set gives up the bulk of the TDR advantage that the avoidance gear configuration demonstrates, suggesting that mastery is strictly worse than avoidance for TDR.  Mastery/avoidance is still ahead of control/avoidance, though, suggesting that mastery’s still ahead of hit and expertise by a good bit.  So our TDR stat priorities end up being Avoidance > Mastery > Hit/Expertise.

Once again, the smoothness metrics seem to favor the control strategies.  We see a significant reduction in both 80% and 90% spikes for 4+ attacks by shifting from an avoidance-based configuration to a control-based configuration.  I think a lot of this disparity is due to the differences in Shield Block uptime.  The control sets boast over 40% uptime, while the avoidance sets barely manage to maintain 30%.  There’s also a significant disparity in rage generation, with avoidance sets nearly a full 1 rage per second behind the control sets.

There’s also a bit of a chicken-and-egg scenario going on here.  The control sets are generating more rage and thus having to push Shield Block casts back less often, resulting in higher Shield Block uptime.  But that increased Shield Block uptime leads to more critical blocks, which increases rage generation through Enrage.  There’s diminishing returns on that feedback loop, of course, but the interaction is definitely having an effect.

Mastery seems to be a better choice than avoidance in the smoothness category as well.  Control/mastery consistently outperforms control/avoidance by a rather healthy margin.  And the mastery/avoidance set also outperforms the pure avoidance set. though the differences are much smaller.  Again, the lower Shield Block uptime is hurting mastery in the avoidance sets, suggesting that its value is heavily dependent on how often you’re casting Shield Block.  All told, this indicates that the smoothness stat priorities for the F-110 queue should be Hit/Expertise >> Mastery > Avoidance.

It’s interesting that the TDR and smoothness stat priorities differ so completely.  But I think that the TDR variations are so much weaker than the smoothness effects that we can more or less ignore them.  So the overall recommendation for this queue would be Hit/Expertise > Mastery > Avoidance.  Though I think you could make a pretty good argument that hit and expertise  should be “>>” (much greater than) the other two based on the smoothness metrics.

Conclusions:

There are a few obvious trends that stick out when you consider all three data sets.  First, hit and expertise are consistently good smoothing stats.  No matter what queue you happen to be using, hit and expertise tend to do a good job of smoothing out rage generation and subsequently finisher use, giving smoother damage intake profiles.  The SB queue is the only situation where anything else came close in the smoothness department, primarily because of the sheer amount of excess rage being wasted due to the lack of some sort of low-cost rage dump.

On the other hand, hit and expertise were generally poor for TDR.  It was only in the SBr* queue that they managed to crawl out of last place, and only because mastery has no interaction with Shield Barrier.  In the other two cases, they were distant runners-up.

This is pretty similar to how the paladin simulations came out.  Hit and expertise aren’t that great for raw TDR, but dominate the control category.  From a design standpoint, that’s how it ought to be, because it builds a trade-off into the system.  Want smoother damage intake?  Then be prepared to take a little more damage overall.  It ensures that there’s no “king stat” that excels in every category, to the point that you ignore everything else.

It’s worth noting that, just as in part 2, the F-110 queue gives SB a serious run for its money.  Both seem to excel with a control/mastery gearing scheme, though SB seems to perform well with a mastery/avoidance build as well.  But while F-110 does permit more 90% spikes, it maintains lower overall spike presence in control/mastery than SB does in either of the two gear sets.  I think it’s safe to say that F-110 is a legitimate competitor when it comes to finisher queues.

But no matter the queue, it’s clear that for damage smoothing you’ll want to prioritize hit and expertise rather highly.  For any queue that includes Shield Block, it seems that  Hit/Exp >  Mastery > Avoidance will be your go-to gearing priority.  If you’re ignoring Shield Block entirely, then mastery drops to last place for smoothing.

Posted in Tanking, Theck's Pounding Headaches, Theorycrafting | Tagged , , , , , , , , , , , , , , , , | 16 Comments

5.1 Warrior Simulations – Part 2 – Rotations

Last time, we went over the model we’ll be using to evaluate different rotations and looked at some basic queues.  We decided that we’d use the SB and SBr* queues (“Spam Shield Block” and “Spam Shield Barrier,” more or less) as our gold standard for comparison.  Hopefully, some of the more sophisticated queues that utilize both Shield Barrier and Shield Block will improve over these basic queues in one way or another.

Before we start, I want to mention that I’ve made slight modifications to the files since the last post.  The only difference is that I’ve greatly expanded the versatility of the finisher code – rather than hard-coding each finisher priority, I now use regular expressions to construct them dynamically.  So if you’re fooling with the code, you may want to grab revision 550 (warr_mc.m, warr_mc_finishers.m).

Just to reiterate the meaning of the statistics that you’ll be seeing in the tables below:

S% is our Shield Block uptime in decimal form (ex: 0.6667=66.67%)
mean is our mean damage intake in percentage of maximum DTPS.
std is the standard deviation of damage intake for a 5-attack moving average
SBr(k) is the total number of Shield Barrier casts, in thousandsSBr<60(k) is the number of Shield Barrier casts at less than 60 rage, in thousands
RPS is our rage generation rate (i.e. X rage per second)
xsR(k) is the amount of excess rage, in thousands

Note that all of these are for 10,000 minutes of combat, which is why we’re counting in thousands for many of these metrics.  In addition, we have two spike damage metrics:

80% is the percentage of spikes that are above 80% maximum throughput
90% is the percentage of spikes that are above 90% maximum throughput

I’ve calculated both spike metrics for strings of 2 attacks in a row to 7 attacks in a row and everything in-between.  If you see me use shorthand like “90% events for 4-attack strings,” it means we’re looking at what percentage of all 4-attack strings fell above 90% of maximum throughput – in other words, how many times did we take 4 attacks in a row that summed to 90% of 4 full hits.

Also note that the 90% metric is a subset of the 80% metric.  In other words, the 80% category tells us about all of the events above 80% throughput, which necessarily includes all of the 90% events too.  If we want to know how many events fall between 80% and 90%, we have to subtract the number in the “90%” row from the number in the “80%” row.  In other words, if we have a queue that gives us the following data:

80%: 5.0
90%: 2.5

It means that 5% of all events exceeded 80% throughput, 2.5% of all events exceeded 90% throughput, and therefore 5.0-2.5=2.5% of all events were between 80% and 90%.

So, with all of that said, let’s start looking at queues.

Bleed Queues

The “bleed” category of queues was inspired by my earliest attempt at combining Shield Block and Shield Barrier. The idea was to simply use Shield Barrier as a “bleed valve” for excess rage beyond what was necessary to maintain Shield Block. Subsequently, the logic for these queues is pretty simple:

  • B-100 tries to cast Shield Block on cooldown, and will cast Shield Barrier any time rage exceeds 100 (after trying to cast Shield Block first, obviously)
  • B-105 through B-120 are identical except for having a higher rage-bleed threshold.

Let’s see what adding a bleed valve to Shield Block accomplishes:

|      Set: |       SB |     SBr* |   B-100 |   B-105 |   B-110 |   B-115 |    B-120 |
|        S% |   0.6667 |   0.0000 |  0.6667 |  0.6667 |  0.6667 |  0.6667 |   0.6667 |
|      mean |   0.5852 |   0.4144 |  0.5152 |  0.5139 |  0.5144 |  0.5202 |   0.5276 |
|       std |   0.1394 |   0.2029 |  0.1909 |  0.1924 |  0.1932 |  0.1941 |   0.1929 |
|    SBr(k) |   0.0000 | 100.0000 | 14.4770 | 14.4240 | 14.0260 | 12.9640 |  11.4290 |
| SBr<60(k) |   0.0000 |  66.0780 |  0.0000 |  0.0000 |  0.0000 |  0.0000 |   0.0000 |
|       RPS |   8.1018 |   7.3681 |  8.1171 |  8.1267 |  8.1314 |  8.1233 |   8.1168 |
|    xsR(k) | 860.9650 |   0.0000 |  1.5100 | 10.4890 | 37.2100 | 96.0460 | 184.1910 |
|    ------ |    --- 2 |   Attack |  Moving | Average |  ------ |  ------ |   ------ |
|       80% |  23.3400 |  17.1937 | 18.3660 | 18.5260 | 18.8710 | 19.7318 |  20.5240 |
|       90% |   8.0145 |   8.4785 |  6.2952 |  6.1865 |  6.2670 |  6.6265 |   7.0230 |
|    ------ |    --- 3 |   Attack |  Moving | Average |  ------ |  ------ |   ------ |
|       80% |   9.1480 |   5.5260 |  7.1965 |  7.1465 |  7.2642 |  7.7650 |   8.2138 |
|       90% |   0.0003 |   3.9580 |  0.4938 |  0.2680 |  0.1538 |  0.1130 |   0.0800 |
|    ------ |    --- 4 |   Attack |  Moving | Average |  ------ |  ------ |   ------ |
|       80% |   7.8452 |   2.1927 |  6.3350 |  6.2198 |  6.2600 |  6.6950 |   6.9975 |
|       90% |   0.0005 |   0.0000 |  0.6302 |  0.3563 |  0.2053 |  0.1538 |   0.1080 |
|    ------ |    --- 5 |   Attack |  Moving | Average |  ------ |  ------ |   ------ |
|       80% |   5.9655 |   1.9955 |  4.9975 |  4.8215 |  4.7722 |  5.1018 |   5.2975 |
|       90% |   0.0000 |   0.0000 |  0.1505 |  0.0703 |  0.0460 |  0.0350 |   0.0313 |
|    ------ |    --- 6 |   Attack |  Moving | Average |  ------ |  ------ |   ------ |
|       80% |   0.0005 |   1.0360 |  0.5940 |  0.3290 |  0.1935 |  0.1495 |   0.0950 |
|       90% |   0.0000 |   0.0000 |  0.0010 |  0.0005 |  0.0000 |  0.0030 |   0.0047 |
|    ------ |    --- 7 |   Attack |  Moving | Average |  ------ |  ------ |   ------ |
|       80% |   1.1823 |   0.4202 |  1.2530 |  1.0570 |  0.9883 |  1.0565 |   1.0500 |
|       90% |   0.0000 |   0.0030 |  0.0010 |  0.0008 |  0.0000 |  0.0017 |   0.0030 |

The bleed queues eliminate a lot of the excess rage that SB can’t do anything with, and obviously give lower mean damage intake (around 12% or so for B-100 and B-105). They all maintain maximum Shield Block uptime, however, and subsequently don’t have a large effect on rage generation. And of course, all of the Shield Barrier casts are at 60 rage, as expected. As the bleed valve threshold increases, it becomes less effective at both mitigating damage and using up excess rage. But in any event, they’re all definitely an improvement over SB in TDR and rage utilization.

However, the real problem with these queues is in the spike damage category. They perform slightly better for 2-attack strings, but they’re worse at strings of 3 attacks or more. We’ve reduced the number of spikes that exceed 80% spikes compared to SB, but the majority of those spikes are more deadly 90% spikes (~4% out of 5.5%). At the 5-attack level or higher it’s not a huge problem, but 0.2% of the time is still about twice in 2 hours of boss attempts (probably reasonable estimate of time spent on-boss for a 4-hour raid night where you’re solely working on a progression kill).  And it doesn’t get any better for longer queues – they’re strictly worse for 6-attack strings, and not significantly different from SB for 7-attack strings.

The sweet spot for the bleed valve seems to be around 110 rage – you get the largest reduction in 80% spikes across all string lengths and aren’t giving up quite as much in the 90% department as you would at lower rage settings.  Higher rage setting seem to be a little stronger for long 90% spikes, but permit more spikes overall.

But how could spending otherwise-wasted rage on Shield Barrier possibly make you less survivable? The answer is surprisingly straightforward: spending rage on Shield Barrier ends up pushing back Shield Block casts and subsequently creating gaps in your Shield Block coverage that exceed 3 seconds. If rage generation was higher, this problem wouldn’t manifest itself. However, maximum rage generation tops out at around 8.12 RPS, and 6.67 of that is necessary to maintain Shield Block. That only leaves about 1.5 RPS for Shield Barrier casts.

One might naively assume that we could spend that excess rage without affecting Shield Block uptime if we were careful, meaning we only tried to cast a Shield Barrier every 40 seconds on average. It turns out that’s not the case. Consider what happens if we cast a generator and reach exactly 120 rage, triggering our bleed valve. We drop 60 rage on a Shield Barrier, dropping us to 60 rage. We then cast a Shield Block that drops us to zero. In theory, it should only take us about 60/8.12=7.4 seconds to generate the next 60 rage for Shield Block, which should be fast enough.

But we don’t get rage in a steady stream, it comes in discrete chunks at variable intervals due to Sword and Board and Revenge procs. So while that might work out some of the time, some of the time we’ll get an unlucky streak and get only 40 rage from Shield Slams and about 2 rage from Defensive Stance. And when that happens, the next Shield Block is delayed slightly. Thanks to the charge mechanism, we’re still able to maintain maximum Shield Block uptime in these situations, but what it does is create cases where we have almost 12 seconds of continuous Shield Block uptime followed by a 5-6 second gap. And that 5-6 second gap is deadly, because we leave ourselves open to larger spikes.

Another issue with these bleed queues is that they tend to cast Shield Barrier when we need it least. We’re unlikely to get to 100+ rage shortly after dumping 60 into a Shield Block, so that means we’re generally casting Shield Barrier after we’ve had some time to pool rage, which means we cast it right before we cast Shield Block. We’re doubling up our protection, which isn’t a good smoothing strategy. It would make a lot more sense if we could try to prioritize Shield Barrier casts in such a way as to slip them in when Shield Block isn’t active – i.e. to weave them in-between Shield Block buffs. This leads to a new set of strategies, which we’ll call “weave” queues.

Weave Queues

The goal of a “weave” queue is to come up with conditionals that produce a Shield Barrier cast in the gaps in our Shield Block coverage.  Ideally, we want to try and cast a low-rage Shield Barrier when Shield Block falls off to tide us over until the next Shield Block.  Doing so is a little trickier than it sounds.  If we use a simple queue like “Cast Shield Block if rage>60, else cast Shield Barrier if rage>20,” we’ll end up spamming Shield Barrier most of the time rather than successfully weaving the two.  We also know that if we cast a 60-rage Shield Barrier right before a Shield Block charge becomes available, we’ll end up pushing Shield Block back further, which is likely to be counter-productive.

To avoid the “spam Shield Barrier” problem, we want a conditional that prevents us from casting Shield Barrier if a Shield Block charge is available.  Strengthening that condition a little bit allows us to bypass the second problem.  We introduce the idea of a “lockout” period during which we’re not allowed to cast Shield Barrier.  The lockout period is keyed to the availability of Shield Block charges: basically, a lockout period of X seconds means that we can’t cast Shield Barrier if a Shield Block charge will become available in the next X seconds.  That’s simple enough, and gives us a knob we can turn to see exactly how long the ideal lockout period should be.

Remember that the goal was to weave these in-between Shield Block casts.  With just the conditionals above, we could run into situations where we gain a bunch of rage quickly, cast Shield Block, and then cast Shield Barrier with the extra rage during Shield Block’s duration.  Since we don’t want to do that, we’ll add another lockout condition: we aren’t allowed to cast Shield Barrier if the Shield Block buff is active.  That should successfully limit us to truly “weaving” our Shield Barrier casts instead of stacking them with Shield Block.  Finally, we’ll also add a lockout condition for Shield Barrier on itself, so we don’t overwrite the buff.  Since our Barrier casts will be confined to 3-second periods of Shield Block downtime, buff overwriting is just going to waste rage.

Thus, here’s the short form of the conditionals for the “weave” strategies:

  • WX tries to cast Shield Block on cooldown, and will cast Shield Barrier if
      • Rage is >= 20
      • A Shield Block charge will not be available in the next X seconds
      • Shield Block’s defensive buff is not active
      • Shield Barrier’s defensive buff is not active

And we’ll let X take on values of 4, 3, 2, and 1.  A value of 0 would be almost like removing the lockout entirely (but not exactly – more on that in a later section), which we’re pretty sure we don’t want to do.  1 is almost as bad, in that it’s less than a full GCD, but we’ll give it a whirl anyway.  Increasing the lockout further is simply playing more conservatively, in an attempt to minimize Shield Block pushback.  Now that we have the logic figured out, let’s see how these queues pan out:

|      Set: |       SB |     SBr* |       W4 |      W3 |      W2 |      W1 |
|        S% |   0.6667 |   0.0000 |   0.6667 |  0.6665 |  0.6664 |  0.6659 |
|      mean |   0.5855 |   0.4159 |   0.5853 |  0.5154 |  0.5150 |  0.5143 |
|       std |   0.1387 |   0.2025 |   0.1389 |  0.1756 |  0.1758 |  0.1761 |
|    SBr(k) |   0.0000 | 100.0000 |   0.0000 | 17.1190 | 17.4090 | 18.4490 |
| SBr<60(k) |   0.0000 |  66.1670 |   0.0000 |  6.9420 |  7.6780 |  9.9900 |
|       RPS |   8.1070 |   7.3617 |   8.1074 |  8.1144 |  8.1128 |  8.1145 |
|    xsR(k) | 864.0440 |   0.0000 | 864.2560 |  0.1640 |  0.1100 |  0.0470 |
|    ------ |    --- 2 |   Attack |   Moving | Average |  ------ |  ------ |
|       80% |  23.2888 |  17.2935 |  23.2272 | 15.7037 | 15.5595 | 15.1150 |
|       90% |   8.0242 |   8.5203 |   8.0382 |  6.3570 |  6.5395 |  6.9605 |
|    ------ |    --- 3 |   Attack |   Moving | Average |  ------ |  ------ |
|       80% |   9.1170 |   5.6035 |   9.0838 |  6.9930 |  7.1907 |  7.7350 |
|       90% |   0.0000 |   3.9815 |   0.0000 |  2.9437 |  3.2748 |  3.6463 |
|    ------ |    --- 4 |   Attack |   Moving | Average |  ------ |  ------ |
|       80% |   7.7910 |   2.1948 |   7.7340 |  6.2015 |  6.3585 |  6.7892 |
|       90% |   0.0000 |   0.0000 |   0.0000 |  2.7633 |  3.0295 |  3.3723 |
|    ------ |    --- 5 |   Attack |   Moving | Average |  ------ |  ------ |
|       80% |   5.8880 |   2.0383 |   5.8137 |  5.5548 |  5.7040 |  6.0615 |
|       90% |   0.0000 |   0.0000 |   0.0000 |  0.8783 |  1.0170 |  1.2260 |
|    ------ |    --- 6 |   Attack |   Moving | Average |  ------ |  ------ |
|       80% |   0.0000 |   1.0653 |   0.0000 |  2.3687 |  2.5800 |  2.9080 |
|       90% |   0.0000 |   0.0000 |   0.0000 |  0.2658 |  0.3277 |  0.4365 |
|    ------ |    --- 7 |   Attack |   Moving | Average |  ------ |  ------ |
|       80% |   1.1480 |   0.4245 |   1.1415 |  2.0782 |  2.2130 |  2.5255 |
|       90% |   0.0000 |   0.0028 |   0.0000 |  0.1373 |  0.1635 |  0.2280 |

The first thing to notice is that W4 doesn’t end up casting Shield Barrier at all.  I was puzzled by this at first, but after a little bit of debugging it made sense.  It’s the Shield Block lockout conditional at work.  You will never have more than 3 seconds remaining on a Shield Block charge when Shield Block’s buff isn’t active, because by the time the buff falls off the first charge has had at least 6 seconds to recharge.  So a 4-second lockout essentially nullifies the weaving entirely, turning this into a duplicate of the “SB” queue.

Unfortunately, the other weave queues are disappointing for completely different reasons.  W3 is a flat-out gain for strings of two attacks, but fails to be attractive as soon as you consider a third attack.  You shave another 2% off of the number of 80% attacks, but in doing so shifts 3% of them into the even more dangerous 90% category.  And things don’t get better as you look at longer strings, as W3 rapidly falls behind SB in both 80% and 90% spike categories.  The only advantage is a significant (~12%) drop in overall damage intake thanks to Shield Barrier’s numerical advantage over Shield Block in TDR.

And the situation isn’t helped by reducing the lockout – that just makes the pushback effect worse.  We actually start seeing a slight (~0.1%) drop in Shield Block uptime due to the pushback, and no spike mitigation improvement over the W3 queue in any category.  These queues do show better rage utilization (less wasted rage), and slightly improved TDR (though only barely), but wasting less rage isn’t all that attractive if it’s going to get you killed more often either.  Though not shown in the table, I also simmed out W3.5 and W2.5; W3.5 is identical to W4, and W2.5 falls solidly in-between W3 and W2 with no further advantage.

Almost unbelievably, the weaving strategy makes you less survivable than spamming Shield Block and ignoring Shield Barrier does!

The problem again comes down to rage generation.  We simply don’t generate rage fast enough to satisfy the conditionals we’re shackled with without causing Shield Block pushback.  It takes an average of about 7.4 seconds to generate enough rage to cast Shield Block.  Since we’re really gaining rage in discrete chunks, sometimes it’s 5-6 seconds, and sometimes it’s 8-9 seconds or longer, but it’s rarely much less than 5 seconds.  Even back-to-back Sword and Board procs plus Berserker Rage only gives us 60 rage in 3 seconds (SS-Dev-SS, ignoring the trailing GCD), and that’s not a frequent occurrence.

When we use Shield Barrier and drop below 20 rage, we only have at most 3 seconds in which to generate the extra 40-60 rage we need before the next Shield Block charge becomes available.  And we’re just not generating rage fast enough (or consistently enough) to pull that off reliably.  We’d need to be generating 14-20 RPS to be able to successfully weave a Shield Barrier in without a significant risk of Shield Block pushback, and that’s just not possible.

Remember, we’re hit- and expertise-capped in this set.  We’re hitting the “rage soft cap,” so to speak, by capping our most effective rage gain stats.  While we have a good chunk of mastery and avoidance, the rage gain through those mechanics is weak by comparison.  We’re in an almost ideal gear set for rage generation, and it’s still not enough.  And shifting that itemization from avoidance into mastery (or vice versa) isn’t going to be enough of a change to nearly double our rage generation.

There’s little doubt that the weaving strategy is just not as good as we all thought it would be.  You can include me in that group too – in previous comments here and on other forums, I too suggested that this strategy would probably give smoother damage profiles.  But it just goes to show you that you can’t always trust your intuition.  We all made the same flawed assumption – that rage overhead at hit and expertise caps would be high enough to support seamless weaving.  And that assumption turned out to be flat-out wrong.

Just for curiosity’s sake, I cranked up the rage generation of Defensive Stance from 1 rage every 3 seconds (0.333 RPS) to 9 rage every 3 seconds (3 RPS).  Doing so pushes us up to about 10.76 RPS total, and has a drastic effect on the results.  W4 doesn’t change, but W3 suddenly becomes amazing.  33% less damage taken than SB and about 10x better at eliminating 80% spikes across the board.  For example, the 5-attack moving average data drops to 0.4068% in the 80% category and 0.0028% in the 90% category.  If we could maintain that level of rage generation, the weave strategy would be hands-down better for survivability.

So we can perhaps be forgiven for our errant assumption – the weave strategy is great in concept, it’s just stifled by (and very sensitive to) lack of rage generation.  The weave strategy is a leashed dog chasing a squirrel in the backyard, only to find that the leash leaves him one yard short of his quarry.  But one yard may as well be a mile as far as the dog’s concerned, and another 3 rage per second may as well be a million for us, because we’re both at the end of our leashes.

This exercise wasn’t completely fruitless though.  One thing we have discovered is that the W3 queue is a little better than the SBr* queue for 2-attack strings.  This might be relevant in and of itself if we run into a boss that hits for nearly half our health in a single attack.  You wouldn’t survive long against such a boss without cooldowns, but that knowledge might be useful if we run into a boss with mechanics that require you never take two attacks in a row without some sort of mitigation.

In addition, we know that we’re not far from the rage levels that would support a weaving strategy.  It’s not uncommon to get raid buffs that significantly improve resource generation, and while protection warriors no longer have any resource scaling with haste, one would hope that the developers account for this (see, for example old Essence of the Red vs. new Essence of the Red).  So in a fight like Sinestra, we might shift to a weave strategy.

Weave-Bleed Queues

After the “meh” performance of bleed queues and the outright lack of success with weave queues, I wouldn’t blame you for asking why I’d expect a combination weave-bleed queue to fare any better.  In fact, I wouldn’t, but it turns out that I actually ran these weave-bleed simulations first, and only afterwards tried the “pure” weave queues.  It wasn’t until I saw the results of these simulations that I thought to separate out the weave.  But since I’ve already coded the queues and generated the output, we may as well take a look at what happens.  The logic is pretty straightforward:

  • WX-Y will try and cast Shield Block on cooldown, and will try and cast Shield Barrier if
    • either
      • Rage is >= 20
      • A Shield Block charge will not be available in the next X seconds
      • Shield Block’s defensive buff is not active
      • Shield Barrier’s defensive buff is not active
    • or
      • Rage is >= Y

It’s just what you would expect to see for a WX queue with a Y bleed valve added.  Let’s see what happens:

|      Set: |       SB |     SBr* |  W3-105 |  W3-110 |  W3-115 |  W3-120 |
|        S% |   0.6667 |   0.0000 |  0.6665 |  0.6665 |  0.6665 |  0.6665 |
|      mean |   0.5854 |   0.4174 |  0.5153 |  0.5157 |  0.5154 |  0.5145 |
|       std |   0.1390 |   0.2021 |  0.1761 |  0.1755 |  0.1759 |  0.1759 |
|    SBr(k) |   0.0000 | 100.0000 | 17.0950 | 17.1350 | 17.1360 | 17.1490 |
| SBr<60(k) |   0.0000 |  66.4910 |  6.9520 |  7.0110 |  7.0490 |  6.9750 |
|       RPS |   8.1052 |   7.3499 |  8.1123 |  8.1146 |  8.1118 |  8.1164 |
|    xsR(k) | 862.9810 |   0.0000 |  0.0420 |  0.0970 |  0.1300 |  0.2870 |
|    ------ |    --- 2 |   Attack |  Moving | Average |  ------ |  ------ |
|       80% |  23.2643 |  17.4233 | 15.7930 | 15.7805 | 15.7305 | 15.6757 |
|       90% |   8.0210 |   8.5962 |  6.3663 |  6.3312 |  6.3775 |  6.2878 |
|    ------ |    --- 3 |   Attack |  Moving | Average |  ------ |  ------ |
|       80% |   9.0898 |   5.6418 |  7.0233 |  6.9907 |  7.0135 |  6.9320 |
|       90% |   0.0000 |   4.0285 |  2.8112 |  2.7873 |  2.9040 |  2.8022 |
|    ------ |    --- 4 |   Attack |  Moving | Average |  ------ |  ------ |
|       80% |   7.7640 |   2.2183 |  6.1898 |  6.1692 |  6.2270 |  6.1375 |
|       90% |   0.0000 |   0.0000 |  2.6545 |  2.6183 |  2.7140 |  2.6425 |
|    ------ |    --- 5 |   Attack |  Moving | Average |  ------ |  ------ |
|       80% |   5.9170 |   2.0448 |  5.5000 |  5.4852 |  5.5430 |  5.4417 |
|       90% |   0.0000 |   0.0000 |  0.8215 |  0.7983 |  0.8648 |  0.8220 |
|    ------ |    --- 6 |   Attack |  Moving | Average |  ------ |  ------ |
|       80% |   0.0000 |   1.0720 |  2.2700 |  2.2455 |  2.3280 |  2.2725 |
|       90% |   0.0000 |   0.0000 |  0.2238 |  0.2210 |  0.2440 |  0.2315 |
|    ------ |    --- 7 |   Attack |  Moving | Average |  ------ |  ------ |
|       80% |   1.1575 |   0.4313 |  1.9890 |  1.9552 |  2.0055 |  1.9895 |
|       90% |   0.0000 |   0.0040 |  0.1087 |  0.1050 |  0.1208 |  0.1093 |

If you’re wondering where to look in the table to find the interesting part… well, there isn’t one.  They all perform almost identically to W3, suggesting that the bleed valve doesn’t do very much.  That does tell us that the “pure” weave queues rarely build up enough rage to need a bleed valve though.  It happens so rarely, in fact, that we barely even get a single 60-rage Barrier worth of excess rage savings.  That also means there’s no point in simming W2-Y queues, as they’ll just perform like the W2 queue did.

These queues are very sensitive to the lockout.  We’re only getting weaving at all because W3′s lockout is exactly the duration of Shield Barrier’s downtime window.  If you set the lockout to anything higher than 3 (i.e. W3.1-110), all weaving stops and the bleed valve becomes the only avenue for Shield Barrier casts.  And in that case, the results look almost identical to the associated “pure” bleed queues.

Basically, depending on where you set the lock and bleed thresholds X and Y, the WX-Y queues collapse into either a weave or a bleed, but never seem to engage both.  There’s not much more to be said about these queues.  There’s no obvious advantage to any of these over the simple bleed or weave queues, so there doesn’t seem to be any point in using them.

FCFS Queues

Finally, I want to fool around with something I call “first come, first serve” or “FCFS” queues.  The idea behind these queues is that maybe it doesn’t matter if we push back Shield Block as long as we have something active.  As long as we’re throwing something defensive up at a regular interval, we might be able to get a damage smoothing benefit out of it.

How do these queues differ from the Weave-Bleed queues?  Primarily, it’s  that we’re constraining both Shield Block and Shield Barrier rather than just Barrier.  All of the earlier queues were still focused on trying to minimize the disruption of Shield Block uptime.  With these queues we’re going to give them more equal footing.

The basic logic is this:

  • F-Y will attempt to cast
    • Shield Block if
      • Shield Block’s defensive buff is not active
      • Shield Barrier’s defensive buff is not active
    • Shield Barrier if
      • either
        • Shield Block’s defensive buff is not active
        • Shield Barrier’s defensive buff is not active
        • Rage is >= 20
      • or
        • Rage >= Y

As you can see, this is similar to the weave strategy, but with the additional constraint on Shield Block.  It still favors Shield Block, of course, but it’s a little more equitable than the weave strategies.  I haven’t included a lockout here, even though the code will technically accept “FX-Y” queues and handle them appropriately.  But I haven’t included them because after trying a few of those queues, they turned out no different than the Weave-Bleed queues.  Even a lockout of 0 seconds will force you into Shield Barrier casts once the charge is available.  It’s only when you remove the lockout completely that you start to see different behavior, because now we may end up casting a 40-rage Shield Barrier even though a Shield Block charge is available.

Of  course, the fear is that with no lockout, we’ll just degenerate into a SBr* and spam Shield Barrier all day.  Let’s see if that’s really what happens:

|      Set: |       SB |     SBr* |   F-110 |   F-115 |   F-120 |
|        S% |   0.6667 |   0.0000 |  0.4219 |  0.4122 |  0.4146 |
|      mean |   0.5857 |   0.4159 |  0.4786 |  0.4774 |  0.4764 |
|       std |   0.1388 |   0.2027 |  0.1601 |  0.1606 |  0.1605 |
|    SBr(k) |   0.0000 | 100.0000 | 57.8110 | 58.7820 | 58.5360 |
| SBr<60(k) |   0.0000 |  66.2570 | 56.5630 | 57.6290 | 57.3190 |
|       RPS |   8.1061 |   7.3562 |  7.8358 |  7.8148 |  7.8297 |
|    xsR(k) | 863.4910 |   0.0000 |  0.0000 |  0.0250 |  0.0350 |
|    ------ |    --- 2 |   Attack |  Moving | Average |  ------ |
|       80% |  23.2543 |  17.2838 | 14.2528 | 14.5067 | 14.4210 |
|       90% |   7.9967 |   8.5430 |  5.3230 |  5.3033 |  5.2850 |
|    ------ |    --- 3 |   Attack |  Moving | Average |  ------ |
|       80% |   9.1100 |   5.5718 |  5.7012 |  5.7890 |  5.7838 |
|       90% |   0.0000 |   3.9517 |  3.3825 |  3.3708 |  3.3872 |
|    ------ |    --- 4 |   Attack |  Moving | Average |  ------ |
|       80% |   7.7692 |   2.1925 |  2.0100 |  1.9283 |  1.8865 |
|       90% |   0.0000 |   0.0000 |  0.1363 |  0.1295 |  0.1123 |
|    ------ |    --- 5 |   Attack |  Moving | Average |  ------ |
|       80% |   5.8825 |   2.0310 |  1.8770 |  1.6962 |  1.6265 |
|       90% |   0.0000 |   0.0000 |  0.0000 |  0.0000 |  0.0000 |
|    ------ |    --- 6 |   Attack |  Moving | Average |  ------ |
|       80% |   0.0000 |   1.0682 |  0.8375 |  0.7502 |  0.7150 |
|       90% |   0.0000 |   0.0000 |  0.0000 |  0.0000 |  0.0000 |
|    ------ |    --- 7 |   Attack |  Moving | Average |  ------ |
|       80% |   1.1593 |   0.4270 |  0.4678 |  0.4182 |  0.3960 |
|       90% |   0.0000 |   0.0013 |  0.0010 |  0.0008 |  0.0017 |

I’ve only shown three bleed settings here, but that’s enough to see that the bleed valve doesn’t have a strong effect on this queue.  It’s certainly being invoked in F-110, because I checked for that in the debugging, but it only triggers a handful of times (literally) in the entire 10,000 minute run.  And the bleed valve didn’t get invoked at all at the 115 or 120 bleed levels.  When I dropped the bleed value to 100, it performed a little worse than F-110, probably due to a few extra early bleed triggers.  In any event, it seems the bleed setting is mostly irrelevant to the behavior here.  The behavior is dominated by the NOR() we’re performing on the Shield Block and Shield Barrier buffs.

It’s also clear that we haven’t devolved into a Shield Barrier spam routine, because we have a fairly significant amount of Shield Block uptime.  While we’re nowhere near the cap, 41% is still a pretty large amount of coverage for a queue that permits chain spamming of Shield Barrier.  F-110 also casts a little over half as many Shield Barriers as SBr* does, and the majority of them are 40-rage casts (14.47% @ 20-rage, 83.37% @ 40-rage, 2.16% @ 60-rage).

As far as the queue’s performance, TDR and rage generation fall squarely between SB and SBr*, and there’s almost no wasted rage to speak of.  The spike damage data is… well, surprisingly good, actually.  It’s solidly ahead of both SB and SBr* for two-attack strings, much like the Weave queues.  It has the same problems a SBr* at 3 attacks, with improved overall (80%) spike reduction at the cost of an increase in 90% events.  It’s similar to SBr* for 4-attack queues, though it does permit a small amount of 90% events.  But it beats SBr* pretty consistently for 5+ attacks.

While it isn’t as good as SB for eliminating 90% spikes across the board, it does generally give a lower percentage of 80%+ spikes overall.  If you’re less concerned with the exact distribution of spikes above 80% and more concerned with minimizing the total number of events that exceed 80%, it’s considerably better than either of the basic queues, and edges out the Weave and Bleed queues as well.  The only place it loses with that metric is for 6-attack strings, which SB eliminates completely.

Conclusions – Part 2

These simulations have been a bit of an eye-opener, I think.  We all expected to see a significant performance increase from combining Shield Barrier and Shield Block casts, but that increase failed to materialize in practice.  The simple Bleed queues failed to be all that attractive, and the Weave queues fell flat on their face rather than vindicating the “weaving” strategy many have been espousing as ideal.  And we got an unexpected surprise in the performance of the FCFS queues, which I had assumed would suffer due to low Shield Block uptime.

But what is perhaps the most surprising result is just how well the simple “Shield Block spam” queue held up.  Despite all of the criticisms of this queue – it was “simplistic,” “unrealistic,” and a “poor model for rage utilization” – you could make a strong argument based on these results that it was in fact the strongest performer against Patchwerk.  The ability to completely eliminate 90% spikes is a huge selling point, and not to be dismissed lightly.

It does raise a new questions though: where exactly ought we set our sights? Is is events exceeding 90% that matter most, or should we be minimizing everything over 80%?  If you aren’t going to survive an 80% spike anyhow, the significance of that distribution becomes less important.  And if that’s the case, these new FCFS queues may be worth considering further, as they’re incredibly effective in that department.  Just as you could make a good argument for SB based on 90% spikes, I think you could make a strong argument for F-110 based on 80% spikes.

It’s hard to crown a “winner” here as a result.  I think it’s clear that the Weave and Bleed queues were both disappointing, and wouldn’t qualify for the title without some external source of rage.  But I think it’s a pretty close toss-up between SB and F-110.  I can think of situations where I’d want one or the other, but I’m not sure which is the more general choice.  Adding magic damage into the mix ought to favor F-110, one would expect.  That’s something we can look into in another installment.  On the other hand, lower rage generation might favor SB, for example if someone isn’t hit- and expertise-capped.  That’s something we’ll analyze once we start looking at how stat distribution affects the results.  The excess rage could potentially be turned into Heroic Strike DPS (lower rage cost, especially with Deadly Calm active, which should eliminate the risk of Shield Block pushback).  And there’s a nerf to Shield Barrier coming in 5.2, so that may shift the results a bit too.

In any event, I’m going to perform future tests with several queues.  Certainly SB and F-110 are going to be included, and potentially SBr*.  They all have slightly different strengths and weaknesses, so it’s reasonable to expect them to vary differently with initial conditions.  It’s unlikely that I’ll consider the Weave or Bleed queues very heavily, but there’s nothing stopping us from trying them if the situation looks like it warrants it.

I’m actually not entirely sure which aspect we’ll look at next.  I have the simulations written, but haven’t cranked out or analyzed the data.  There’s a plethora of questions we could tackle.  What stat allocations are ideal? How does periodic magic damage affect queue choice?  What happens if we crank up/down boss damage significantly?  What effect does a longer swing timer have?  If you have opinions as to what’s more interesting, please share them in the comments.

Posted in Tanking, Theck's Pounding Headaches, Theorycrafting, Uncategorized | Tagged , , , , , , , , , , , , , , | 50 Comments

5.1 Warrior Simulations – Part 1 – The Model

It’s been quite some time since we last looked at warrior mechanics. While this is primarily a paladin-centric blog, I like to dabble in other classes from time to time, specifically when it seems like there’s something I’m uniquely suited to contribute.  That’s not to suggest there’s no warrior theorycrafting going on – certainly Tankspot and Elitist Jerks both have active theorycrafting discussions.  What they both tend to lack, however, is rigorous simulation-based modeling.  Simcraft is certainly quite accurate for warriors, but the interface seems to mostly focus on DPS results.  If there’s a way to analyze damage intake patterns, I haven’t found it yet.  And in any event, it’s always nice to have multiple, independent tools to verify results.

Numerical modeling is sort of my area of expertise when it comes to WoW, and especially given how similar the interests of protection warriors and paladins are, it seemed like spending some time to refine those earlier warriors simulations was justified.  I thought it was going to be a rather quick project and another one-off blog post.  But the deeper I got into it, the more interesting it became, eventually ballooning into a significantly larger and more time-consuming enterprise (unfortunately forcing me to push back several other, more paladin-specific projects as a result).  There’s no way that a single blog post would end up doing it justice at this point.

What follows is therefore the first of a series of posts critically analyzing the different options available to protection warriors.  You may remember that my initial stabs at this problem were fairly limited.  First, we looked at mitigation stat weights by using a  Monte-Carlo similar to the one I wrote for paladins and a very simple “spam Shield Block” model for finisher usage.  In the follow-up, I tried to address how Shield Barrier changes the stat priorities.  But there were a number of serious limitations to both of those models.  The goal of this series will be to eliminate those limitations, improve the model so that it’s sufficiently accurate, and see what it tells us.

Limitations of earlier modeling

The first and foremost limitation was the modeling of finishers.  Excluding Shield Barrier entirely was obviously not a great real-world model, and the “bleed” strategy implemented in the follow-up was at best a guess at proper usage.  It was suitable enough for simple TDR simulations, but really doesn’t accurately model how warriors claim to actually use Shield Barrier when they play.

A further wrinkle is that there doesn’t seem to be a consensus on what does constitute optimal Shield Barrier usage.  There’s been a variety of suggestions, and a lot of discussion in the comments of the last post and on a number of forums.  The most common idea presented was to “weave” Shield Barriers in during the downtime of Shield Block in an attempt to increase smoothing.  But there’s a lot of hand-waving in those suggestions and not a lot of specifics.  One of our objectives in these posts will be to try and quantify the specifics of that weaving process.

Many people found it surprising that mastery fared so well in the earlier models, and it ended up being a fairly major point of discussion.  I read a lot of comments expressing surprise that hit and expertise weren’t significantly better than the model predicted.  A lot of that surprise was based on misinterpretation though.  Remember that the earlier models were calculating total damage reduction (TDR) stat weights, and while those are interesting numbers, they’re also not always the most relevant.  For example, dodge and parry have the highest TDR stat weights for paladins, and hit and expertise are abysmal at TDR.  Yet we pretty much ignore dodge and parry completely in favor of hit and expertise because we’re more interested in damage smoothing than TDR.  So it’s not really surprising at all that hit and expertise aren’t killer TDR stats – there’s no expectation that they should be (and arguably, they shouldn’t be from a design standpoint if dodge and parry are to fill any niche).

This has led to some conjecture that the real power of hit and expertise is in the smoothing department.  After all, they’re amazing smoothing stats for Paladins, so it stands to reason that they may perform similarly for warriors.  To see that, though, we need more sophisticated metrics.  Calculating raw TDR-based numbers isn’t enough.  Thus, this time around, we’re going to thoroughly analyze the spike damage numbers (much like I’ve done for paladins) in addition to TDR.

Model Details

First, let’s go over the details of the model.  The files I’ve used can be found on the matlabadin repository:

warr_mc.m
warr_mc_finisher.m

warr_mc_finisher is just a script file that calls warr_mc multiple times with different options (i.e. different queues).  warr_mc is the guts of the simulation.  It’s a pretty standard Monte-Carlo style simulation which handles all of the combat rolls, tracks buff uptimes, spell cooldowns, and the global cooldown, chooses spells according to priority queues, and so on.  And of course, it spits back a bunch of statistics about the run that we can use later to determine what’s going on.

The code simulates 10000 minutes of combat for each trial in 0.5-second time steps.  This is long enough to get good, statistically stable results while still running relatively quickly.  Smaller time steps are not necessary for warriors as there are no haste-scaling effects to consider, and using a larger time step vastly decreases execution time.  To give you an idea of scale, it takes about 45 seconds to run a single trial – considerably faster than the 300-400 seconds it takes to run the paladin version of the code, which needs to use much smaller time steps.

The simulation will be using the file’s “default” gear set, which is based on a character with an average ilvl of about 496.  It’s been adapted from my paladin simulations, so it has the same 11k strength and 17150 points worth of secondary stats, but they’re allocated more appropriately for a warrior.  The exact stat allocation is as follows:

Strength: 11000
Parry Rating: 3000
Dodge Rating: 3000
Mastery Rating: 3000
Hit Rating: 2550
Expertise Rating: 5100
Armor: 63500

I’ve chosen to use hard hit and expertise caps for this set because one of the arguments for hit and expertise is that it allows more Shield Barrier use.  By allocating to reach the caps, we put ourselves in the best possible situation for Shield Barrier, which should  help us avoid bias introduced by being unnecessarily rage starved.  Once we’ve nailed down our “winning” finisher queues in this blog post, we can go back and try different stat allocations in a follow-up post.  The gear assumes the Eternal Primal Diamond is equipped and activated, and properly accounts for all stat conversions and diminishing returns (DR) calculations.  This set of stats gives you about  20.9% block chance, 31.4% critical block chance, 8.4% dodge, and 17.7% parry on the character sheet.  Note that against a boss, block, dodge, and parry are all 4.5% lower than the character sheet value.

The boss we’ll be using in the model is a Patchwerk clone with a 1.5-second swing timer and a raw DPS output of 310k for Vengeance purposes.  That means that the boss’s raw swing is 465k, which is about 150k damage after armor (52%), spec (25%), and Weakened Blows (10%) mitigation effects.  Vengeance is assumed to be static at the average value, which is a steady-state contribution of 124k AP.  The average 60-rage Shield Barrier absorbs 277k at this level of Vengeance and armor mitigation, or a little over 1.8 full boss swings worth of damage.  Note that all the damage in this simulation is physical at the moment – I plan on implementing a periodic magical damage source for a future blog post to see what happens, but it was simply too much complexity to add to an already long blog post.

The file contains two different “generator queues,” as I’ve described in earlier blog posts. One is a “steady-state” queue that casts spells according to the following priority:

Shield Slam > Revenge > Battle Shout > Thunder Clap > Devastate

Thunder Clap is only cast if Weakened Blows isn’t active.  Berserker Rage is also included in the simulation, and is cast essentially on cooldown, but since it’s off-GCD it isn’t part of the generator queue.  The second queue is a “short” queue that ignores Thunder Clap entirely to optimize for short, 30-second tanking intervals.  I’ve used the steady-state queue for everything in this post, as the differences are fairly negligible.  The cost of Thunder Clap is only about 0.03 rage per second (RPS) – less than 0.5% of our total rage income, which clocks in at around 8.1 RPS.  This generator queue agrees with most theorycrafting sources (EJ and Tankspot), and the RPS value is consistent with what I get from Airowird’s Spreadsheet.  I have also assumed that the warrior is using the Glyph of Unending Rage, so we have a more relaxed rage cap of 120.

The simulation tracks and records a great number of details for debugging and post-processing, but for analyzing the data presented below we only need to describe a few of them.  First of all, it records Shield Block uptime, which will be given in percentage and labeled “S%.”  It also records the normalized damage registered by each boss swing (i.e. 0 for an avoid, 0.69 for a block, 0.38 for a critical block, 1 for a full hit).  In post-processing, we perform a number of calculations on this string of damage events.

The simplest is to calculate the mean of damage intake, which we express in a normalized fashion as a percentage of maximum damage intake.  To clarify that a bit, the absolute worst case you’ll ever see is if you took every attack straight to the face (no blocks, avoids, absorbs, etc.).   That’s the maximum theoretical DTPS, so we call that 100% of maximum DTPS.  If instead you blocked every attack (no crit blocks, no avoids, etc.), it should be pretty clear that you’d be taking 69% as much damage as if you took every attack to the face.  And subsequently, the mean damage intake is 69% of the maximum possible DTPS in this normalization scheme.

When you have a mix of blocks, critical blocks, avoids, absorbs, and regular hits, it gets more complicated to calculate, but that’s what computers are for – MATLAB does all the hard work for us.   This normalized damage percentage it spits out gives us a nice, clear, understandable number that represents effectiveness.  If we want to talk about TDR, it’s understood that taking 55% percent of max possible damage is better than taking 60% or 70%, for example.

We also use this damage string to calculate a moving average DTPS in order to evaluate spike damage events, much like we’ve done for paladins.  The statistics we report for these moving averages are the percentage of events that fall above 80% and 90% of maximum theoretical intake.  This is a rough measure of the percentage of the time you’ll be subject to a dangerous spike event.  Since it’s not always clear what number of attacks we’re interested in, I’ve posted results for everything from a 2-attack moving average to a 7-attack moving average so that we can evaluate each independently.

I’ve also reported the standard deviation of spike damage intake to give us some idea of the variation about the mean.  In all cases I’ve used the 5-attack moving average to calculate the standard deviation, as it seems like a fairly reasonable spike window to care about (7.5 seconds) for a 1.5-second swing timer.

Finally, I’ve reported some additional statistics that are unrelated to the damage event string.  For each queue I’ve reported the number of Shield Barrier casts in thousands (“SBr(k)”) as well as the number of those casts that consume less than 60 rage (“SBr<60(k)”).  The reasoning for this will be clearer once we start looking at specific queues.  I’ve also reported the average generated rage per second for each simulation and the “excess rage” in thousands (“xsR(k)”), which is the amount of rage wasted by casting generators that put us above 120 rage.  For example, if we cast Shield Slam at 110 rage, we only gain 10 rage and add 10 to the “excess rage” counter.

Now that we’ve gone over all of that, let’s dive into the results.

Basic Queues

The first set of queues we want to check are the “basic” ones that exclusively use either Shield Block or Shield Barrier, but not both.  We don’t expect these to be our ideal queues, but they’re useful to determine certain general trends and for use as a benchmark for later queues.  The logic in use for each of these is as follows:

  • SB is just a simple “spam Shield Block if rage>=60″ finisher queue.
  • SBr is the complementary “spam Shield Barrier if rage>=20″ queue.
  • SBr* is simply SBr plus the conditional that the Shield Barrier buff isn’t active – i.e. we refuse to overwrite an existing Shield Barrier buff.
  • SBr60 simply raises the rage threshold of SBr to 60.
  • SBr60* is just SBr60 plus the refuse-to-overwrite conditional

As for how these queues sim out:

|      Set: |       SB |      SBr |     SBr* |   SBr60 |  SBr60* |
|        S% |   0.6667 |   0.0000 |   0.0000 |  0.0000 |  0.0000 |
|      mean |   0.5853 |   0.4864 |   0.4152 |  0.4203 |  0.4154 |
|       std |   0.1396 |   0.1780 |   0.2028 |  0.2269 |  0.2251 |
|    SBr(k) |   0.0000 | 206.4450 | 100.0000 | 73.6000 | 73.5750 |
| SBr<60(k) |   0.0000 | 206.4450 |  66.3290 |  0.0000 |  0.0000 |
|       RPS |   8.1027 |   7.3572 |   7.3596 |  7.3600 |  7.3576 |
|    xsR(k) | 861.4570 |   0.0000 |   0.0000 |  0.0000 |  0.0000 |
|    ------ |    --- 2 |   Attack |   Moving | Average |  ------ |
|       80% |  23.3978 |  14.7177 |  17.2875 | 22.6947 | 21.9303 |
|       90% |   7.9937 |  10.5173 |   8.5653 | 17.8223 | 17.2885 |
|    ------ |    --- 3 |   Attack |   Moving | Average |  ------ |
|       80% |   9.1665 |   3.1238 |   5.5723 | 12.2955 | 11.7200 |
|       90% |   0.0000 |   2.2260 |   3.9820 |  8.4932 |  8.1530 |
|    ------ |    --- 4 |   Attack |   Moving | Average |  ------ |
|       80% |   7.8185 |   5.2713 |   2.2310 |  6.5980 |  6.2198 |
|       90% |   0.0000 |   0.0000 |   0.0000 |  5.4610 |  5.1498 |
|    ------ |    --- 5 |   Attack |   Moving | Average |  ------ |
|       80% |   5.9015 |   2.1840 |   2.0305 |  4.4545 |  4.2405 |
|       90% |   0.0000 |   0.0000 |   0.0000 |  1.9775 |  1.8755 |
|    ------ |    --- 6 |   Attack |   Moving | Average |  ------ |
|       80% |   0.0000 |   0.2325 |   1.0405 |  2.9575 |  2.8235 |
|       90% |   0.0000 |   0.0000 |   0.0000 |  0.4120 |  0.3885 |
|    ------ |    --- 7 |   Attack |   Moving | Average |  ------ |
|       80% |   1.1783 |   0.5647 |   0.4083 |  0.7910 |  0.7565 |
|       90% |   0.0000 |   0.0000 |   0.0037 |  0.0175 |  0.0118 |

First of all, we note that the Shield Barrier queues are significantly ahead on total damage taken.  That isn’t surprising – at this level of Vengeance, a max-rage Shield Barrier absorbs about 1.8 boss attacks.  A single Shield Block cast can cover at most 4 attacks, and only guarantees 31% mitigation on each attack, or roughly 1.24 boss attacks.  That’s not accurate though, because some of those attacks may be avoided, and about 1 in 5 of them would have been blocked anyway.  The guaranteed block effect increases the mitigation of critical block, but that barely offsets the blocking losses.  In general, Shield Block will give you closer to about 1 boss attack worth of mitigation (and gets worse with more avoidance).

Conversely, avoidance makes Shield Barrier better, because an avoid doesn’t waste Shield Barrier’s absorption potential.  It does have a small effect, in that multiple avoids in a row could cause you to waste a Shield Barrier buff by not taking enough damage, but that’s relatively rare and thus has a very small effect.  This synergy between Shield Barrier and avoidance is interesting, because it’s very reminiscent of an early beta implementation of Shield of the Righteous.  It’s a positive feedback loop in which each one makes the other better.

In any event, the imbalance in the damage mitigated to rage spent ratio is a pretty significant factor.  The best Shield Barrier queue (SBr*) takes almost 30% less damage than the Shield Block queue, which is a pretty huge amount of TDR.  However, the comparison isn’t entirely fair, as the SB queue wastes a significant amount of rage – it only takes 6.667 RPS to maintain maximum Shield Block uptime, and anything over that is wasted without another rage sink to spend it on.

What we’re really interested in is the spike data though.  And this is where Shield Block really shows its strength – it is 100% effective at removing 90% spikes for strings of 3 or more attacks.  This should be obvious by inspection – you get 12 seconds of Shield Block uptime every 18 seconds, and this naturally falls into a 6-seconds-on, 3-seconds off cycle.  In 3 seconds, you’ll only ever see 2 boss attacks at this swing speed, so you’re always guaranteed to block at least one out of every 3 attacks.  And the relative damage intake of that is (0.69+1+1)/3=0.8967, or 89.6%.

It does less well for 80% spikes in short windows, but pretty quickly pares that down as well.   For 6-attack strings, it eliminates all of the  80% spikes thanks to guaranteed block coverage.  They pop up again for the 7-attack strings, which might seem surprising, but it’s just a result of combinatorics – as we increase string length, we get a periodic oscillation in the number of unblocked swings.  The moving average slowly damps away to zero as it rides this oscillation because of statistical averaging and avoidance (more swings = less likely to have zero avoids).

It’s also worth noting that most of these 80% events are right on the borderline, as in exactly 80%.  A little more passive mitigation and most of them might shift down below the 80% threshold, giving us much better results for SB.  We’ll see that more clearly on the histograms, though.

The SBr60 queues don’t do very well.  They have the characteristic lower TDR, but otherwise they only eclipse SB in one or two isolated instances, specifically in 80% spikes in the 4-, 5-, and 7-attack categories.  But the associated cost is an unacceptable amount of 90% spikes in all categories.  And for short attack strings they’re simply abysmal.  So we can safely rule them out as desirable queues.

The curious (and perhaps surprising) result here is how well the low-rage Shield Barrier queues perform.  Both the SBr and SBr* queues are very competitive with Shield Block in the spike damage categories.  They both all but eliminate 90% spikes for 4+ attacks and best SB in the 80% category for strings of 5 attacks or less.  It’s only for 6 attacks that Shield Block is clearly better, but SBr/SBr* have an edge in the 7-attack category as well.

I was also a bit surprised that the buff overwriting in the SBr queue doesn’t seem to hurt it too much.  While it isn’t broken down completely in the table, SBr casts almost exclusively 20-rage Shield Barriers (93% are 20 rage, 7% are 40 rage, none are 60 rage), while SBr* has a more varied mix (33% are 60 rage, 53% are 40 rage, and the remaining 13% are 20-rage casts).  One would expect that to mean we overwrite a 20-rage buff with another 20-rage buff fairly frequently, thus wasting a lot of potential.  And while it does carry a fairly significant cost in TDR, it doesn’t seem to hurt smoothness metrics.  In fact, it even improves some of them, especially for short attack strings.

I think what’s happening here is that since a 20-rage Shield Barrier absorbs about 60% of a boss swing, we’re getting situations where a critically-blocked attack won’t clear the Barrier buff.  SBr* would leave that weak, ~20% remaining Barrier in-tact so as to not waste any potential absorption, but SBr will over-write it with a new Barrier.  Thus, SBr will be significantly stronger against 2-attack strings, but for longer strings it won’t be much better than SBr*.  In fact, it seems like the two keep jockeying for position on odd and even numbers of attacks, suggesting we have another combinatorics effect going on here.

In fooling around with some numbers, SBr performed much more poorly than SBr* at higher armor values, where a single Shield Barrier cast covers a larger portion of a boss attack.  Conversely, SBr performed better at lower armor values.  So SBr seems to be more dependent on armor than SBr* is, making it a little more volatile.  It’s also worth noting that both Barrier queues are fairly sensitive to armor.  In the sims I’ve run at lower armor values, the absorption of Shield Barrier was about 20% weaker, and these queues ended up falling strictly behind SB.  That extra 20% was enough to make a noticeable difference in the strength of a single Shield Barrier cast.  Note that the armor-Barrier synergy we’re seeing here is very similar to the avoidance-Barrier synergy I spoke about earlier – armor makes each mitigated hit less, thus making Shield Block weaker compared to Shield Barrier.  This could explain the coming nerf – Shield Barrier is scaling a little faster than it should thanks to its synergy with armor and avoidance.

As a final piece of analysis, let’s look at the damage histograms for SB, SBr, and SBr*.  This is a plot of the 5-attack moving average DTPS that we’re using to calculate our 80% and 90% statistics.  Basically, it shows the distribution of damage spikes – lots of events up in the 80%-100% region means lots of spikes, fewer events in that region means fewer spikes.

Damage intake histogram for "SB" queue

Damage intake histogram for “SB” queue

The SB plot looks similar to the ones we’ve seen for the “control/haste” build for paladins.  Events up at the top end are heavily suppressed, but we still have a chunk (about 6% of all events) right on the borderline at 80%.  This is what I was talking about earlier; if we had set the arbitrary threshold at 81%, Shield Block would’ve looked incredible on the tables.  In any event, most of the damage is clustered between 50% and 80%, giving us the nice, smooth, predictable damage intake that we like.

Damage intake histogram for "SBr" queue

Damage intake histogram for “SBr” queue

The SBr plot has a wider distribution, as is evidenced by the larger standard deviation.  We also have a larger representation of spikes in the ~87% range, nearing the 90% danger threshold.  But the relative dearth of 60-rage barrier casts means that we have relatively few full absorbs.  Most of the damage is falling between 35% and 75% of max throughput.

Damage intake histogram for "SBr*" queue

Damage intake histogram for “SBr*” queue

The SBr* queue has an even wider distribution, thus a significantly larger standard deviation.  We get a lot more full absorbs and low-percentage strings with SBr*, which makes our damage a lot spikier.  That said, the dangerous spikes are fairly limited – we have a few percent in the 80%-90% window, and nothing above 90%.

It’s worth noting that both Shield Barrier queues are going to have spikier damage intake than the Shield Block queue thanks to the broader distribution.  However, it’s not clear that a wider spread necessarily means that we have a dangerous version of spiky.  Taking a consistent 60% of maximum DTPS may not be much better or worse than taking 70% some of the time and 50% the rest of the time, as long as healers are prepared for 70% throughput.  It may be more convenient for them to heal, but I suspect that as long as the spikes remain below a comfortable threshold your healer won’t care that much.  The “dangerous” spikes are the ones that exceed 80% throughput, which is why we look at them.  We’ll get a better look at “dangerous spiky” when we look at some of the later queues.

Conclusions from Part 1

Going forward, it seems that the two queues we want to use as our gold standard are SB and SBr*.  We could use SBr, but its more sensitive dependence on armor makes the results a little less general, and the TDR savings isn’t as significant.  In addition, SBr and SB have very similar histogram distributions, while SBr* has a significantly different, flatter distribution.  Since the results of SBr and SBr* are going to be similar, it may not matter too much, but it seems like a good idea to use the two that are most different just in case. So for each of the subsequent queue categories, I’ll include both of those columns on the table to make the comparisons easier.

In the next part of the series, we’ll start looking at more complicated queues that combine Shield Block and Shield Barrier.  These will include several versions of the simple “bleed” queues that I used in the early analysis, as well as some more sophisticated queues that attempt to intelligently interleave Barriers and Blocks.  While most of the work is already done, it’s fairly easy to add a queue type and model it, so feel free to suggest ways to perform that interleaving in the comments.

Posted in Tanking, Theck's Pounding Headaches, Theorycrafting | Tagged , , , , , , , , , , , , , , , | 11 Comments

Tankadin Meta Gems – Detailed Analysis

So far, we’ve been assuming that the Austere Primal Diamond was our go-to meta gem. With the massive changes to blocking in 5.0, the flat 1% block value afforded by the Eternal Primal Diamond can’t hold a candle to 2% increased armor, right?

This week, I received a private message from an EJ user asking exactly that question. They provided some quick-and-dirty numbers that compared the damage reduction of 1% extra block to the damage reduction of 2% extra armor. The extra armor mitigated more raw damage on a 100k hit than the extra block value did, and of course that’s not even accounting for the fact that block isn’t guaranteed. But there was still the extra avoidance granted by the Eternal diamond to consider, and they weren’t sure how to handle that.

As such, I figured it was time to break out the calculus and treat the problem properly.

We can start with the damage taken equation we developed all the way back in August:

$D = D_0 S F_{ar} F_{av} F_{b} F_{S}\large$

In this expression, $D$ is net damage taken after all mitigation effects, while $D_0$ is the boss’ raw (unmitigated) damage output. $S$ is the Sanctuary mitigation factor ($S=0.9$). $F_{ar}$, $F_{av}$, $F_{b}$, and $F_{S}$ are the armor, avoidance, block, and SotR damage mitigation factors, respectively. For now, I’m not going to repeat the definitions of the different mitigation factors, since they’re exhaustively in that earlier post.

To calculate the effect of the block or armor meta gems, we differentiate this expression to determine the change in damage intake $dD$ that each gives us.

Armor Meta

The armor meta essentially multiplies our armor by a factor of 1.02. There are some details there we’re glossing over (for example, this factor isn’t applied to armor from enchants or elixirs), but it’s such a minor correction that we can safely ignore it in this analysis. Since it has no other effect, it won’t change the factors $F_{av}$, $F_{b}$, or $F_{S}$, so our differential is simply:

$dD = D_0 S F_{av} F_{b} F_{S} dF_{ar}\large$

and we know from that earlier post that $dF_{ar} = \frac{dAr}{f_{ar}}F_{ar}$. $dAr$ is the change in armor, which is just $0.02Ar$, while $f_{ar}=Ar+K$ is the effective “rating-to-percentage” conversion factor for armor (again, see the August post for details on why we defined that value). Thus, the net change in damage taken is just:

$dD = \frac{0.02 Ar}{Ar + K} D\large$

Block Meta

The block meta gives us 1% extra block value and 432 avoidance rating. Thus, it will change the values of $F_{av}$ and $F_{b}$, but not $F_{ar}$ or $F_{S}$. This means that wen we differentiate, we get two terms:

$dD = D_0 S F_{ar} F_{S} \left ( F_{b}dF_{av} + F_{av}dF_{b} \right )\large$

The avoidance term is pretty easy, since its a dodge rating bonus – we can use the already-calculated result of

$dF_{av} = -\left ( \frac{dr_d}{f_d} \right ) \Phi_d\large$

where $dr_d$ is the amount of dodge rating added (432), $f_d$ is the dodge rating-to-percent conversion factor, and $\Phi_d$ is a factor defined in the August post that encapsulates the effects of diminishing returns.

The block term is also pretty easy. Starting with the definition of $F_{b}=1-B_v B_c$, with $B_v$ and $B_c$ representing our decimal block value and block chances respectively, we simply differentiate:

$dF_{b} = -dB_v B_c = -0.01*B_c\large$

Combining these two, we get:

$dD = -D_0 S F_{ar} F_{S} \left ( \frac{432}{f_d} F_{b}\Phi_d + 0.01*B_c F_{av} \right ) \large$

Plugging in Numbers

To see which of these has the largest effect, we plug in some numbers. I’ve put my current stats on Theck into my 5.1 Tankadin Stats Sheet, which spits out the numbers of interest:

$F_{ar}=0.5068$
$F_{av}=0.8150$
$F_{b}=0.9266$
$F_{S}=0.8009$
$\Phi_d = 1.0323$
$B_c = 0.2448$
$Ar=56815$
$K = 58370$
$f_d = 88500$

Plugging those into the expressions above, we get the following results.

Armor meta: $dD/D_0 = 0.2721\%$
Block meta: $dD/D_0 = 0.2435\%$

Surprisingly, the gap isn’t as large as we originally thought. The majority of the block meta’s mitigation comes from the avoidance (~0.17%, compared to ~0.07% for the block value increase). However, there are some other factors that make the armor meta hands-down superior to the block meta.

First, we have to note that the mitigation of the block meta is the combination of the dodge rating and the block value effect. However, the 2% armor bonus isn’t the only thing the armor meta gives you. It also gives you a nice chunk of stamina, which we value pretty highly, especially in a control gearing scheme.

Second, if you’ve been following this blog for any significant amount of time, you already know that we don’t put much stock in total damage reduction. We’re more interested in what makes you a better tank, and generally that means making you easier to heal and less likely to become a puddle on the floor. So it’s not just the amount of damage reduction that matters, but also how that damage reduction is applied. The armor meta is the quintessential smoothing mechanic – it applies to every single attack that gets through your avoidance, no matter what else happens.

On the other hand, the block meta is more erratic. It gives its damage reduction in chunks – an extra avoided attack here, or a little extra mitigation on a blocked attack there. By its nature, it’s “spiky” damage reduction. Even if the block meta gave slightly higher damage mitigation, we might shy away from it and favor the smooth mitigation of the armor meta, for exactly the same reason we choose control gearing strategies over avoidance gearing strategies.

Conclusions

In short, our intuition about our meta gem choices this tier were correct. The Austere Primal Diamond provides more overall damage mitigation than the Eternal Primal Diamond, does so in a “smoother” manner, and also gives a nice chunk of stamina. What’s surprising is just how close the mitigation values are – I don’t think many of us realized exactly how much mitigation that ~0.5% avoidance on the Eternal was worth. But either way, there’s just no compelling reason to pick up the Eternal diamond – it falls short in all of the categories we care about, and just ends up being the weaker option for survivability. If the Eternal option increased block chance by 1% in addition to increasing block value, it would at least pull ahead of the Austere in raw TDR, though that still isn’t enough to offset the stamina disparity in my mind.

I’ve updated the 5.1 Tankadin Stat Sheet to include the meta gem comparison above, even though it’s not something we’re likely to change. But at least you can play around with stats that way to see what it would take to push the block meta ahead in raw TDR. I’ll also note that I’ve used a more careful calculation for the spreadsheet. Since the sheer amount of avoidance granted by the Eternal diamond is enough to significantly affect the amount of diminishing returns experienced, I’ve instead calculated the actual damage mitigation values before and after equipping each meta rather than using differentials.

You may notice that I didn’t mention the Effulgent Primal Diamond at all in this analysis. I don’t think that it’s particularly compelling for the majority of encounters in this tier. For that meta to become attractive, you’d need around 30%-40% of your total damage taken to be magical in nature. Luckily, it’s a drop-in replacement for the Austere diamond, so you can just swap them around for fights that do satisfy that constraint (Lei Shi being an obvious one).

Posted in Tanking, Theck's Pounding Headaches, Theorycrafting | Tagged , , , , , , , , , , | 8 Comments

Damage Smoothing for Paladins – Round Three

It’s been almost two months since we took a close look at damage smoothing and gearing strategies.  In that post, we definitively concluded that the “control” gearing scheme, which focuses on reaching hit and expertise caps before other stats, was better at eliminating spike events than more traditional gearing methods.  However, that benefit comes at a price: increased overall damage intake.

There were a few things I wanted to clean up about those simulations, however.  The first and least technical issue was the formatting of the output.  It was a pain to figure out what was going on in the tables, even for me, because they were labeled with a gear set number rather than a descriptive title.  I found myself constantly looking back at the gear set list to figure out which set was which, especially when coming back to the post after a few weeks.  While this isn’t a hard thing to fix, it’s something that sorely needed to be done, so I’ve corrected that problem for the current round of simulations.

The second issue I wanted to address was the actual stat allocations of those gear sets.  For starters, I was pretty cavalier about allocating stats as I saw fit in the last round, especially with mastery (lol @ a gear set with 58 mastery rating?). However, we’re rarely going to be able to pick up ideal gear.  On Theck, I’m “stuck” with about 2500 dodge rating and 3000 parry rating, as well as about 1700 mastery rating.  I’d love to convert all of that to haste, but there’s just no way to do it.  Thus, instead of having complete freedom with the allocation of the secondary stats, this time I’ve enforced a minimum amount of mastery, dodge, and parry.

In addition, none of them were actually hit- or expertise-capped.  They all stopped at least 30 points shy of each cap.  Initially, I meant to do this so that I had some head room to test adding additional amounts of each stat – for example, to see whether adding 30 mastery or 30 hit was a better choice when you were very close to hit cap.  Unfortunately, I never got around to doing those simulations at the time.  And there’s a further problem with that plan which would have emerged had I tried: in a Monte-Carlo simulation such as this, 30 points worth of stat is a small enough change that the effect tends to be smaller than statistical variations.

However, it’s definitely a point we need to address as there’s an ongoing debate about how critical it is to reach or exceed hit and expertise caps.  The arguments against strictly enforcing caps are generally that being a few tenths of a percent under cap isn’t a problem because those events are so statistically rare that they’re not worth worrying about.  The arguments for strict capping focus on the fact that the entire point of the control strategy is to eliminate those events, and that it isn’t worth giving up the certainty that your resource generators will hit just to gain a tiny amount of extra damage reduction from TDR stats.

To try and answer this question, I’ve re-worked most of the gear sets to make them more useful, as well as updating them to reflect a more realistic gear level for entering heroic content.  I modeled them off of my stats on Theck, but adjusted them slightly by choosing nice round numbers.  The gear sets all have 11k strength, and then have 17150 rating worth of secondary stats, which is approximately what you have at an average gear level of 496.  That amount of rating is enough to hit and expertise cap and still have 9500 left over to distribute amongst avoidance, mastery, or haste.

We’re also going to look at results for two different encounter situations.  The first is our gold standard: a Patchwerk boss with a 1.5-second swing timer that just beats the hell out of us.  This is our best model for a boss whose melee attacks are the most threatening element of the encounter for us as tanks.  However, Schroom brought up an interesting question over at maintankadin about whether avoidance gearing might still be preferable in multi-mob situations, such as phase two of Grand Empress Shek’zeer.

So we’ll also analyze data for the case of a Patchwerk boss with a 0.25-second swing timer, which approximates having 6 mobs on you at a time, each of which has a 1.5-second swing timer individually.  This also assumes that they’re all hitting you at a staggered pace, which is a middle-of-the-road situation.  However, if all of their timers were aligned, careful timing of SotR would allow you to preferentially cover the high-spike situations, making it even more powerful.  Of course, the converse is true: if you time SotR badly, you might take worse spikes in that situation.  However, that situation ends up just being a close approximation to the usual Patchwerk model, so it doesn’t tell us anything new either.  If we’re hoping to be fair about things, the staggered-attack case is a more realistic “worst case” situation for a talented tank, so we’ll stick with that.

Gear Sets

The gear sets I’ve worked out are shown in the table below.  I’ve ignored the case of expertise soft-capping, as our last round of simulations have sufficiently convinced us that there’s no advantage to stopping there.  Instead, we’ll look at a variety of Control and Avoidance gear sets.

|    Set: |  C/Ha |  C/Ma |  C/Av | C/Bal | C/Bal-NC | Avoid | Av/Mas | Mas/Av |
|     Str | 11000 | 11000 | 11000 | 11000 |    11000 | 11000 |  11000 |  11000 |
|   Parry |  2000 |  2000 |  4000 |  2375 |     2375 |  7325 |   6000 |   4000 |
|   Dodge |  2000 |  2000 |  4000 |  2375 |     2375 |  7325 |   6000 |   4000 |
| Mastery |  1500 |  5500 |  1500 |  2375 |     2575 |  1500 |   4150 |   8150 |
|     Hit |  2550 |  2550 |  2550 |  2550 |     2450 |   500 |    500 |    500 |
|     Exp |  5100 |  5100 |  5100 |  5100 |     5000 |   500 |    500 |    500 |
|   Haste |  4000 |     0 |     0 |  2375 |     2375 |     0 |      0 |      0 |

The first three are control/haste, control/mastery, and control/avoidance, which are almost exactly what you’d expect.  They all have 2000 dodge rating, 2000 parry rating, and 1500 mastery rating standard thanks to our enforced minimums, and then allocate stats for hit and expertise caps.  The leftover 4000 rating then goes into the appropriate stat, split evenly between dodge and parry in the Control/Avoidance case.

The next two are what I call a  “control/balance” gear set.  In this case I instead split that 9500 rating evenly amongst parry, dodge, mastery, and haste, such that each gets 2375 rating.  The goal is twofold: one, to have a reference set that’s a more realistic estimate to what most players will be using, and also to determine whether it’s better to focus heavily on one secondary stat or to spread that itemization over different areas.  The second set is a “flawed” control/balance gear set that doesn’t quite reach hit or expertise caps.  It’s 100 rating below each cap, with that excess itemization shifted into mastery.  Again, the goal here is to see whether there’s any significant advantage to strictly observing the caps, or whether it’s OK to sit ~0.3% below each cap.

The remaining three gear sets are avoidance- and mastery-based sets.  We have an avoidance set that drops our hit and expertise ratings to 500 each, and puts all 14650 of the leftover rating into dodge and parry.  We also have an avoidance/mastery set that shifts a little of that avoidance back into mastery.  And finally, we have a mastery/avoidance set that focuses on beefing mastery up while still keeping an above-average amount of avoidance itemization.  Hopefully, these sets will span the space of cases we’re interested in.

Damage Smoothness Analysis – Regular Boss

The table below lists the results for our simple Patchwerk boss, arranged by gear set and the number of attacks over which we perform the moving average.  Each entry is the percentage of all events that fall into that window: so for example, the “80%” line contains data that tells us the percentage of all spikes that exceed 80% of max theoretical throughput (i.e., none of the attacks being mitigated or avoided).

|   Set: |    C/Ha |    C/Ma |    C/Av |   C/Bal | C/Bal-NC |   Avoid |  Av/Mas |  Mas/Av |
|     S% |  0.4543 |  0.4152 |  0.4151 |  0.4379 |   0.4358 |  0.3534 |  0.3544 |  0.3538 |
|   mean |  0.5799 |  0.5478 |  0.5595 |  0.5678 |   0.5670 |  0.5351 |  0.5312 |  0.5261 |
|    std |  0.1319 |  0.1300 |  0.1431 |  0.1337 |   0.1340 |  0.1669 |  0.1612 |  0.1542 |
| ------ |  ------ |   --- 2 |  Attack |  Moving |  Average |  ------ |  ------ |  ------ |
|    80% | 10.1583 | 12.6313 | 11.5818 | 10.9463 |  11.2483 | 15.4707 | 16.2007 | 17.6840 |
|    90% |  6.8462 |  7.5065 |  7.7990 |  7.1493 |   7.3093 | 10.3928 | 10.0268 |  9.6502 |
| ------ |  ------ |   --- 3 |  Attack |  Moving |  Average |  ------ |  ------ |  ------ |
|    80% | 10.7928 |  9.4153 | 11.4168 | 11.0675 |  11.3118 | 12.5280 | 11.2655 | 11.5750 |
|    90% |  0.9430 |  1.1973 |  1.2717 |  1.0898 |   1.1250 |  3.3348 |  3.1488 |  2.9970 |
| ------ |  ------ |   --- 4 |  Attack |  Moving |  Average |  ------ |  ------ |  ------ |
|    80% |  2.4950 |  3.5423 |  3.2400 |  2.8768 |   3.0308 |  6.0340 |  6.5250 |  5.5388 |
|    90% |  0.0000 |  0.0193 |  0.0163 |  0.0000 |   0.0778 |  2.0045 |  2.1345 |  2.3832 |
| ------ |  ------ |   --- 5 |  Attack |  Moving |  Average |  ------ |  ------ |  ------ |
|    80% |  2.3895 |  1.4245 |  2.3105 |  1.5755 |   1.6275 |  4.2990 |  3.8393 |  3.2715 |
|    90% |  0.0000 |  0.0110 |  0.0128 |  0.0000 |   0.0462 |  1.2333 |  1.2523 |  0.7850 |
| ------ |  ------ |   --- 6 |  Attack |  Moving |  Average |  ------ |  ------ |  ------ |
|    80% |  0.3575 |  0.0168 |  0.0290 |  0.1855 |   0.3030 |  2.3022 |  2.4695 |  2.2470 |
|    90% |  0.0000 |  0.0000 |  0.0000 |  0.0000 |   0.0080 |  0.4150 |  0.3663 |  0.3828 |
| ------ |  ------ |   --- 7 |  Attack |  Moving |  Average |  ------ |  ------ |  ------ |
|    80% |  1.2565 |  0.0000 |  1.3030 |  0.7735 |   0.7867 |  2.4328 |  1.8857 |  1.1427 |
|    90% |  0.0000 |  0.0000 |  0.0000 |  0.0000 |   0.0000 |  0.1210 |  0.1348 |  0.1515 |

There’s a lot of data here, and we could spend days comparing and discussing different features.  However, I’m going to try and summarize the major points and leave the nitty-gritty discussion for later, either in the comments or a future blog post if it’s warranted.

First, we see the same features that we observed last time. Control builds are better at reducing the frequency of spikes than the avoidance or mastery builds are, and within the control subset the haste sub-build does the best job of eliminating 90% spikes.  For strings of 4 or more attacks, 90% spikes are all but non-existent (<0.0001%) in the control/haste build.  The haste sub-build is also best at reducing “short” 80% spikes (2-4 attacks) while the mastery sub-build is significantly better at removing “long” 80% spikes (5+ attacks).

In fact, we see a resurgence of 80% events in the control/haste build at 7 attacks – this is a feature that existed in the old data as well, but I didn’t discuss it at the time.  Because of the periodic on/off nature of SotR’s coverage, the representation of 80% spikes will slowly oscillate as it decays with increasing number of attacks.

We also see that the control/avoidance build isn’t significantly worse than the haste or mastery sub-builds, but it also doesn’t appear to have any clear advantage either.  My advice here is similarly unchanged: control/avoidance is less dependent on player skill than the other sub-builds, so it might be a good stepping stone between Avoidance and control/haste for a tank that’s not as confident in their rotation.

The avoidance builds, including the mastery-focused version, are all inferior for spike prevention.  There is literally no case where an avoidance build can keep up with a properly-played control build.  The mastery/avoid build outperforms its peers, somewhat predictably, but it’s still far behind the control offerings.  The only thing that the avoidance builds excel at is total damage reduction (TDR): the mastery/avoidance build takes between 4% and 10% less damage than the control builds (relatively DR – in absolute terms it’s ~2%-5.5%).

For the more graphically/visually inclined, here’s another way to see those results.  Below are the histograms of all 5-attack spike events for the control/haste and avoidance gear sets:

Histogram of spike event damages for 5-attack strings using the Control/Haste gear set

Histogram of spike event damages for 5-attack strings using the control/haste gear set. Note the complete absence of events above 85%. This is what hit/exp capping does for you: it eliminates the very worst spikes.

Histogram of spike event damages for 5-attack strings using the Avoidance gear set

Histogram of spike event damages for 5-attack strings using the avoidance gear set. Unlike the control gear sets, the avoidance set gives you a much wider range of damages (broader distribution) with a significant amount of high-damage spikes.

Again, the point here is that while the Avoidance set gives you a lower mean, the distribution is much broader and includes plenty of dangerous spikes in the 80%-100% range.  The control set sacrifices some of that raw TDR to preferentially eliminate those high-damage spikes and narrow up the damage distribution, resulting in smoother and less threatening damage intake.

None of that is news, though – we knew all of that.  What is news is what we learn from the control/balance gear sets.  First of all, they generally lag control/haste slightly, but perform almost as well.  That’s in large part due to their similarity – they have almost the same amount of avoidance (barely above the minimum), about 800 more mastery, and still have almost half the haste that control/haste does.  In short, the performance of the Balance gear set is still primarily dominated by the generous amount of haste and mastery it contains.  This just emphasizes that you don’t need to stack 6000 haste to get the sort of benefits we saw in the last round of simulations.  It’s an excellent control stat even in small amounts, so feel free to stack it early and stack it often, because it will pay great dividends.

Furthermore, the un-capped version of the balance set shows us exactly what hit- and expertise-caps  give us.  By dropping below the cap, even by as little as 0.3%, we have a significant increase in spikes in the 4- to 6-attack region.  Whereas the default balance set effectively eliminates 90% spikes for 4+ attack strings, those strings still show up in the uncapped versions until we get to 7-attack strings.  Admittedly, their representation is small: generally on the order of tenths or hundredths of percent.  But it’s still several orders of magnitude worse than the capped case, and the benefit is less than 0.14% less damage taken overall.

In my opinion, that’s a bad trade-off.  I’m not going to notice that amount of overall damage reduction, and while I’m not terribly likely to take a 4-attack 90% spike either (0.0778%), that’s still high enough to happen once every 1-2 hours, on average.  I’d rather avoid that potential wipe entirely and eat the extra damage.  I think this data supports the argument that it’s better to be a little over the caps and waste a few points of itemization than try to maximize your numerical “score” and chance running into those potentially-deadly spike situations.

Damage Smoothness Analysis – AoE Tanking

We can repeat this for the 0.25-second swing timer, but in this case we want to average over more attacks.  Averaging over 2 attacks is sort of pointless, as that’s only half a second, and you’re not likely to be taking enough throughput damage to die in such a short period while AoE tanking.  The concept is that overall damage taken per second is similar to the first situation, but it’s split amongst more mobs – thus, since we have 6 mobs, each attack is only 1/6 the size of our regular model.  What we’re concerned about is spike lengths on the order of those used in the earlier model, so we look at groups of 15, 20, 25, and 30 swings.  These correspond to 3.75-, 5.00-, 6.25-, and 7.50-second spike windows.

|   Set: |   C/Ha |   C/Ma |   C/Av |  C/Bal | C/Bal-NC |  Avoid | Av/Mas | Mas/Av |
|     S% | 0.4537 | 0.4152 | 0.4155 | 0.4381 |   0.4358 | 0.3543 | 0.3544 | 0.3544 |
|   mean | 0.6333 | 0.6105 | 0.6114 | 0.6238 |   0.6227 | 0.5756 | 0.5775 | 0.5805 |
|    std | 0.1932 | 0.2079 | 0.1996 | 0.1977 |   0.1982 | 0.2065 | 0.2099 | 0.2186 |
| ------ | ------ | --- 15 | Attack | Moving |  Average | ------ | ------ | ------ |
|    80% | 8.7618 | 8.7283 | 7.1310 | 8.4270 |   8.4127 | 4.4684 | 5.3790 | 7.0031 |
|    90% | 1.1410 | 1.0177 | 0.8511 | 1.0665 |   1.1059 | 0.4231 | 0.4815 | 0.5841 |
| ------ | ------ | --- 20 | Attack | Moving |  Average | ------ | ------ | ------ |
|    80% | 3.8405 | 3.9843 | 3.3426 | 3.7652 |   3.8137 | 2.3411 | 2.7956 | 3.7285 |
|    90% | 0.1936 | 0.2284 | 0.1825 | 0.1965 |   0.2323 | 0.1147 | 0.1550 | 0.2055 |
| ------ | ------ | --- 25 | Attack | Moving |  Average | ------ | ------ | ------ |
|    80% | 1.0867 | 1.2077 | 1.0433 | 1.0653 |   1.1755 | 1.0666 | 1.3407 | 1.9188 |
|    90% | 0.0010 | 0.0174 | 0.0183 | 0.0083 |   0.0197 | 0.0245 | 0.0406 | 0.0627 |
| ------ | ------ | --- 30 | Attack | Moving |  Average | ------ | ------ | ------ |
|    80% | 0.1583 | 0.1771 | 0.2115 | 0.1528 |   0.2231 | 0.4740 | 0.6308 | 0.9288 |
|    90% | 0.0000 | 0.0000 | 0.0000 | 0.0000 |   0.0027 | 0.0053 | 0.0085 | 0.0097 |

The main thing to notice here is how much avoidance improves.  By using a much shorter swing timer, we’re closer to the stochastic situation that favors avoidance.  Avoidance does a crappy job when it’s got one chance to work in a 1.5-second period, but when you give it six chances to trigger in that same time period, statistical averaging works to its benefit.  The avoidance sets not only give lower overall damage taken, but tend to do a better job with the shorter (15- and 20-attack) spikes.

However, as we move to longer time scales the control sets start to pull ahead. By the time we reach a 25-attack sequence (6.25-second window), control/haste has pulled solidly ahead in all categories, and beats avoidance by a factor of 20 or more in spikes above 90%.

So it depends on what you’re trying to optimize. Avoidance will give smoother overall intake for periods of <4 seconds, control/haste will generally equal or outperform avoidance at 5+ seconds. Note that this analysis is also ignoring cooldowns, which would tend to favor control strategies since you can optimize your SotR coverage by banking HP during cooldown effects and burning it between cooldowns.  For example, you could alternate cooldown-SotR-SotR-cooldown-SotR-SotR-, so that you have 6 seconds of SotR uptime in-between other DR cooldowns to stretch out your coverage window.

Conclusions

Mostly, this post has been re-confirming results we already had.  The big news is that reaching or exceeding hit and expertise caps is just as important as many had surmised.  Sitting 0.3% below hit and expertise caps is basically admitting that about once per raid night, you’re going to take a big spike event due to missed generators, and the only benefit is a negligible amount of overall damage reduction.  That’s rare enough that you probably can get away with it, but there also doesn’t seem to be much point in risking it.  Better to slightly over-cap and be sure than to duck the cap and risk causing an unnecessary wipe.

In addition, it looks like the AoE scenario isn’t all that different from the basic Patchwerk model.  Control builds still perform strongly over long enough time periods, as expected.  However, an argument can definitely be made for avoidance gearing if you’re concerned with high throughput in short time periods – i.e. a 3-4 second burst window from a large amount of adds.  I don’t think it’s necessarily worth overhauling your gear for such a situation, especially if the encounter also has single-target sections, but if we end up with an extremely difficult fight that relies on us AoE tanking a lot of dangerous mobs (heroic Nefarian adds come to mind), it might be an avenue we’d consider.

Finally, since I know we get a fair number of warriors wandering through here, I want to mention that these results aren’t strictly applicable to warriors, as your mechanics are slightly different.  I expect that the same sorts of trends will exist (i.e. hit/exp for smoothness, avoidance for TDR), but it’s impossible to estimate numbers based on the paladin results.  It would just be guesswork, at best.  Luckily for you, I’m working on an identical set of simulations for Warriors, so hopefully I’ll have results for you within the next few weeks.

Posted in Tanking, Theck's Pounding Headaches, Theorycrafting | Tagged , , , , , , , , , , , , , , | 15 Comments

Tankadin WeakAuras Strings: 5.1 update

Many of you noticed that a few of the elements of my WeakAuras setup broke with 5.1.  Blizzard made a change to the return values of UnitBuff, which was throwing off the Vengeance display.  And the Sacred Shield and Bastion of Glory indicators were intermittently breaking.  The Vengeance aura was pretty easy to fix, at which point I started trying to reproduce the SS/BoG bugs… and couldn’t.  After a few days of monitoring, I was stumped – either the error in the Vengeance text was also causing the SS/BoG errors, or else it was something far more subtle and hard to reproduce.

However, I got confirmation on twitter from Kelerei that he saw the same behavior once he fixed the Vengeance aura.  So at this point, I’m going to assume the SS/BoG bugs were indirect errors and are fixed (either that, or a new version of WeakAuras fixed them).

In the meantime, I’ve also made a few minor additions.  I frequently found myself wanting to know how long was left on the cooldown for Light’s Hammer, so I added cooldown trackers for all three L90 talents (in the same place as their “available” icon was, on the priority row).  I also added a cooldown icon/tracker for Devotion Aura to the “cooldowns” row.

Below are the updated strings.  I haven’t made a new video since not much has changed; if you want to see what they look like, check the YouTube video in the 5.0.5 post.

Priority Row:

dC0GkbGifc5tkeWOevXPevPzPqq3IkWUOsfnmfQJrfTmufpJIY0uaxtrzBuu13uqnovk6CuP4EuuP9PqGoivOfQipuuvtKkOlsLQ2ifv4Jke1ivi5KuP0kvPQzQaDtQuj7uP(PcYqvuTuvk9uOPIWvPsLARuur6RkeQZsrf1CviYEj)fLgmQCyjTyQKhJOjJIld2Sk5Zkz0uKtRQvRsHxRqQzlXTPWUr63ImCrz5u1ZLA6cxNsBhv13rvA8Qu58IkRNkvy(uurSFvSCkcHvrOqyl0P7Ca35WUZBk0qiJqgri0dRprjYLbcx(KntydLR5PNgcNgIGyi31GU3CqieUlRszagnjKAni8)Ab(wBNcFgHeMaYr7G5(u4G5(p5)iNWsQYicH(ubeHqdBjErOqHcfcjfH2ofHqsBhjdc4Uq45(Z9cT0W)Rf4fHWodkLD1a0EMzMF8yfcd)VwGxecTnW(u(GVbnjK02rYG10ZacJ3ayeABG1dg1N(0LCjSZGszxnaTNzM5hpwywIxWZMYaFnsEHJGMRWSeVGxOzcb(aneoQuj3HBEIxWl02aRL(HMeg5YaHDudBl02aBNbLYUAaAsOTb2SeVGxtcTuGpqdHvBKesA7izWg5YaHDudBRqOj4xMcThySWsQYicH2gyPaFWlxcjl1UfHW(PRciCUJd6OdD7wHqBdSKLA3AsOpvari0WwIxekuiKwnaHyokfeABGTZasnj02alTAaYLqBdSKjdx1qtc7mGuec7NUkG28OqHWRenW3DaAZZyHEy9jkrUmq4tMOcz((gwkz88bnjSJk5O75PNgcZ39Bc3FRWkdZhFIwlSH)xlW3IqBNIqy4)1c8IqyBDb8bAm3dx)DcX5UFWbfg5YaHvRVkKbCzVUiYLbchL7hCU5WDpOW26c4d0aTxx)DczZ3rKGfjC8wcH0Qb0IqBNcD4Z)PWHBU1NLAqHql9dHzLAoWle4d0q4OGAjmjK02rYG10ZacJ3ayui0sd)VwGxekuOqyLm(eTfHWoQ(qec7KLYi0T0a8xvsyKCKHjr7rAed1r7O1x7rAEIxW7O1xB3fW81rctwktpsJUsA6Pl3zATeYKy7KLYixkeE90VnjcHmjwsBhjd5sHcHpJq00dfMdx66WfMGd3T)YuajBl8UHUUAiK5WbdB(Hh78MMNhEUPB4XnZgBMUCWaMx4LVAay4RrvB3iK3NjmP9aJfsTge(FTaFRnpcZn01vdH2oy4Xcz(oRuZ5wYevOBPb4VQKWi5wYeThjhD9LpYXoVwQmpLfn9qHjDzofOlOsjbHKPuHjXlvUegWDr(PsYlcTDQ9yTntMJbg2mZC6MbCZyEgWnonBGz6YbZmtHcT5recz((gwkz88bnjK02rYGaUleEU)CVWCdDD1qOTdgESWkz8jAlcHDu9Hie2jlLrOBPb4VQKWi5idtI2J0igQJ2rRV2J08eVG3rRV2UlG5RJeMSuMEKgDL00txUZ0AjKjX2jlLrtkeE90VnjcHmjwsBhjd5sHcHH)xlWlcH2gyZs8cEnj02aRL(HMesA7izWA6zaHXBamcJCzGWoQHTfML4f8cNjmlXl4ztzGVgjVWrqZviWhOHWrLk5oCZt8cEHK2osgSrUmqyh1W2cTnW6bJ6tF6sUeABGTZGszxnanj02a7t5d(g0Kqlf4d0qy1gjHDguk7QbO9mZm)4XkeAc(LPq7bglSKQmIqOTbwkWh8YLqYsTBriSF6QacN74Go6q3Uvi02alTAaYLqFQaIqOHTeViuOqiTAacXCuki02aBNbKAsOTbwYsTBnj02alzYWvn0KWodifHW(PRcOnpkui8krd8DhG28mwOhwFIsKlde(KjQqYuj5fH2dO9yfcjtPctIxQCj8zeIMEOWC4sxhUWeC4U9xMciz7dNdF6s4LVAay4RrvB3iK3NjmP9aJfAPH)xlWlcHDguk7QbO9mZm)4XkesTge(FTaFRnpcVBORRgczoCWWMF4XoVP55HNB6gECZSXMPlhmG5fwzy(4t0AHn8)Ab(weA7uecd)VwGxecjTDKmyn9mGW4nagHrUmqy16Rczax2RlICzGWr5(bNBoC3dkSTUa(anq711FNq28DejyrchVLqOL(HWSsnh4fsRgqlcTDk0Hp)NchU5wFwQbfcb(aneokOwctcBRlGpqJ5E46Vtio39doOcHwA4)1c8IqHcfcz(oRuZ5wYevOBPb4VQKWi5wYeThjhD9LpYXoVwQmpLfn9qHjDzofOlOsjbHDujhDpp90qy(UFt4(BfgWDr(PsYlcTDkZH5hWnUXmN8mWyZgGNXUzMtD5GzZ02mzogWndmZjpUz8yEm)yEUPBCJUCWSb0EaThRqH2MjcHmFFdlLmE(GCjm3qxxneA7GHhlm8)AbErimYLbc7Og2wiPTJKbBKlde2rnSTqBdSg1G0eWCRLcAsOTb2NYh8nOjHaFGgcZpLkmjEPhU5(0YdDF4YdMbLsEfABG1s)qtcTnW2zqPSRgGMesA7izWA6zaHXBamcTuGpqdHvBKeABG1dg1N(0LCjSZGszxnaTnBMzUzMcHMGFzk0EGXclPkJieABGLSu7wtc9PcicHg2s8IqHcH2gyPaFWlxcTnW2zaPMeABGLmz4QgAsyNbKIqy)0vb0Mhfcjl1UfHW(PRciCUJd6OdD7wHcHEy9jkrUmq4tMOcVBORRgcTDG5NjSYW8XNO1cB4)1c8Ti02Pieg(FTaVieg5YaHvRVkSTUa(anq711FNq28DejyrchVLqiWhOHWrb1sysiTAaTi02PWrmuhnqbMd3ujXBRqOTHBbdnj0dgcNj0dgdLb(AK8chbnxHT1fWhOXCpC93jeN7(bhuOL(HWO6xqiKbCzVUiYLbchLJ36UmhU7bvi0sd)VwGxekuOq4ZimFu4LVAay4Rrv7beY7ZeM0EGXcT0W)Rf4fHWodkLD1a02SzM5MzkesTge(FTaFRnpcjtPctIxQCPq7beHqMVVHLsgpFqUeMBORRgcTDWWJfg(FTaVieABG1dg1N(0LCjK02rYGnYLbc7Og2wOTbwJAqAcyU1sbnj02a7t5d(gKlHaFGgcZpLkmjEPhU5(0YdDF4YdMbLsEfABG1s)qtcTnW2zqPSRgGMe2zqPSRgG2MnZm3mtyKlde2rnSTqlf4d0qy1gjHK2osgSMEgqy8gaJcHz(0YdDp3dKF)jQ2JfAc(LPq7bglSKQmIqOTbwYsTBnj0NkGieAylXlcfkeABGLc8bVCj02aBNbKAsOTbwYKHRAOjHDgqkcH9txfqBEuiKSu7wec7NUkGW5ooOJo0TBfkeELOb(UdqBN3uOhwFIsKlde(KjQWoQKJUNNEAimF3VjC)TcFgH5JhU8DOWlF1aWWxJQ2diK3NjmP9aJf(u(GVbnjKAni8)Ab(wBEeAPH)xlWlcHDguk7QbOTzZmZnZui8UHUUAi02bMFMWkdZhFIwlSH)xlW3IqBNIqy4)1c8IqyKldewT(QW26c4d0aTxx)DczZ3rKGfjC8wcHaFGgchfulHjH0Qb0IqBNchXqD0afyoCtLeVTcH2gUfm0KqpyiCMqpymug4RrYlCe0Cf2wxaFGgZ9W1FNqCU7hCqHw6hcJQFbHqgWL96IixgiCuoER7YC4UhuHqln8)AbErOqHcHKPuHjXlvtk0EMieY89nSuY45dYLqln8)AbEriSZGszxnaTNz2m3mtHWW)Rf4fHWodkLD1a0EMzZCZmHrUmqyh1W2cTnW6bJ6tF6sUesA7izWg5YaHDudBl02aRrninbm3APGMeABG9P8bFdAsiWhOHW8tPctIx6HBUpT8q3hU8GzqPKxH2gyT0p0Kqlf4d0qy1gjH2gy7mOu2vdqtcjTDKmyn9mGW4nagfcnb)YuO9aJfwsvgri02alzP2TMe6tfqecnSL4fHcfcTnWsb(GxUeABGTZasnjSZasriSF6QaAZJcH2gyjtgUQHMeswQDlcH9txfq4Chh0rh62Tcfc9W6tuICzGWNmrfE3qxxneA7aZptizkvys8sLlHvgMp(eTwyd)VwGVfHcHx(QbGHVgvTntiVptys7bglm3qxxneA7GHhlKAni8)Ab(wBNcFgHJkf3QqBZlcHwA4)1c8IqyNbLYUAaApZSzUzMcHH)xlWlcHK2osgSMEgqy8gaJqBdSEWO(0NUKlHK2osgSrUmqyh1W2cTuGpqdHvBKeABG1OgKMaMBTuqtcTnW(u(GVb5siWhOHW8tPctIx6HBUpT8q3hU8GzqPKxH2gyT0p0KWixgiSJAyBH2gy7mOu2vdqtc7mOu2vdq7zMnZnZuimZNwEO75EG87pr1ESqtWVmfApWyHLuLrecTnWswQDRjH(ubeHqdBjErOqHqBdSuGp4LlH2gy7mGutc7mGuec7NUkG28OqOTbwYKHRAOjHKLA3Iqy)0vbeo3XbD0HUDRqHWRenW3DaA78Mc9W6tuICzGWNmrfwzy(4t0AHn8)Ab(wekesMsfMeVunj8UHUUAi02bMFMWNr4OsXThU8DOqMVVHLsgpFqUeE5Rgag(Au12mH8(mHjThySWCdDD1qOTdgESqQ1GW)Rf4BTDk8P8bFdAsyhvYr3ZtpneMV73eU)wfApSieAPH)xlWlcHDguk7QbOnpJ5zyNkeg(FTaVie2zqPSRgG28mMNHDkmYLbc7Og2wOTbwpyuF6txYLqsBhjd2ixgiSJAyBH2gynQbPjG5wlf0KqBdSpLp4Bqtcb(aneMFkvys8spCZ9PLh6(WLhmdkL8k02aRL(HMeAPaFGgcR2ij02aBNbLYUAaAsiPTJKbRPNbegVbWOqOj4xMcTnBSWsQYicH2gyjl1U1KqFQaIqOHTeViuOqOTbwkWh8YLqBdSDgqQjHDgqkcH9txfqBEui02alzYWvn0KqYsTBriSF6QacN74Go6q3UvOqOhwFIsKlde(KjQW7g66QHqBhWZmHKPuHjXlvtcRmmF8jATWg(FTaFlcfcz((gwkz88b5siVptysBZglm3qxxneA7GHNj8P8bFdAsi1Aq4)1c8T2of(mcV3YSadGgc7Oso6EE6PHW8D)MW93Qq7BkcHwA4)1c8IqyNbLYUAaAZZyEg2PcHH)xlWlcHK2osgSMEgqy8gaJqBdSEWO(0NUKlHK2osgSrUmqyh1W2cTuGpqdHvBKeABG1OgKMaMBTuqtcTnW(u(GVb5siWhOHW8tPctIx6HBUpT8q3hU8GzqPKxH2gyT0p0KWixgiSJAyBH2gy7mOu2vdqtc7mOu2vdqBEgZZWovimZNwEO75EG87pr1ESqtWVmfAB2yHLuLrecTnWswQDRjH(ubeHqdBjErOqHqBdSuGp4LlH2gy7mGutc7mGuec7NUkG28OqOTbwYKHRAOjHKLA3Iqy)0vbeo3XbD0HUDRqHWRenW3DaA7CaHEy9jkrUmq4tMOcFgH3BzwGbqJ8DOWoQKJUNNEAimF3VjC)TcRmmF8jATWg(FTaFlcfcVBORRgcTDapZeY7ZeM02SXcz((gwkz88b5s4t5d(g0KqQ1GW)Rf4BTDkm3qxxneA7GHNjKmLkmjEPAsH2UrecT0W)Rf4fHWodkLD1a02mNUXSzkeg(FTaViesA7izWA6zaHXBamcTnW6bJ6tF6sUeg5YaHDudBl0sb(anewTrsOTbwJAqAcyU1sbnj02a7t5d(g0KqGpqdH5NsfMeV0d3CFA5HUpC5bZGsjVcTnWAPFOjHK2osgSrUmqyh1W2cTnW2zqPSRgGMe2zqPSRgG2M50nMntHWmFA5HUN7bYV)ev7Xcnb)YuOTzJfwsvgri02alzP2TMe6tfqecnSL4fHcfcTnWsb(GxUeABGTZasnjSZasriSF6QaAZJcH2gyjtgUQHMeswQDlcH9txfq4Chh0rh62Tcfc9W6tuICzGWNmrfwzy(4t0AHn8)Ab(weke2rLC0980tdH57(nH7Vv4Zi0r(aDb(rG(WHMEOWi8UHUUAi025yH8(mHjTnBSqMVVHLsgpFqUesTge(FTaFRTtHpLp4BqtcZn01vdH2oy4zcjtPctIxQMuOTZXIqOLg(FTaVie2zqPSRgG2M50nMntHWW)Rf4fHqsBhjdwtpdimEdGryKlde2rnSTWodkLD1a02mNUXSzcjTDKmyJCzGWoQHTfABG1OgKMaMBTuqtcTnW(u(GVb5siWhOHW8tPctIx6HBUpT8q3hU8GzqPKxH2gyT0p0KqBdSEWO(0NUKlH2gy7mOu2vdqtcTuGpqdHvBKuimZNwEO75EG87pr1ESqtWVmfAB2yHLuLrecTnWswQDRjH(ubeHqdBjErOqHqBdSuGp4LlH2gy7mGutcTnWsMmCvdnjSZasriSF6QaAZJcHKLA3Iqy)0vbeo3XbD0HUDRqHWRenW3DaA7CaHEy9jkrUmq4tMOcRmmF8jATWg(FTaFlcfcjtPctIxQMe(mcDKpqxGFeOpCOPhkmhU8DOW7g66QHqBNJfY7ZeM02SXcz((gwkz88b5s4t5d(g0KqQ1GW)Rf4BTDkm3qxxneA7GHNjSJk5O75PNgcZ39Bc3FRcTD6uecVBORRgcTV5yH5g66QHqBhm8mHH)xlWlcHrUmqyh1W2cjTDKmyn9mGW4nagHK2osgSrUmqyh1W2cTuGpqdHvBKeABG9P8bFdYLqGpqdHosgFIE4C3D1vbeABG1s)qtcTnW6bJ6tF6sUeABGTZGszxnanjSZGszxnaT5zaEgEMcHMGFzk02SXclPkJieABGLSu7wtc9PcicHg2s8IqHcH2gyPaFWlxcTnW2zaPMe2zaPie2pDvaT5rHqBdSKjdx1qtcjl1UfHW(PRciCUJd6OdD7wHcHEy9jkrUmq4tMOcz((gwkz88b5sizkvys8sLlHpJWrvnma)HlDD4gX(AysiVptysBZgl0sd)VwGxec7mOu2vdqBEgGNHNPqi1Aq4)1c8T2ofwzy(4t0AHn8)Ab(wekuOTtEeHqln8)AbEriSZGszxnaT5zaEgEMcHH)xlWlcH2gy9Gr9PpDjxc7mOu2vdqBEgGNHNjK02rYGnYLbc7Og2wyKlde2rnSTqBdSpLp4BqUec8bAim)uQWK4LE4M7tlp09Hlpyguk5vOTbwl9dnj0sb(anewTrsOTb2odkLD1a0KqsBhjdwtpdimEdGrHWmFA5HUN7bYV)ev7Xcnb)YuOTzJfwsvgri02alzP2TMe6tfqecnSL4fHcfcTnWsb(GxUeABGTZasnj02alzYWvn0KWodifHW(PRcOnpkeswQDlcH9txfq4Chh0rh62TcfcVs0aF3bOTZbe6H1NOe5YaHpzIkSJk5O75PNgcZ39Bc3FRWCdDD1qOTdgEMWNr4OQggG)WLUoCJyFnmD4Y3Hcz((gwkz88b5siVptysBZglKAni8)Ab(wBNcFkFW3GMewzy(4t0AHn8)Ab(wekeE3qxxneAFZXcjtPctIxQMuOTtZeHqMVVHLsgpFqUeMBORRgcTDWWZeg(FTaVie2zqPSRgG2oD6MXdZJqBdSEWO(0NUKlHrUmqyh1W2cjTDKmyJCzGWoQHTfABG1OgKMaMBTuqtcTnW(u(GVbnje4d0qy(PuHjXl9Wn3NwEO7dxEWmOuYRqBdSw6hAsOLc8bAiSAJKqBdSDguk7QbOjHK2osgSMEgqy8gaJcHMGFzk02SXclPkJieABGLSu7wtc9PcicHg2s8IqHcH2gyPaFWlxcTnW2zaPMeABGLmz4QgAsyNbKIqy)0vb0Mhfcjl1UfHW(PRciCUJd6OdD7wHcHEy9jkrUmq4tMOcVBORRgcThyMqYuQWK4LkxcRmmF8jATWg(FTaFlcfc59zctAB2yHwA4)1c8IqyNbLYUAaA70PBgpmpkesTge(FTaFRTtHpJWrLk5oCJyFnmPqBNdicH5g66QHqBhm8mHH)xlWlcHK2osgSMEgqy8gaJqBdSEWO(0NUKlHK2osgSrUmqyh1W2cTuGpqdHvBKeABG1OgKMaMBTuqtcTnW(u(GVb5siWhOHW8tPctIx6HBUpT8q3hU8GzqPKxH2gyT0p0KWixgiSJAyBH2gy7mOu2vdqtc7mOu2vdqBNoDZ4H5rHWmFA5HUN7bYV)ev7Xcnb)YuOTzJfwsvgri02alzP2TMe6tfqecnSL4fHcfcTnWsb(GxUeABGTZasnjSZasriSF6QaAZJcH2gyjtgUQHMeswQDlcH9txfq4Chh0rh62TcfcVs0aF3bOTZbe6H1NOe5YaHpzIk8UHUUAi0EGzc7Oso6EE6PHW8D)MW93k0sd)VwGxec7mOu2vdqBNoDZ4H5rHWNr4OsLChUrSVgMoC57qH8(mHjTnBSqQ1GW)Rf4BTDk8P8bFdAsiZ33WsjJNpixcRmmF8jATWg(FTaFlcfcjtPctIxQMuOTZzIq4DdDD1qOTtNZeMBORRgcTDWWZeg(FTaViesA7izWA6zaHXBamcJCzGWoQHTfABG1dg1N(0LCj0sb(anewTrsOTbwJAqAcyU1sbnj02a7t5d(g0KqGpqdH5NsfMeV0d3CFA5HUpC5bZGsjVcTnWAPFOjHK2osgSrUmqyh1W2cTnW2zqPSRgGMe2zqPSRgG28y(zdBMcHMGFzk02SXclPkJieABGLSu7wtc9PcicHg2s8IqHcH2gyPaFWlxcTnW2zaPMe2zaPie2pDvaT5rHqBdSKjdx1qtcjl1UfHW(PRciCUJd6OdD7wHcHEy9jkrUmq4tMOcz((gwkz88b5syLH5JprRf2W)Rf4BrOTtrim8)AbErimYLbcjTDKmesA7izi8YsjJprZtEp3F4oChUd35(d3H7WD4kjYA5WDLSuMdN5E4UQLgo3F4oChUd35(d3H7WD4Us(d3BUohHhUT72DXoYdAopFuS4GdrGhoM05(d3H7WD4oChUd3H7VoCD4F6YDE9uM8mYqmYLCzMg8PJopFEhHJO8t0gi914t0ruEpChZjM7HJ(LdxycON7pChUd3H7WD4oChUd3H7WD4UswkZHZCpCH3chUZ9hUd3H7WD4oChUdhqzo3F4oChUdhqzoCN7pChUd3HZdH1tpC0uC4UswkZ5EGYiSTUa(anq711FNq28DejyrchVLqiPjGC0cTzm1aesA7izWg5YaHDudBle4d0q4OGAjmjSTUa(anM7HR)oH4C3p4GkeAPH)xlWlcfkuiK3NjmPTzJfAPH)xlWlcHDguk7QbOnpMF2WMPqi1Aq4)1c8T28i8zeMFI2aPVgFIkKmLkmjEPYLcTDAEri0sd)VwGxec7mOu2vdqBEm)SHntHWW)Rf4fHWodkLD1a0MhZpByZeg5YaHDudBl0sb(anewTrsiPTJKbBKlde2rnSTqBdSg1G0eWCRLcAsOTb2NYh8nixcb(aneMFkvys8spCZ9PLh6(WLhmdkL8k02aRL(HMeABG1dg1N(0LCj02aBNbLYUAaAsiPTJKbRPNbegVbWOqyMpT8q3Z9a53FIQ9yHMGFzk02SXclPkJieABGLSu7wtc9PcicHg2s8IqHcH2gyPaFWlxcTnW2zaPMeABGLmz4QgAsyNbKIqy)0vb0Mhfcjl1UfHW(PRciCUJd6OdD7wHcHxjAGV7a025ac9W6tuICzGWNmrfY89nSuY45dAsyhvYr3ZtpneMV73eU)wH5g66QHqBhm8mHpJW8t0gi914t0dx(ouiVptysBZglKAni8)Ab(wBEe(u(GVbnj8UHUUAi02PZzcRmmF8jATWg(FTaFlcTDkcHH)xlWlcHrUmqiPTJKHqsBhjdHxwkz8jAEY75(d3H7WD4o3F4oChUdxjrwlhURKLYC4m3d3vT0W5(d3H7WD4o3F4oChUd3vYF4EZ15i8WTD3Ul2rEqZ55JIfhCic8WXKo3F4oChUd3H7WD4oC)1HRd)txUZRNYKNrgIrUKlZ0GpD055Z7iCeLFI2aPVgFIoIY7H7yoXCpC0VC4cta9C)H7WD4oChUd3H7WD4oChUd3vYszoCM7Hl8w4WDU)WD4oChUd3H7WD4akZ5(d3H7WD4akZH7C)H7WD4oCEiSE6HJMId3vYszo3dugHT1fWhObAVU(7eYMVJibls44TecjnbKJwOnJPgGqsBhjd2ixgiSJAyBHaFGgchfulHjHT1fWhOXCpC93jeN7(bhuHqln8)AbErOqHcHKPuHjXlvtk025WIq4DdDD1qOTtNZeAPH)xlWlcHDguk7QbOTtNMFaZpScHH)xlWlcHDgukULrOtNMFaZpSqBdSg1G0eWCRLcAsyIx6q0sonjKwnGweA7uy(jAdK(A8jQcHK2osgSMEgqy8gaJqBdSEWO(0NUKlH2gyT0p0KWodkLD1a02PtZpG5hwiWhOHW8tPctIx6HBUpT8q3hU8GzqPKxHrUmqyh1W2cTnW2zqP4wgnj02aBNbLYUAaAsiPTJKbBKlde2rnSTqBdSpLp4BqtcTuGpqdHvBKeEzlLMSs1KcHMGFzk02SXclPkJieABGLSu7wtc9PcicHg2s8IqHcH2gyPaFWlxcTnW2zaPMeABGLmz4QgAsyNbKIqy)0vb0Mhfcjl1UfHW(PRciCUJd6OdD7wHcHEy9jkrUmq4tMOcFgH5NOnq6RXNOhUrUKlZeWiKmLkmjEPYLWkdZhFIwlSH)xlW3IqBNIqy4)1c8IqyKldesA7iziK02rYq4LLsgFIMN8EU)WD4oChUZ9hUd3H7WvsK1YH7kzPmhoZ9WDvlnCU)WD4oChUZ9hUd3H7WDL8hU3CDocpCB3T7IDKh0CE(OyXbhIapCmPZ9hUd3H7WD4oChUd3FD46W)0L786Pm5zKHyKl5Ymn4thDE(8ochr5NOnq6RXNOJO8E4oMtm3dh9lhUWeqp3F4oChUd3H7WD4oChUd3H7WDLSuMdN5E4cVfoCN7pChUd3H7WD4oChoGYCU)WD4oChoGYC4o3F4oChUdNhcRNE4UswkZ5EGYiSTUa(anq711FNq28DejyrchVLqiPjGC0cTzm1aesA7izWg5YaHDudBle4d0q4OGAjmjSTUa(anM7HR)oH4C3p4GkeAPH)xlWlcfkuiK3NjmPTzJfY89nSuY45dYLWCdDD1qOTdgEMqQ1GW)Rf4BT5rH2oVPieMBORRgcTDWWZeg(FTaVie2zqP4wgHoDA(bm)WcTnWAudstaZTwkOjH2gyFkFW3GCjK02rYG10ZacJ3ayeg5YaHDudBlSZGszxnaTD608dy(HfsA7izWg5YaHDudBlKwnGweA7uy(jAdK(A8jQcHaFGgcZpLkmjEPhU5(0YdDF4YdMbLsEfABG1s)qtcTuGpqdHvBKeABGTZGsXTmAs4t5d(g0KqBdSEWO(0NUKlHjEPdrl50KqBdSDguk7QbOjHx2sPjRunPqyMpT8q3Z9a53FIQ9yHMGFzk02SXclPkJieABGLSu7wtc9PcicHg2s8IqHcH2gyPaFWlxcTnW2zaPMe2zaPie2pDvaT5rHqBdSKjdx1qtcjl1UfHW(PRciCUJd6OdD7wHcHxjAGV7a025ac9W6tuICzGWNmrf2rLC0980tdH57(nH7VvyLH5JprRf2W)Rf4BrOTtrim8)AbErimYLbcjTDKmeAPaFGgcR2ije4d0qy(jkZhFI2cBRlGpqJ5E46Vtio39doOqsBhjdHxwkz8jAEY75(d3H7WD4o3F4oChUdxjrwlhURKLYC4m3d3vT0W5(d3H7WD4o3F4oChUd3vYF4EZ15i8WTD3Ul2rEqZ55JIfhCic8WXKo3F4oChUd3H7WD4oC)1HRd)txUZRNYKNrgIrUKlZ0GpD055Z7iCeLFI2aPVgFIoIY7H7yoXCpC0VC4cta9C)H7WD4oChUd3H7WD4oChUd3vYszoCM7Hl8w4WDU)WD4oChUd3H7WD4akZ5(d3H7WD4akZH7C)H7WD4oCEiSE6H7kzPmN7bkJqsBhjd2ixgiSJAyBHKMaYrl0MXudqOTbwl9dnjSTUa(anq711FNq28DejyrchVLqOL(HWSsnh4vi0sd)VwGxekuOq4DdDD1qOTtNZeY7ZeM02SXcFkFW3GMesTge(FTaFRnpcT0W)Rf4fHWodkLD1a02PtZpG5hwHqMVVHLsgpFqUe(mcZprBG0xJprpCJCjxMjG5WLVdfsMsfMeVunPqBNUrecVBORRgcTDoBSqln8)AbEriSZGszxnaT5zSB4zMcHH)xlWlcHrUmqyh1W2cTuGpqdHvBKeABG1OgKMaMBTuqtcTnW(u(GVbnje4d0qy(PuHjXl9Wn3NwEO7dxEWmOuYRqBdSw6hAsOTb2odkLD1a0KWodkLD1a0MNXUHNzcjTDKmyJCzGWoQHTfABG1dg1N(0LCjK02rYG10ZacJ3ayui0e8ltH2MnwyjvzeHqBdSKLA3AsOpvari0WwIxekui02alf4dE5sOTb2odi1KqBdSKjdx1qtc7mGuec7NUkG28OqizP2Tie2pDvaHZDCqhDOB3kui0dRprjYLbcFYev4ZieRKEG5WHMEOWC4mhFPaEHKPuHjXlvUewzy(4t0AHn8)Ab(wekeE5Rgag(Au12mH8(mHjTnBSqMVVHLsgpFqUeMBORRgcTDWWZesTge(FTaFRTtfAZZyri8UHUUAi025SXcZn01vdH2oy4zcd)VwGxecjTDKmyn9mGW4nagHrUmqyh1W2cTnW6bJ6tF6sUeAPaFGgcR2ij02aRrninbm3APGMeABG9P8bFdYLqGpqdH5NsfMeV0d3CFA5HUpC5bZGsjVcjTDKmyJCzGWoQHTfABGTZGszxnanjSZGszxnaT5zSB4zMqBdSw6hAsHqtWVmfAB2yHLuLrecTnWswQDRjH(ubeHqdBjErOqHqBdSuGp4LlH2gy7mGutc7mGuec7NUkG28OqOTbwYKHRAOjHKLA3Iqy)0vbeo3XbD0HUDRqHqpS(eLixgi8jtuHpJqSs6bMdhA6HcZHZC8Lc4pC57qHx(QbGHVgvTntiVptysBZgl0sd)VwGxec7mOu2vdqBEg7gEMPqi1Aq4)1c8T2of(u(GVbnjK57ByPKXZhKlHvgMp(eTwyd)VwGVfHcHKPuHjXlvtk0MhNIq4DdDD1qOTZBotyUHUUAi02bdpty4)1c8IqiPTJKbRPNbegVbWimYLbc7Og2wOTbwpyuF6txYLqlf4d0qy1gjH2gynQbPjG5wlf0KqBdSpLp4Bqtcb(aneMFkvys8spCZ9PLh6(WLhmdkL8kK02rYGnYLbc7Og2wOTb2odkLD1a0KWodkLD1a02PZbCoByH2gyT0p0KcHMGFzk02SXclPkJieABGLc8bVCjmQfGgA78Mcjl1UfHW(PRciCUJd6OdD7wHqBdSrTa0qtcTnWswQDRjH(ubeHqdBjErOqHqBdSDgqQjH2gyjtgUQHMe2zaPie2pDvaT5rHcHEy9jkrUmq4tMOcFgHU)oG0gFIE4qGgaLeeE5Rgag(Au1EaH8(mHjTnBSqln8)AbEriSZGszxnaTD6CaNZgwHqQ1GW)Rf4BTDkK57ByPKXZhKlHvgMp(eTwyd)VwGVfHcHKPuHjXlvUuOnp8icHwA4)1c8IqyNbLYUAaA705aoNnScHH)xlWlcHrUmqyh1W2cTnWAPFOjHwkWhOHWQnscTnWAudstaZTwkOjH2gyFkFW3GCje4d0qy(PuHjXl9Wn3NwEO7dxEWmOuYRqBdSDguk7QbOjHDguk7QbOTtNd4C2WcjTDKmyJCzGWoQHTfABG1dg1N(0LCjK02rYG10ZacJ3ayui0e8ltH2MnwyjvzeHqBdSuGp4LlHrTa0qBN3uizP2Tie2pDvaHZDCqhDOB3keABGnQfGgAsOTbwYsTBnj0NkGieAylXlcfkeABGTZasnj02alzYWvn0KWodifHW(PRcOnpkui0dRprjYLbcFYevizkvys8s1KWkdZhFIwlSH)xlW3IqHW7g66QHqBN3CMWNrO7VdiTXNOhoeObqjHdx(ouiZ33WsjJNpixcV8vdadFnQApGqEFMWK2Mnw4t5d(g0KWCdDD1qOTdgEMqQ1GW)Rf4BTDQqBEmtecVBORRgcTDEZzcT0W)Rf4fHWodkLD1a02PZbCo7Mkeg(FTaVieg5YaHDudBl02aRL(HMeAPaFGgcR2ij02aRrninbm3APGMeABG9P8bFdAsiWhOHW8tPctIx6HBUpT8q3hU8GzqPKxH2gy7mOu2vdqtc7mOu2vdqBNohW5SBkK02rYGnYLbc7Og2wOTbwpyuF6txYLqsBhjdwtpdimEdGrHqtWVmfAB2yHLuLrecTnWsb(GxUeg1cqdTDoSqYsTBriSF6QacN74Go6q3Uvi02aBulan0KqBdSKLA3AsOpvari0WwIxekui02aBNbKAsOTbwYKHRAOjHDgqkcH9txfqBEuOqOhwFIsKlde(KjQqYuQWK4Lkxcz((gwkz88b5s4ZiCWFzkgb6d3OQggGx4LVAay4Rrv7beY7ZeM02SXcRmmF8jATWg(FTaFlcfcZn01vdH2oy4zcPwdc)VwGV12PcT5zarim3qxxneA7GHNjm8)AbEriK02rYG10ZacJ3ayeg5YaHDudBl02aRhmQp9Pl5sOLc8bAiSAJKqBdSg1G0eWCRLcAsOTb2NYh8nixcb(aneMFkvys8spCZ9PLh6(WLhmdkL8k02aRL(HMesA7izWg5YaHDudBl02aBNbLYUAaAsyNbLYUAaA705aoNDtfcnb)YuOTzJfwsvgri02alf4dE5syulan025Wcjl1UfHW(PRciCUJd6OdD7wHqBdSrTa0qtcTnWswQDRjH(ubeHqdBjErOqHqBdSDgqQjH2gyjtgUQHMe2zaPie2pDvaT5rHcHEy9jkrUmq4tMOcVBORRgcTDEZzcFgHd(ltXiqF4gv1Wa8hU8DOWlF1aWWxJQ2diK3NjmPTzJf(u(GVbnj0sd)VwGxec7mOu2vdqBNohW5SBQqi1Aq4)1c8T2ofY89nSuY45dYLWkdZhFIwlSH)xlW3IqHqYuQWK4LQjfAZZmri8UHUUAi025nNjm3qxxneA7GHNjm8)AbEriK02rYG10ZacJ3ayeg5YaHDudBl02aRhmQp9Pl5sOLc8bAiSAJKqBdSg1G0eWCRLcAsOTb2NYh8nOjHaFGgcZpLkmjEPhU5(0YdDF4YdMbLsEfABG1s)qtcjTDKmyJCzGWoQHTfABGTZGszxnanjSZGszxnaTD6CaNMFMcHMGFzk02SXclPkJieABGLc8bVCjmQfGgA708cjl1UfHW(PRciCUJd6OdD7wHqBdSrTa0qtcTnWswQDRjH(ubeHqdBjErOqHqBdSDgqQjH2gyjtgUQHMe2zaPie2pDvaT5rHcHEy9jkrUmq4tMOcz((gwkz88b5syLH5JprRf2W)Rf4BrOq4LVAay4Rrv7beY7ZeM02SXcT0W)Rf4fHWodkLD1a02PZbCA(zkesTge(FTaFRTtHpJWrLk5oCZ9FBiKmLkmjEPYLcT5X8Iq4DdDD1qOTZBotOLg(FTaVie2zqPSRgG2oDoGtZptHWW)Rf4fHWixgiSJAyBHwkWhOHWQnscTnWAudstaZTwkOjH2gyFkFW3GCje4d0qy(PuHjXl9Wn3NwEO7dxEWmOuYRqBdSw6hAsOTb2odkLD1a0KWodkLD1a02PZbCA(zcjTDKmyJCzGWoQHTfABG1dg1N(0LCjK02rYG10ZacJ3ayui0e8ltH2MnwyjvzeHqBdSuGp4LlHrTa0qBNMxizP2Tie2pDvaHZDCqhDOB3keABGnQfGgAsOTbwYsTBnj0NkGieAylXlcfkeABGTZasnj02alzYWvn0KWodifHW(PRcOnpkui0dRprjYLbcFYevizkvys8s1KWNr4OsLChU5(VnoC57qHmFFdlLmE(GCjSYW8XNO1cB4)1c8Tiui8Yxnam81OQ9ac59zctAB2yHuRbH)xlW3A7uyUHUUAi02bdpt4t5d(g0Kcfc5RTZbgpwHe

Cooldown Row:

dWeNZaGivvPUKkqAukIoLIKvPcfVsfknlkOULIu7srOFrbPggvXXuvwgvPNPI00urCnkvBJcPVPcyCIQ6CcH7jef7JcsYbPalur9qvituf0ffvPnQQk(OquAKQQsojfQvQcvVufiAMkcUjfe2Ps(jLIHQQYsvvvpfzQQYvPGOTQce(QkqnwHO6SIQO5kQc7L8xkAWIYHfzXQOESknzOCzWMHkFwPgnu1PHSAkiPETqKzJQBtvTBu(TGHluhNcsy5u55snDjxxHTlK(oLsJNcX5fvwpfKO9tjRp9eL0tLOw03epzIhyI5lYxeMim9e5GnkWE5IbrBxyelcmsCIHby6SOg44(fqSs0SnVNngIjK3)8eLWWqfkWsCZYH2BW16Psect0dpCJ00)CHA6JcbowWwwlIn8Fo0EdUwRpr8qctprUah0tK)Gxi9uPsLkrx906tprgXgC4AO0FMo)to5KV8TFGio9ZJNtT)jCtFYbevo0Edo9efSLzdJNtZIyjFO1tRpr)J24limARS)mC5ujcXIcUg0SO7ORGVjEegiQq(aMkr4b0gFPLDpI4HeMEIgnyE5PU1SixGd6jYFWlKEQujA0GjdIcoDw0ObZogUAw0LN6wprnIT5GOFgmbdo04LkrDmC1tuJyBoOLxvQe5GnkWE5IbrOBGjkNn4W1qP13jEfHWe9pAJVGWOTY(ZWLZkZyw6wOOGOeggQqbwIBwo0EdUwpvISfHv41YUhr3ap40tRt0FS717jFhWUrZ3E(g970dyuHBA7NQseB4)CO9gCTwFIWqDmpLZ4BGjYywboCPlKhgFdSopOyGZn)RapNjbjUn4(ZWLtLwE1t0Gvo0Edo9e1XaNVs(GwE9eHx7Qevo0Edo9e1XaNBmMOVp7hiFrJgm9t1fpG9)GbAw0Obtelk4AqNfnAWCWqLMf1XaNVs(GwE9eHx7IgmikWkrPrfebrbwj6OqGJfSLzL9Zf2oOBRSjPyGZNs0D0vW3epcdeviFat0GHkrvYTHs0ObZog48vYh0Sielk4AqZIyjFO1tRprhmKIeWamRSzEW2wLOrdMDmW5gJPzryW5boCVCXGO)YG)ne)XqobvIIDHTd6(NdUOgfyA5reEaTXxA51UiEiHPNOrdMxEQBnlYf4GEI8h8cPNkvIgnyYGOGtNfnAWSJHRMf1XWvprnIT5GwEvjA0G5n4FovAw0LN6wprnIT5GOFgmbdo04LkvIWqDmpLJQ0nsTOd6vKd2Oa7LlgeHUbMOBiWXc2Y0SiJydoCnuAnD(2fHWeDWqksadWSYM5bBBRmdIJ55eLWWqfkWsCZYH2BW16PsKTiScVwETlkXq(Pcfy6jYpHy6jQVjo8Nb7kYb1WXSYWny3cfytg7cBh0THTY6k5Qi3WwzDLCvEAyRS(M4qKByRS(M4qEoL1XTYSYSYSY4HBIBLLyBoyLfzSYMm2f2oOBRSJXkZRv2XyL5Nk8tmgnLv20wzt6Nk8tmgzLzOTY8oL1XTYSYSYSYCqnCmRSUsUkYTYowRSjNCs)uHFInInzIT5WuwzhRv23ugAVtzLDmwzt23ehICRSPTY(MAkdBL1vYv5Pv2XALn5Kt6Nk8tSrSjtSnhMYk7yTY(MYq7DkRSJXkBY(M4qEALnTv23utzDCGHzDCrJgm7BId6SOBGhCZA9j6g4bxKvRprJgmlxI18ubAwuFtC4Llgefp4nik2bnuIohgSliQCjwZtf8Nb7kYb1WXSYWny3cfytg7cBh0THTY6k5Qi3WwzDLCvEAyRmmGxPi3WwzyaVs55uwh3kZkJhUjUv25WGDHdrDLyxWklYyL5Nk8tSrSjJDHTd62k7ySY8tf(jgJMY64wzwzoOgoMvwxjxf5wzhRv2KXUW2bDBLDmwzyaVsr(ug2kRRKRYtRSJ1kBYZHb7chI6kXUGv2XyLHb8kLNtzDCGHzDCr9nXHCA9nr7Is8y8jT8i6g4bNbA9jkNwtFQhrgrlpIWgUuHcmrEMOrf13ehmIwFt0UOkxmi6o6k4lYfQubA5ru5sSMNk4LlgeDomyxq0nWdU)16tLkrSH)ZH2BW1A9jcXIcUg0SOC2GdxdLwt)5XUimuhZt5m(gyImMvGdx6c5HX3aRZddoJ4OkN5bNCouWzEWj3rUCI6kDJu)lGyLOJY76L3)vP1P6jYi2GdxdLwtNVDr5SbhUgkTM(ZJDrLdT3Gtpr3rxbFt8imquH8bmrDmW5gJjYRNi8Ax0GbrbwjknQGOrdM(P6IhW(FWanlA0GjIffCnOZIGOaReDuiWXc2YSY(5cBh0Tv2KumW5tjA0G5GHknlA0GzhdCUXyAw0ObZog48vYh0SObdvIQKBdLiwYhA906t0bdPibmaZkBMhSTvjcdopWH7Llge9xg8VH4pgYjiQJboFL8bT86jcV2vjk2f2oO7Fo4IAuGPLhr4b0gFPLx7I4HeMEIgnyE5PU1SixGd6jYFWlKEQujA0GjdIcoDw0ObZogUAw0ObZBW)CQ0SOogU6jQrSnh0YRkrxEQB9e1i2MdI(zWem4qJxQujYbBuG9YfdIq3atuxPBK6FbeReDuExV8(VO0Oc6SObRCO9gC6jQJboFL8bT86jcV2vjkHHHkuGL4MLdT3GR1tLiBryfET8Axect0bdPibmaZkBMhSTfXg(phAVbxR1NimuhZt5m(gyImMvGdx6c5HX3aRZddoJ4OkN5bNCouWzEWj3rUCIUHahlyltZQ06e9enyLdT3GtprDmW5RKpOLxpr41UkrLdT3GtprDmW5RKpOLxpr41UOog4CJXe51teETlAWGOaReLgvq0Obt)uDXdy)pyGMfnAWeXIcUg0zrquGvIoke4ybBzwz)CHTd62kBskg48PenAWCWqLMfnAWSJbo3ymnlIL8HwpT(enN6cfywzbCwzrwEWLtLOrdMDmW5RKpOzr3rxbFt8imquH8bmvIIDHTd6(NdUOgfyA5reEaTXxA51UiEiHPNOrdMxEQBnlYf4GEI8h8cPNkvIgnyYGOGtNfnAWSJHRMf1XWvprnIT5GwEvjA0G5n4FovAw0LN6wprnIT5GOFgmbdo04LkvIWfyfHmucA9DIihSrb2lxmicDdmr3qGJfSLPzrgXgC4AO0A6Vp7I6kDJuFuGvjeZhyLiBmKpY4dZRieMO5uxOaZklGZklYYdUCIsyyOcfyjUz5q7n4A9ujYwewHxlV2fXg(phAVbxR1NOC2GdxdLwt)5XUimuhZt5m(gyImMvGdx6c5HX3aRZddoJ4OkN5VepHHyM)vY3hCbCfE4F0gFbHrlQR0ns9VaIvIMT59SXqOsl76jkNn4W1qP10FESlQCO9gC6jQJbo3ymrE9eHx7Igny6NQlEa7)bd0SOGTmBy8CAwuhdC(k5dA51teETl6o6k4BIhHbIkKpGjcIcSs0rHahlylZk7NlSDq3wztsXaNpLOrdMDmW5gJPzrJgm7yGZxjFqZIqSOGRbnlAWGOaReLgvq0Obtelk4AqZIgnyoyOsZIyjFO1tRpru66amRmcpc4yQeHBW59nX0Skr4b0gFPLx7I4HeMEIgnyYGOGtNfvjoWkTIquhdx9e1i2MdA5vLOrdMvIdSsZIgnyE5PU1SixGd6jYFWlKEQujA0GzhdxnlA0G5n4FovAw0LN6wprnIT5GOFgmbdo04LkvICWgfyVCXGi0nWezeBWHRHsRPTBxegQnupy3cff0zrimru66amRmcpc4yIsmKFQqbMEI8tiMEIUbEW9VwFIUbEWzGwFIUbEWfz16t0ObZYLynpvGMfv5Ibr3rxbFrLlXAEQG)myxroOgoMvgUb7wOaBYyxy7GUnSvwxjxf5g2kRRKRYtdBLHb8kf5g2kdd4vkpNY64wzwz8WnXTYohgSlCiQRe7cwzrgRm)uHFInInzSlSDq3wzhJvMFQWpXy0uwh3kZkZb1WXSY6k5Qi3k7yTYMm2f2oOBRSJXkdd4vkYNYWwzDLCvEALDSwztEomyx4quxj2fSYogRmmGxP8CkRJdmmRJlQVjoKtRprjEm(KwEeLtRP96rKr0YJO(M4Gr06te2WLkuGjYZenQOyh0qj6CyWUGixOsfOLhrLlXAEQGxUyq05WGDbr3ap4M16tLkr2IWk8A51UObRCO9gC6jQJboFL8bT86jcV2vjIn8Fo0EdUwRprjmmuHcSe3SCO9gCTEQeHH6yEkNX3atKXScC4sxipm(gyDEyWzehv5m)L4jmeZCMdDdygcGHHyBvAzu9eLZgC4AO0A6pp2fvo0Edo9e1XaNBmMiVEIWRDrJgm9t1fpG9)GbAwuWwMnmEonlQJboFL8bT86jcV2fnyquGvIsJkicIcSs0rHahlylZk7NlSDq3wztsXaNpLO7ORGVjEegiQq(aMOrdMDmW5gJPzrJgmrSOGRbDwel5dTEA9jIsxhGzLr4rahtLOrdMDmW5RKpOzrJgmhmuPzr4gCEFtmnRsuSlSDq3)CWf1OatlpIWdOn(slV2fXdjm9enAW8YtDRzrUah0tK)Gxi9uPs0ObtgefC6SOrdMDmC1SOlp1TEIAeBZbr)mycgCOXlvIgnyEd(NtLMf1XWvprnIT5GwEvPsegQJ5PCuLUrQfDqJf5GnkWE5IbrOBGj6gcCSGTmnlkHHHkuGL4MLdT3GR1tLiJydoCnuAnTD7ISfHv41YRDrimru66amRmcpc4ywzhoCIyd)NdT3GR16t0Gvo0Edo9e1XaNVs(GwE9eHx7Qe1v6gP(xaXkrhL31lV)RsRdONiJydoCnuAnTxpIgSYH2BWPNOog48vYh060V8Z)evIkhAVbNEIQCXGOUs1OfnyquGvIsJki6o6k4BIhHbIkKpGjA0GjIffCnOzrquGvIoke4ybBzwz)CHTd62kBskg48PenAW0b(jedX26SOrdMDmW5RKpOzrDmW5RKpO1PF5N)jIyjFO1tRprgZmumqnQqbMkrJgmhmuPzvIIDHTd6(NdUOgfyA5reEaTXxA51UiEiHPNOrdMxEQBnlYf4GEI8h8cPNkvIgnyYGOGtNfnAWSJHRMfnAW8g8pNknlQJHREIAeBZbT8Qs0LN6wprnIT5GOFgmbdo04LkvICWgfyVCXGi0nWe1v6gP(OaRsiMpWkr2yiFKXhMxrjmmuHcSe3SCO9gCTEQezlcRWRLx7IYzdoCnuAn9Nh7Iyd)NdT3GR16tectKbrb2gX2wzhSlv4f1v6gP(xaXkrZ28E2yiuPv(6jAWkhAVbNEI6yGZxjFqRt)Yp)tujQCO9gC6jA0GPd8tigIT1zrdgefyLO0OcIgnyIyrbxd6SiikWkrhfcCSGTmRSFUW2bDBLnjfdC(uIgnyoyOsZIgny2XaNVs(GMfXs(qRNwFImMzOyGAuHcmvI6yGZxjFqRt)Yp)tev5IbrDLQrl6o6k4BIhHbIkKpGPsuSlSDq3)CWf1OatlpIWdOn(slV2fXdjm9enAW8YtDRzrUah0tK)Gxi9uPs0ObtgefC6SOrdMDmC1SOogU6jQrSnh0YRkrJgmVb)ZPsZIU8u36jQrSnhe9ZGjyWHgVuPsKd2Oa7LlgeHUbMOBiWXc2Y0SOeggQqbwIBwo0EdUwpvImIn4W1qP10E9iYwewHxlV2fHWezquGTrSTv2b7sfERSJouuoBWHRHsRP)8yxeIffCnOzrSH)ZH2BW1A9jQR0ns9VaIvIokVRxE)xLwrONObRCO9gC6jQJboFL8bTojI8vjQCO9gC6jQYfdI6kvJw0GbrbwjknQGOrdM(P6IhW(FWanlA0GjIffCnOzrquGvIoke4ybBzwz)CHTd62kBskg48PenAWCWqLMf1XaNVs(GwNer(Igny2XaNVs(GMfDhDf8nXJWarfYhWujk2f2oO7Fo4IAuGPLhr4b0gFPLx7I4HeMEIgnyE5PU1SixGd6jYFWlKEQujA0GjdIcoDw0ObZogUAwuhdx9e1i2MdA5vLOrdM3G)5uPzrxEQB9e1i2MdI(zWem4qJxQujYbBuG9YfdIq3atuxPBK6JcSkHy(aRezJH8rgFyEfHWeDikkIbwz)CHcUfkWeLWWqfkWsCZYH2BW16PsKrSbhUgkT(8iYwewHxlV2fLZgC4AO0A6pp2fXg(phAVbxR1NOUs3i1)ciwjA2M3ZgdHkT(8ONObRCO9gC6jQJboFL8bTojI8vjQCO9gC6jQYfdI6kvJw0GbrbwjknQGOrdM(P6IhW(FWanlA0GjIffCnOZIGOaReDuiWXc2YSY(5cBh0Tv2KumW5tjA0G5GHknl6o6k4BIhHbIkKpGjA0GzhdC(k5dAwuhdC(k5dADse5RsuSlSDq3)CWf1OatlpIWdOn(slV2fXdjm9enAW8YtDRzrUah0tK)Gxi9uPs0ObtgefC6SOrdMDmC1SOogU6jQrSnh0YRkrJgmVb)ZPsZIU8u36jQrSnhe9ZGjyWHgVuPsKd2Oa7LlgeHUbMOeggQqbwIBwo0EdUwpvIUHahlyltZI6kDJuFuGvjeZhyLiBmKpY4dZRieMOdrrrmWk7NluWTqbMv2rhkYi2GdxdLwFEezlcRWRLx7IYzdoCnuAn9Nh7IqSOGRbnlIn8Fo0EdUwRprDLUrQ)fqSs0r5D9Y7)Q067tpr8qctprJgmV8u3AwKlWb9e5p4fspvQenAWKbrbNolA0GzhdxnlQJHREIAeBZbT8Qs0ObZBW)CQ0SOlp1TEIAeBZbr)mycgCOXlvQeLZgC4AO0A6pp2fnyLdT3GtprDmW5RKpO1PF5B3JkrLdT3GtprvUyquxPA0IgmikWkrPrfenAW0pvx8a2)dgOzrJgmrSOGRbnlcIcSs0rHahlylZk7NlSDq3wztsXaNpLOrdMdgQ0SOog48vYh060V8T7r0ObZog48vYh0SO7ORGVjEegiQq(aMkrSH)ZH2BW1A9jYwewHxlV2fHWezGddyLv2HaoGHborjmmuHcSe3SCO9gCTEQezeBWHRHsRt8icpG24lT8AxKd2Oa7LlgeHUbMkT(8QNOC2GdxdLwt)5XUOYH2BWPNOkxmiQRunArdgefyLO0OcIgny6NQlEa7)bd0SOrdMiwuW1GolcIcSs0rHahlylZk7NlSDq3wztsXaNpLOrdMdgQ0SO7ORGVjEegiQq(aMOrdMDmW5RKpOzrDmW5RKpO1PF5B3JkrXUW2bD)ZbxuJcmT8icpG24lT8AxepKW0t0ObZlp1TMf5cCqpr(dEH0tLkrJgmzquWPZIgny2XWvZI6y4QNOgX2CqlVQenAW8g8pNknl6YtDRNOgX2Cq0pdMGbhA8sLkroyJcSxUyqe6gyI6kDJu)lGyLOJY76L3)fHWezGddyLv2HaoGHboRSJouKrSbhUgkToXJiBryfET8AxucddvOalXnlhAVbxRNkriwuW1GMfnyLdT3GtprDmW5RKpO1PF5B3JkrSH)ZH2BW1A9j6gcCSGTmnRsRVt1tegQJ5PCuLUrQfDqVImIn4W1qP1b8iIhsy6jA0G5LN6wZICboONi)bVq6PsLOrdMmik40zrJgm7y4QzrDmC1tuJyBoOLxvIgnyEd(NtLMfD5PU1tuJyBoi6NbtWGdnEPsLObRCO9gC6jQJboFL8bTY3Og1EeQe5GnkWE5IbrOBGjkHHHkuGL4MLdT3GR1tLi2W)5q7n4AT(ezlcRWRLx7IkhAVbNEIQCXGOUs1OfnyquGvIsJkiA0GPFQU4bS)hmqZIgnyIyrbxdAweefyLOJcbowWwMv2pxy7GUTYMKIboFkrJgmhmuPzrDmW5RKpOv(g1O2Jq0ObZog48vYh0SO7ORGVjEegiQq(aMkrimrrwdyhKIWdOn(slV2fLZgC4AO0A6pp2vP13j6jkNn4W1qP10FESlQCO9gC6jQYfdI6kvJw0GbrbwjknQGOrdM(P6IhW(FWanlA0GjIffCnOZIGOaReDuiWXc2YSY(5cBh0Tv2KumW5tjA0G5GHknl6o6k4BIhHbIkKpGjA0GzhdC(k5dAwuhdC(k5dALVrnQ9iujk2f2oO7Fo4IAuGPLhr4b0gFPLx7I4HeMEIgnyE5PU1SixGd6jYFWlKEQujA0GjdIcoDw0ObZogUAwuhdx9e1i2MdA5vLOrdM3G)5uPzrxEQB9e1i2MdI(zWem4qJxQujYbBuG9YfdIq3atuxPBK6FbeReDuExV8(VieMOiRbSdsRSJouKrSbhUgkToGhr2IWk8A51UOeggQqbwIBwo0EdUwpvIqSOGRbnlAWkhAVbNEI6yGZxjFqR8nQrThHkrSH)ZH2BW1A9j6gcCSGTmnRsRp76jcd1X8uoQs3i1IoOxr5SbhUgkTM(ZJDrdw5q7n40tuhdC(k5dA95XE(EIqLiJydoCnuA95XJOYH2BWPNOkxmiQRunArdgefyLO0OcIgny6NQlEa7)bd0SOrdMiwuW1GMfbrbwj6OqGJfSLzL9Zf2oOBRSjPyGZNs0ObZbdvAw0ObZog48vYh0SO7ORGVjEegiQq(aMOog48vYh06ZJ989eHkrimr)vGNZkZGOaBdorjmmuHcSe3SCO9gCTEQezlcRWRLx7Iyd)NdT3GR16teEaTXxA51UihSrb2lxmicDdmr8qctprJgmzquWPZIQehyLwFNk6YtDRNOgX2Cq0pdMGbhA8sLOrdMvIdSsZIgnyE5PU1SixGd6jYFWlKEQujA0GzhdxnlA0G5n4FovAwuhdx9e1i2MdA5vLkvA9zu9ezeBWHRHsRppEeLZgC4AO0A6pp2fvo0Edo9ev5IbrDLQrlAWGOaReLgvq0Obt)uDXdy)pyGMfnAWeXIcUg0zrquGvIoke4ybBzwz)CHTd62kBskg48PenAWCWqLMf1XaNVs(GwFESNVNienAWSJboFL8bnl6o6k4BIhHbIkKpGPsuSlSDq3)CWf1OatlpIWdOn(slV2fXdjm9enAWKbrbNolQsCGvA9DQOlp1TEIAeBZbr)mycgCOXlvIgnywjoWknlA0G5LN6wZICboONi)bVq6PsLOrdMDmC1SOrdM3G)5uPzrDmC1tuJyBoOLxvQe5GnkWE5IbrOBGjQR0ns9VaIvIokVRxE)xucddvOalXnlhAVbxRNkr2IWk8A51UieMO)kWZzLzquGTbNv2rhkcXIcUg0SObRCO9gC6jQJboFL8bT(8ypFprOseB4)CO9gCTwFIUHahlyltZQ067a6jYi2GdxdLwFN6repKW0t0ObtgefC6SOkXbwP13PIU8u36jQrSnhe9ZGjyWHgVujA0GzL4aR0zrJgmV8u3AwKlWb9e5p4fspvQenAWSJHRMfnAW8g8pNknlQJHREIAeBZbT8QsLihSrb2lxmicDdmrdw5q7n40tuhdC(k5dAD6x(E)ujIn8Fo0EdUwRprimrhcrdfkWSYmy4sIkhAVbNEIQCXGOUs1OfnyquGvIsJkiA0GPFQU4bS)hmqZIgnyIyrbxdAweefyLOJcbowWwMv2pxy7GUTYMKIboFkrJgmhmuPzrDmW5RKpO1PF579t0ObZog48vYh0SO7ORGVjEegiQq(aMkr2IWk8A51UOeggQqbwIBwo0EdUwpvIWdOn(slV2fLZgC4AO0A6pp2vP1x(6jYi2GdxdLwFN6r0Gvo0Edo9e1XaNVs(GwN(LV3pvIkhAVbNEIQCXGOUs1OfnyquGvIsJkiA0GPFQU4bS)hmqZIgnyIyrbxd6SiikWkrhfcCSGTmRSFUW2bDBLnjfdC(uIgnyoyOsZIgny2XaNVs(GMfDhDf8nXJWarfYhWe1XaNVs(GwN(LV3pvIWdOn(slV2fXdjm9enAWKbrbNolQsCGvA9DQOlp1TEIAeBZbr)mycgCOXlvIgnywjoWkDw0ObZlp1TMf5cCqpr(dEH0tLkrJgm7y4QzrJgmVb)ZPsZI6y4QNOgX2CqlVQujYbBuG9YfdIq3at0ne4ybBzAwect0Hq0qHcmRmdgUKv2rhkkNn4W1qP10FESlYwewHxlV2fXg(phAVbxR1Nielk4AqZIsyyOcfyjUz5q7n4A9uPsRVi0teUaRiKHsqRVtezeBWHRHsRP)mQhryOoMNY9aJuIoOxr3rxb)hyKseUb7wOaZkBYPSYSoUvMvMvMvM1XTYSYSYSY4HBIBLXs(GHnnm6gyg20WMg20WMg20WMg20WMg20WMg20Wrt8bezmKmunpWHBY)oMNYbU)2Wwz)9bbW2qIDH)EkRJBLzLzLzLHWnz0eFawzgQSYIiIiIiIiMYkRWdmRSOj(aSYImwz(Pc)eXXdb3Krt8byO)84XJhpEMYkBIt0k7Vne)TvgWWSoUvMvMvMvgc3Krt8byLzOYklIiIykRScpWSYIM4dWklYyL5Nk8tehpeCtgnXhGH(ZJhptzLnXjAL93r6VTYagM1XTYSYSYSYCqnCSjJM4dykRJdmmroyJcSxUyqubgPeDhDf8FGrkdzmwQarquGvIYzdoCnuAnTrZFIrere2)(oWx(hWUieMOdcGTHe7cIsyyOcfyjUz5q7n4A9ujYwewHx)XOE8CYbIW7NrThH3tY3ONiCtFseIyd)NdT3GR16teEaTXx6p57XJrpnFpg1JrpW3bIWUxHB6tIqudCC)ciwj6O8UE59Fr8qctprJgmV8u3AwKlWb9e5p4fspvQenAWSJHRMfnAW8g8pNknlQJHREIAeBZbT8Qs0LN6wprnIT5GOFgmbdo04LkvIkhAVbNEIUJUc(M4ryGOc5dyIyjFO1tRprheaBdj2fuPsLwE9ONiJydoCnu6pNCG8T7jIionIt8Cseg9uVc30Nyur5SbhUgk9NtIicJ(L)Ph4ary3(bo90tfUPpXUOYH2BWPNOkxmiQRunArJgmrSOGRbDweefyLiQsSlyO)tW5BOny4sIWfC(A5r0ObZbdvAweIffCnOzrdgefyLO0OcIgnyIl481SiwYhA906tebjUvwaNv2Znk8A5vebjUvwaNv2)On(ccJMbDR1PIiiXTYc4SYmM1On(sLO7ORGVjEegiQq(aMkr4b0gFPLDpI4HeMEIgnyE5PU1SixGd6jYFWlKEQujA0Gzhdxnl6YtDRNOgX2Cq0pdMGbhA8sLOogU6jQrSnh0YRi)bVq6PLxnR1PAwLkvICWgfyVCXGi0nWenyLdT3Gtpr4coFT8OsuAubDw0nWdo906e9h7E9EY3bSB08TNVr)o9agv4M2(PQeHWe9Wd3in9kqqIlYwewHxl7EeXg(phAVbxR1NOeggQqbwIBwo0EdUwpvIWqDmpLZ4BGjYywboCPlKhgFdSopOyGZn)RapN5FbjoITny4sQujkQwFN4XJkja

Again, if you have trouble importing, make sure you delete the first two empty lines that WordPress seems to insert for no apparent reason when you copy.

Posted in Tanking, Theck's Pounding Headaches | Tagged , , , , , , , | 15 Comments

Lusty Munching

There’s really not a lot to complain about in our 5.x rotation, but every now and then while I’m playing or writing simulations, I’ll notice a new oddity.  This isn’t that surprising – we had a pretty significant overhaul in 5.0, and while the developers did an impressive job of ironing out most of the kinks, stuff inevitably falls through the cracks when you have a system as complex as WoW.

This time, it’s another instance of haste-induced weirdness courtesy of Sanctity of Battle.  This isn’t the first time that haste scaling has introduced curiosities into our rotation – you may remember back in beta, when Sanctity of Battle was accidentally leading to situations where adding more haste decreased your DPS because of cooldown clashes.  Luckily, that particular bug was fixed before Mists of Pandaria was released.

This time the weirdness is quite a bit more subtle, and involves one of our level 75 talents: Holy Avenger.  Unlike most of our rotational abilities, Shield of the Righteous isn’t affected by Sanctity of Battle.  This leads to a weird situation where if you have a lot of haste (for example, Heroism/Bloodlust) and pop Holy Avenger, you can inadvertently “munch” holy power (for lack of a better term, also because “lusty munching” is an awesome name for a blog post).

To illustrate this, let’s say for the moment that you have 5% haste from gear, the 5% spell haste raid buff, Seal of Insight‘s 10% spell haste, and 30% haste from Heroism.  With that much haste your melee GCD is just under 1.1 seconds and your spell GCD is capped at 1 second.  However, your SotR cooldown is still stuck at 1.5 seconds. You can probably already guess where this is headed: you end up casting holy power generators faster than you can actually consume holy power with SotR.

For example, let’s say you get lucky with Grand Crusader procs and end up casting a sequence of CS-J-AS-CS-AS-.  That’s five holy power generators in a row, being cast at times t=0, 1.1, 2.2, 3.3, and 4.4 seconds.  However, even if you cast your first SotR instantly after CS at t=0, you can’t keep up with that rate of HPG.  Your SotR casts happen at t=0, 1.5, 3.0, and 4.5 seconds.  Note that there are two holy power generators occurring between the SotR casts at t=3.0 and at t=4.5 (at t=3.3 and t=4.4), which means one of them ended up wasted.  If we’re lucky we started the entire sequence at 0 holy power, and really only ended up wasting one holy power instead of three.  But if it happens more than once during the duration of Holy Avenger, the second one is guaranteed to waste three holy power.

In this idealized case, you need to get lucky with Grand Crusader to set up that situation.  However, that’s only how it works on paper.  In practice this issue shows up far more commonly because of latency and reaction time.  I can’t say for sure if SotR can be queued early like other spells – for example, CS can be queued within the latency tolerance window even if it’s still on coldown, provided the remaining cooldown is less than your latency tolerance of course – but while raiding it certainly didn’t feel like it could be, as I was consistently seeing munching issues with single Grand Crusader procs such as CS-J-AS-CS-, which shouldn’t cause the problem according to the ideal scenario.

On the other hand, I’m also certain that I don’t queue up my first SotR instantly after that first Crusader Strike either.  My own reaction time is such that I’m sure there’s at least 50-100 ms of delay between hitting CS and hitting SotR, and that might be a low estimate if I’m trying to do other things as well (moving, taunting a boss, etc.).  And if there’s any delay being accumulated (from similar sources) between SotR casts, that’s going to push subsequent ones back and cause the same clashing issue.  This is perhaps more easily seen in graphical form:

Holy power munching

Holy power munching under Bloodlust and Holy Avenger. The first situation does not cause munching, but the second one does because two HP generators are cast during one SotR period.

The first block diagram shows the ideal case, where your SotR is cast nearly instantly after CS (in this case I’ve delayed it very slightly, less than 30 milliseconds).  There’s only one holy power generator occurring during each SotR cooldown period, so nothing gets munched.  Note, however, that if that second Crusader Strike ends up proccing Grand Crusader, we have the 5-HPG scenario described above and the extra Grand Crusader proc gets munched.

The second block diagram shows a more realistic scenario, where SotR is delayed by a little more than a third of a second (350 milliseconds to be precise) to account for latency and reaction time.  And as you can see, because of the extra delay the second Crusader Strike is just edging ahead of the third SotR cast, leading to the Crusader Strike being munched.  If there’s any more than 300 milliseconds of delay accumulated during those first two SotR casts, either from pre-casting delay or delay between the casts themselves, you’ll run into this situation.

Note that I haven’t shown the Avenger’s Shield cooldown as being reduced to 1 second in this diagram, because it doesn’t end up affecting the results.  At first I mistakenly thought this was a factor in producing this munching scenario, but while making the diagram I realized that all it does is introduce a 0.1-second gap between the end of the AS GCD and the beginning of the CS GCD, as CS doesn’t become available any sooner, even with spell queuing.

I tend to work a little like a metronome, in nice even GCD increments (though Mel has me beat hands-down there: he’s the only person I know who considers a stopwatch an essential element of a raiding UI). For off-GCD abilities like SotR, Heroic Strike, and what have you, I tend to default to casting on half-integer steps, or halfway between GCDs.  That’s obviously a problem in this situation though, since I’d be immediately putting a ~500 millisecond delay on my first SotR cast, guaranteeing that I’ll end up munching my third HP generator.

When Heroism is cast that metronome speeds up, but the rhythm is still nice and steady.  But this gets a little screwy because speeding up my rhythm for the rotation completely de-synchs it from the SotR cast intervals.  And my poor, feeble brain just can’t handle that for some reason; trying to keep both of those timers running in my head just doesn’t work, and inevitably good ol’ brainy just gives up on the SotR one.  I account for it rather inelegantly: continuously spamming my SotR keybind (which itself incurs a few hundred ms of delay – think about how many times you can realistically press and release a button per second, it’s probably only 4-5 at most). And I’m afraid the problem is only going to get worse as we accumulate more haste on our gear in future tiers, because eventually we’ll have enough melee haste that the de-synching will occur (for me, at least) outside of Heroism.

Luckily, there are two pretty straightforward solutions the developers could employ to eliminate this particular case of weirdness.  The first is to simply add SotR to Sanctity of Battle. That way, the cooldown would scale exactly the same way as CS/J/etc., and players like me could go back to using one internal metronome.  The other solution is potentially even simpler: they could reduce the cooldown on SotR to one second instead of 1.5 seconds.

Those may seem like pretty significant buffs at first glance, but in fact, they really aren’t.  SotR is primarily limited by holy power rather than its cooldown, and the duration of the mitigation buff is additive anyway, so reducing the cooldown wouldn’t change how we use the ability in normal circumstances. And I doubt it’s a concern in PvP to be able to get two SotRs off in 1 second instead of 1.5 seconds (do people even PvP as prot anymore?).

At best we’d get an additional ~3-6 seconds of SotR uptime per encounter, provided we use Holy Avenger during Heroism and get lucky with Grand Crusader procs.  That’s 1%-2% more SotR uptime for a 5-minute encounter, and less if we aren’t lucky.  And it comes during the period when healers are at their maximum effectiveness too, further reducing the benefit.  I don’t think it constitutes an unbalancing increase in survivability, to be sure.  It would primarily be a quality-of-life boost to eliminate that weirdness and make the rotation feel less awkward in this one niche situation.

Note that everything I’ve said about SotR here could be equally applicable to Word of Glory, though I haven’t mentioned it until now.  Chain-casting WoG will run into exactly the same munching problem, so it probably warrants a similar solution.  I don’t think it’s any more unbalancing for WoG to be a 1-second cooldown for Prot or Ret, though I admit I don’t know how it would affect Holy (in fact, I don’t even know if they like to spec for Holy Avenger).

Posted in Tanking, Theck's Pounding Headaches, Theorycrafting | Tagged , , , , , , , , , | 15 Comments

Patch 5.1 Itemization Considerations

Patch 5.1 brings absolutely no changes to our core mechanics, so… carry on?  Unless you’ve been heavily using Turn Evil or Hand of Salvation, you might not notice a difference.

It does, however, bring up some interesting questions regarding gear.  In particular, now we can spend valor points to upgrade existing gear.  Since we’re limited to 1000 valor a week, and 3000 total, we’re going to have to spend some of it between now and the next raid tier (5.2, presumably), or else we’re wasting it.  So the obvious question that comes up is “what pieces of gear should I spend valor on?”  There are some new items added from the new factions (Operation: Shieldwall for Alliance, Dominance Offensive for Horde).  Since this isn’t a beginner’s blog, I’m just going to briefly touch on the new gear and then get to the meaty valor upgrading question.

New Reputation Gear

Unfortunately, most of the new items are fairly disappointing for tankadins, at least if you adhere to the Control gearing strategy.  Seal of the Shieldwall (horde equivalent) and Sabatons of the Sullied Shore (horde equivalent) are both dodge/parry itemized, and the Vaporshield Medallion (horde equivalent) trinket is dodge with a mastery proc.  Altogether uninspiring.

Edit: It looks like Seal of the Shieldwall is actually dodge/expertise itemized – wowhead is incorrectly showing the tooltip for Alani’s Inflexible Ring.  That makes it a considerably better ring, and may be worth picking up depending on what else you have access to.

Waistplate of Immobility (horde equivalent) is parry/hit and has reduced strength itemization, though.  Unfortunately it only has one socket, so it has trouble keeping up with other options in the stamina department.  That said, it’s still arguably the best belt you can pick up before heroic gear, so it’s something to consider if you aren’t planning on clearing heroic MSV/Terrace any time soon.

Valor Upgrade Strategies

Determining which items to upgrade will depend on what you’re trying to maximize.  For many of us (particularly 25-man raiders), stamina is the biggest factor in our choices.  We maintain hit/expertise caps through reforging (and gems where necessary), but try and use most of our gem itemization on stamina.  If that’s your gearing philosophy, trinkets one place you might think about spending that valor.  There are only 3 stamina trinkets to choose from: Lao-Chin’s Liquid Courage, Relic of Niuzao, and Jade Warlord Figurine.  That’s it – there are no other stamina trinkets in Heart of Fear or Terrace.  As such, if you’re using stamina trinkets, you’ll be wearing these three straight through until the next raiding tier.  Since Lao-Chin’s is guaranteed to not be replaced, it’s probably the first place to dump valor.  You get +62 stamina from the first 750 Valor points and +64 from the next 750, for a total of +126 stamina when fully upgraded.

Note, however, that trinkets aren’t truly your biggest stamina upgrade.  Helm, Chest, and Legs have the highest raw itemization factor of all pieces, so they’re likely to be the biggest upgrade.  Let’s consider the normal-mode protection tier set:  Upgrading the head, chest, or legs twice gives you  +142 total stamina and +105 extra secondary rating.  However, there’s the chance you’ll replace any or all of those pieces with heroic gear, making that valor expenditure short-lived.  If you’re not likely to see many heroic mode kills before the next raid tier, it might be better to spend valor on those three slots before you go to trinkets.  If you’re planning on being decked out in heroic gear before 5.2, then use it on the heroic helm/chest/legs as you accumulate them, and maybe upgrade your trinkets while you wait for those drops.

It’s worth noting that trinkets are still better (in terms of raw stamina) than any of the other slots.  None of the other slots give more than 1600 stamina, with one notable exception: Heroic Elite Deepwater Greatboots, which are just high-enough ilvl to reach that stamina plateau.

If you’re not focusing on increasing pure stamina – maybe you’re trying to maximize DPS, mastery, haste, or something else – then you want a more general strategy.  In that case, you want to prioritize upgrades based on Slot Modifier, which is what governs how much stat allocation each item gets.  Since helms, chests, and legs all have the highest slot modifier (1.00), they have the most stats and thus benefit the most from additional ilvl upgrades.  Shoulders, gloves, belts, and boots have a slot modifier of 0.75, so they’re the next tier of upgrades once you’re done with the “big three.”  Bracers, cloaks, necks, rings, and shields have a modifier of ~0.56, so they’re the third tier upgrades.  One-handed weapons fall into the last tier (~0.42), giving you the smallest raw stat upgrade.  Trinkets are somewhere between the top two tiers, not far behind the big three slots.

There’s also one or two caveats to mention here as well.  First, shields have over triple the armor itemization of other slots, so while they’re one of the weakest raw stamina upgrades, in practice they’re on-par with the second tier of items in terms of survivability.  For example, you get an additional ~250 armor by fully upgrading a heroic Steelskin, and you won’t be replacing it, so it’s something I’d consider before upgrading shoulders, gloves, belts, or boots.

Weapons will generally give you the biggest raw DPS upgrade, provided the stats on them are good.  Helms, chests, and legs come close thanks to the raw strength itemization, so a chest with expertise/haste or hit/haste itemization might even match a weapon upgrade.  But generally, you’ll be better off upgrading your weapon if you want raw DPS.

And again, your personal upgrade path will depend on what gear you have and have access to.  If you’re not going to replace something until 5.2, then that may take precedence over something you’ll be replacing in a few weeks.  I’ll probably be hitting my trinket up first, but I may skip upgrading Relic of Niuzao in the hopes that a Jade Warlord Figurine will drop.  Your mileage may vary.

Posted in Tanking, Theck's Pounding Headaches, Theorycrafting, Uncategorized | Tagged , , , , , , | 7 Comments

Haste Breakpoints for Tankadins

Mists of Pandaria has introduced protection paladins everywhere to a brave new world in which haste is a useful stat. For the first time in, well, ever, we’ve been given an opportunity to care about how our abilities scale with haste. And that includes something that most protection paladins haven’t had to consider before: haste breakpoints.

Now, if you’ve spent time in a Holy or Retribution off-spec, you might have already encountered haste breakpoints. But it’s possible that 5.x Protection actually beats both of them out in terms of the number and complexity of our haste-scaling effects.

In this post I’m going to go over some basics about how haste is calculated for protection, and then detail some of the situations we may run into at different levels of haste.

Basic Haste Mechanics

First, let’s briefly talk about how haste works. The simplest form is haste rating: you get 1% haste for every 425 haste rating. If you stack 850 haste rating, you have 2% haste, 1275 rating gives you 3% haste, and so on. There are a few ways to represent having x% haste that I will use interchangeably here. The first is what we’ve done so far: simply saying we have X% haste. And of course, any percentage can be expressed in fraction or decimal form, so 5% haste could be written as 5/100 or 0.05.

However, it’s also convenient to present haste in a different decimal form, namely as a multiple of our base (un-hasted) speed. If we say that with 0% haste, our speed is 1.00, then at 5% haste our speed is 1.05 and at X% haste our speed is (1+X/100). There’s no official name for this that I’m aware of, so let’s just call it our “haste modifier.”

This is important because, for the most part, different haste effects are multiplicative. The haste we get from haste rating is multiplicative with the haste we get from Heroism/Bloodlust, the 5% spell haste raid buff, the 10% melee attack speed buff, and the spell haste granted by Seal of Insight. To do calculations for haste, we have to multiply together all of the haste factors for each individual effect. So for example, if we have 5% haste from rating, the 5% spell haste raid buff, and 10% haste from Seal of Insight, our character sheet haste will be:

spellHaste = 1.05*1.05*1.10 = 1.21275,

or 21.28% haste on the character sheet. Note that this is a little larger than the simple sum of the three effects (5%+5%+10%=20%), so we get a little more bang for our buck as a result.

Melee haste is pretty straightforward as well, but it’s worth noting that the 10% melee attack speed buff does not give haste. It increases your attack speed, and even shows up on the character sheet as if it were a 10% multiplicative haste buff, but it doesn’t actually give you haste. As a result, it doesn’t affect Sanctity of Battle either – the cooldown reduction will essentially use your un-buffed haste, so it will be the same on a dummy as it is in a raid (barring boss-specific haste buffs, of course).

There are a number of effects that scale roughly linearly with haste. DPS, for example, is pretty much a 1:1 linear increase. If you get 10% haste, you attack 10% faster, Sanctity of Battle makes your abilities 10% faster, and generally you do about 10% more DPS. DoT effects with 100% uptime (like Censure) also increase linearly in that respect, as do proc-per-minute effects that aren’t haste normalized, like Seal of Insight and Glyph of Battle Healer healing. Real-PPM enchant effects have haste scaling built into them for this reason as well, otherwise they wouldn’t scale properly with haste.

However, there are a few effects that don’t increase strictly linearly. And those are the ones where the concept of a “haste break point” comes into play. The basic idea is that by reaching a specific amount of haste, an effect suddenly and discontinuously becomes better. The clearest example of this is Sacred Shield, which uses the game’s standard DoT/HoT haste-scaling mechanics.

Sacred Shield break points

The games method for calculating the duration and tick spacing for HoTs and DoTs is rather clever, but it requires a few steps to get there. First, let’s define some terms:

$N$ = number of ticks
$T_0$ = default (unhasted) tick duration
$T$ = hasted tick duration
$D_0$ = default(unhasted) buff duration
$D$ = buff duration in presence of spell haste

With no haste, Sacred Shield gives you a tick every $T_0=6$ seconds for $D_0=30$ seconds. What we’re really after is $D$ and $T$, though. The game determines that using the following logic: first, it determines the hasted tick duration; then it determines the number of ticks that comes closest to the unhasted duration; then it calculates the new duration using that number of ticks.

Edit: There’s one interesting addition here – the game rounds the hasted tick duration to the nearest millisecond, which has a small effect on certain haste breakpoints, generally shifting them by 1-5 haste rating. Keldion and I have discussed this in the comments, and I’ve done my own testing to confirm the behavior with Sacred Shield. In the math below, I’ll use “roundToMillisecond()” to represent this rounding.

Mathematically, this can be expressed by:

$T = {\rm roundToMillisecond} \left( T_0 / (1+{\rm spellHaste}) \right )$
$N = {\rm bRound}(D_0/T)$
$D=N*T$

As before, spellHaste is your total spell haste on the character sheet, which is calculated from the product of haste modifiers described in the last section. I’ll explain what “bRound()” is in a second, but for now pretend it’s just simple rounding.

So for example, let’s say you have 4% haste on gear and the spell haste raid buff. Your total spell haste is 1.04*1.05=1.092, or 9.2%. Your hasted tick duration is

$T=6/(1.092)=5.49450$ seconds, which is rounded to $5.495$ seconds.

so you’ll get a number of ticks equal to

$N={\rm bRound}(30/5.495)={\rm bRound}(5.4595)=5$

No extra tick, so your total buff duration is

$D=N*T=5*5.495=27.475$ seconds.

Bump that up to 6% haste from gear. Now your total spell haste is 11.3%, tick duration is $T=6/1.113=5.3908$ seconds, which is rounded to $5.391$ seconds, and

$N={\rm bRound}(30/5.391)={\rm bRound}(5.5648)=6$

Aha, extra tick! The new buff duration is $D=6*5.3908=32.3448$ seconds.

It should be pretty clear from this that you get a new tick every time the argument of bRound() ends in 0.5, which is when $30/T =5.5, 6.5, 7.5, 8.5,$ etc. If we do a little math, we can see what those spell haste breakpoints are:

$N = {\rm bRound}(D_0/T) = {\rm bRound}(D_0/(T_0/(1+{\rm spellHaste}))$
$= {\rm bRound}((D_0/T_0)*(1+{\rm spellHaste}))$
$= {\rm bRound}(D_0/T_0 + D_0/T_0*{\rm spellHaste})$

and plugging in the fact that $D_0/T_0 = 30/6 = 5$, we get

$N = {\rm bRound}(5+5*{\rm spellHaste})$

In other words, we get an extra tick any time 5*spellHaste reaches a value that ends in 0.5. Namely, at 10% (5*0.1=5), 30% (5*0.3=1.5), 50% (5*0.5=2.5), 70% (5*0.7=3.5), and every additional 20%.

Thus, your haste break points for getting new ticks are 10%, 30%, 50%, 70%, etc.

Now, I said we get a new tick every time the argument of “bRound” ends in 0.5. This is only partly true because “bRound” really stands for banker’s rounding, in which we always round to the nearest even number if the number to be rounded ends in exactly 0.50. So in theory, if we had 10% haste, we’d be rounding 5.5 up to 6, granting us a new tick. If we’re at 30% haste though, we’re rounding 6.5 down to 6, which doesn’t get us a new tick. However, as soon as we hit 30.001% haste, we have 6.5005, which gets rounded up. I don’t know how many decimal places the game stores for these values (probably very many), but it’s not likely to matter too much thanks to the millisecond rounding that occurs on the tick duration. It only becomes an issue if you land exactly on a given value (ex: exactly at 30*425=12750 rating, without having other multiplicative haste buffs), and roundToMillisecond() guarantees that happens very rarely. And with the spell haste buff and Seal of Insight, you’re even less likely to land on an exact break point.

Since people often want to know what the breakpoints are under certain conditions, I’ve summarized them on the following table. The code used to generate it can be found here.

|    haste% |  10% |   30% |   50% |   70% |   90% |  110% |
|         N |    6 |     7 |     8 |     9 |    10 |    11 |
|      None | 4251 | 12749 | 21243 | 29749 | 38261 | 46739 |
|        RB | 2025 | 10118 | 18207 | 26308 | 34415 | 42490 |
|       SoI |    1 |  7727 | 15448 | 23181 | 30919 | 38627 |
|    RB+SoI |    0 |  5335 | 12688 | 20053 | 27423 | 34764 |
|        BL |    0 |     0 |  6533 | 13076 | 19624 | 26146 |
|     BL+RB |    0 |     0 |  4198 | 10430 | 16665 | 22877 |
|    BL+SoI |    0 |     0 |  2075 |  8024 | 13976 | 19905 |
| BL+SoI+RB |    0 |     0 |     0 |  5618 | 11287 | 16934 |

Eternal Flame

Even though you shouldn’t be using Eternal Flame in the first place, it might be of interest to know when you get extra ticks of it (maybe you have a Holy off-spec). The calculation for this is identical to the one for Sacred Shield, except that $T_0=3$ instead of $6$. Thus, we want 10*spellHaste to equal something ending in 0.5, which leads to break points at 5% haste, 15% haste, 25% haste, and so on. The banker’s rounding affects 5%, 25%, 45%, etc. The table below summarizes the results:

|    haste% |   5% |  15% |   25% |   35% |   45% |   55% |   65% |   75% |   85% |
|         N |   11 |   12 |    13 |    14 |    15 |    16 |    17 |    18 |    19 |
|      None | 2120 | 6379 | 10637 | 14868 | 19139 | 23375 | 27613 | 31866 | 36131 |
|        RB |    0 | 4052 |  8106 | 12137 | 16204 | 20238 | 24275 | 28325 | 32387 |
|       SoI |    0 | 1936 |  5806 |  9653 | 13536 | 17386 | 21239 | 25106 | 28983 |
|    RB+SoI |    0 |    0 |  3506 |  7170 | 10867 | 14535 | 18204 | 21886 | 25579 |
|        BL |    0 |    0 |     0 |  1630 |  4915 |  8173 | 11433 | 14705 | 17986 |
|     BL+RB |    0 |    0 |     0 |     0 |  2657 |  5760 |  8865 | 11981 | 15106 |
|    BL+SoI |    0 |    0 |     0 |     0 |   605 |  3567 |  6530 |  9504 | 12487 |
| BL+SoI+RB |    0 |    0 |     0 |     0 |     0 |  1373 |  4196 |  7028 |  9869 |

Rotation

The rotation is surprisingly linear in haste up to 50% (melee, which is around 73% spell haste), as shown on the graph below. There are some minor discontinuities due to abilities that aren’t affected by Sanctity of Battle (our level 90 talents, for example), but they’re insignificant in practice because nobody plays like a robot. Latency, reaction time, and encounter mechanics all serve to smooth out those small discontinuities and make them irrelevant. This wasn’t always the case – in beta we discovered that there would be large discontinuities due to Avenger’s Shield, but eventually that was added to Sanctity of Battle to eliminate that problem.

Scaling of DPS, HPS, and HPG with haste up to 50%

Relative scaling of DPS, HPS, and HPG with haste. Up to 50%, everything scales very linearly

Things change at 50% haste because your global cooldown (GCD) becomes capped at one second. That might seem like an unrealistic target to hit, but keep in mind that encounter mechanics often get us there artificially (see, for example, Essence of the Red from Sinestra). Unfortunately, the MATLAB code doesn’t support the GCD clipping that occurs at 50% melee haste, so we can’t sim it out above that point (yet – maybe some day). We can use intuition to figure out some of the effects though.

So let’s say we do get to 50% haste. Is there a benefit to having more? Yes and no. At 50% haste, Crusader Strike’s cooldown is 3 seconds and Judgment’s is 4 seconds. Your rotation is still the same as it is with no haste: CS-J-X-CS-X-J-CS-X-X. Stacking more will reduce spell cooldowns, but not the GCD. That means we’ll have an odd choice to make. We can skip fillers for higher holy power generation (HPG), but probably much lower DPS. Or we can use fillers and delay holy power generators, essentially eliminating the benefit of extra haste on HPG.

For example, assume we have 80% haste. At that point, CS is a 2.5-second cooldown and J is 3.33 seconds. If we cast CS-J, we can either choose to wait half a second and use CS again, turning our rotation into CS-J-wait-CS-X-wait-(repeat), or we can keep our normal rotation and push back CS. The former will be higher HPG than the latter, but will probably be lower DPS.

At 100% haste, J becomes a 3-second cooldown while CS remains 2.25 seconds. If we continue to prioritize CS>J, we still have the 0.25-second clashing effect. However, if we prioritize J>CS, we get a nice even J-CS-X- rotation, with no wasted space. That might be a fairly large break point, because J>CS is higher in both HPG and raw DPS at that point.

We’ll run into this clashing until we get to 125% haste, at which point CS becomes a 2-second cooldown (and J a 2.67-second cooldown). Then we get to a clean CS-J-CS-X-(repeat), which again overtakes the J-CS-X- rotation in HPG (if not DPS). After that, there’s another gap until we have enough haste to push J to a 2-second cooldown, which happens at 200% haste, turning our rotation into a simple CS-J-(repeat) sequence. And of course, once you hit 500% haste, you can just spam Judgment until the end of time!

Note that haste isn’t completely useless in-between those break points – we’re still increasing SoI healing, and getting more Sacred Shield ticks every 20% haste. But it’s not worth a lot, because those are both small effects. We’re going to be seeing very large discontinuities whenever the rotation changes drastically, and a plateau between each of those break points.

So, TLDR: Haste is good up to 50%, uneven between 50% and 125%, and then relatively weak unless you can reach 200% (and then weak again until you can hit 500%, where you can spam Judgment every GCD).

A Word About Latency

Edit: the following section is apparently no longer true in 5.0.5 – as Lakh pointed out in the comments, you can now queue Crusader Strike even when it’s still got a little bit of cooldown left. However, you can’t queue it until the remaining cooldown is less than your “Lag Tolerance” as set in the in-game menu (under the “Combat” subheading). I never noticed this, because I set my custom lag tolerance fairly low (~50 ms). Bumping it up to the default of 400 ms allowed me to queue the next CS appropriately.

In closing, I want to mention latency (and to a lesser extent, reaction time). One of the problems with Crusader Strike is that you can’t queue it up early, as it will still be on cooldown. Thus, we pay a “double-latency” penalty on our rotation: if our latency is 50 milliseconds, our effective CS cooldown is actually 4.5+0.05+0.05=4.6 seconds. And it gets worse as your latency goes up; 100 milliseconds of latency puts you at a 4.7-second CS cooldown.

This has a slight effect on your rotation because it forces you to space out your CS casts. Generally, you’re not going to care about this much because you’re just going to live with it anyway. But if you’re aiming to have exactly X% haste for some reason – for example, if you wanted to make sure you were casting exactly 1 ability per second – then you’d want to account for this extra amount. In general, aiming for an additional couple percent of haste will be enough – in the case mentioned, you’d need an additional ~6.67% haste to turn a 4.7-second CS into a 3.0-second CS after latency.

Note, however, that latency does not significantly devalue haste under normal circumstances. Haste won’t reduce your latency, of course, but your latency is generally small compared to the cooldowns being reduced by haste. So if you add 10% haste, you’re still going to be casting everything about 10% faster. As you stack more haste this starts becoming significant because your latency is a greater fraction of the cooldowns being reduced, but if you’re below the 50% haste GCD cap, you’re devaluing haste by less than 5%. And of course, the latency penalty doesn’t affect auto-attacks, Seal of Insight, Censure, Sacred Shield, or Eternal Flame at all.

Posted in Tanking, Theck's Pounding Headaches, Theorycrafting | Tagged , , , , , , , , , | 41 Comments

Tankadin Weapon Enchants

There’s been quite a bit of discussion about weapon enchants, and which ones are the best for tanks. There are some enchants that are obviously intended to be tanking choices: River’s Song gives us dodge rating, while Colossus gives us absorption bubbles. And Dancing Steel gives a nice chunk of strength, which is almost a 1:1 conversion to parry rating after raid buffs. Given our new-found affinity for haste and mastery, a lot of people have thought favorably of Windsong, which in previous expansions would have been a pure DPS option.

My initial intuition told me that, based on the proc rates and effect types, Colossus would be a decent choice. Unfortunately, I just didn’t have the time to finish writing the detailed simulations I needed to prove it, though the data in my raid logs seemed consistent with what I expected. And before I got around to writing simulations, the “Real Proc Per Minute” (rPPM) mechanic was announced, throwing a wrench into the works. Since it seemed clear they were thinking about migrating the other effects to this system, I decided to wait on writing anything rigorous until the dust settled. And in due time, it was announced that all of these enchants are moving to a rPPM implementation in 5.1. Ten points for lazy Theck!

More seriously, though, this means we can now cleanly compare the different effects. I worked through some of the math for this in several forum posts, albeit a little sloppily. I’ve consolidated those posts here, and updated/corrected the math where it was a little less rigorous.

Uptime Calculations

The rPPM proc mechanics were described in this post by Daxxarri. The proc chance for any given attack is

$p = P H T/60$

where $P$ is the proc rate (i.e. “2 rPPM”), $H$ is your haste modifier (which is the higher of your melee and spell haste; in practice this will always be our spell haste thanks to Seal of Insight and the 5% spell haste raid buff), and $T$ is the time since the last eligible proc source (in this case, the last time you dealt damage, healed someone, or missed/dodged/parried). It’s relatively simple to show that for one of these enchants, this gives an uptime of approximately:

$U = P H D/60,$

where $D$ is the duration of the buff the effect grants.

I say “approximately” because technically a proc-based effect with $x$ rPPM won’t give you exactly $xHD$ seconds of uptime per minute. The reason is that you can get “unlucky” and have overlapping procs that refresh the buff, reducing the overall uptime. Hamlet has already described how to do this, so I won’t go into it here. This will reduce the effectiveness of Windsong, Dancing Steel, and River’s Song. The table below gives the time-averaged uptime of each of the enchants we’re interested in with and without this correction, assuming 10% spell haste:

Enchant P (PPM) P*H*D/60 1-exp(-P*H*D/60)
Windsong 2/3 0.1467 0.1364
Dancing Steel 2 0.4400 0.3560
River’s Song 4 0.5133 0.5133*

In this case, the Windsong result is for any one of the three buffs – i.e., we get about 13.64% uptime on each one. River’s Song is a bit of a special case as well – the buff it grants stacks twice, which changes the uptime calculation a bit. In that case, we only care about the situations where we get 3 procs in a short time period, such that one of them is “wasted.” That’s a much more complicated probability question, and the result will be very small, so we’re going to ignore it for the purposes of this post.

The effect this type of “munching” has on Colossus is harder to model. Colossus is 6 PPM, but it’s not a fixed-duration buff either. It lasts up to 10 seconds, but in practice it will be consumed much faster than that while you’re tanking. Exactly how fast depends on a myriad of factors – the boss’s attack speed, your avoidance, your attack speed, and what spells you cast (and in what order!). It’s too complicated a problem to accurately treat here, so we’re going to fudge the numbers a bit and assume about 10% Colossus munching, such that it completely offsets our haste bonus from Seal of Insight. This is almost certainly an overestimate of the munching effect, so our numbers for Colossus should be a lower bound on what you can reasonably expect.

Analysis

I had been saying that Dancing Steel was going to be better than River’s Song, but now I’m not so sure. Without the stacking mechanic the uptimes would be similar, which would give Dancing Steel the edge. But the stacking mechanic changes things – since it’s harder to waste a River’s Song proc we get considerably higher average uptime out of it. Dancing Steel still has some advantages – the ~587 average strength it provides gives you parry (which in some gear sets may be diminished less than dodge), plus some DPS, plus some SoI healing. But I’m not certain that it’s strictly superior to River’s Song (which gives ~847 dodge rating) anymore, even for raw avoidance.

The math for Windsong is sort of interesting. Since each buff is independent, we get an average of 13.64% for each of the three buffs it can grant. That’s 1500 of each rating with 0.1364 uptime, or an average of ~205 rating of each type. If we ignore crit, that’s about 410 rating total, which seems like a lot more than the other options (for example, the weapon chain’s static 200 expertise). However, remember that in terms of raw TDR, haste is abysmal. Putting my current stats into my spreadsheet, I get the following stat weights:

Armor 0.8358
Parry 0.4324
Dodge 0.4339
Strength 0.4224
Mastery 0.4380
Hit 0.2248
Expertise 0.1445
Haste 0.1722

So haste is about 0.1722/0.4380=39.3% as good as mastery for TDR. Having 205 haste and 205 mastery is roughly equivalent to having 286 mastery. To put that in terms of damage reduction, let’s use a simplistic model: the damage reduction is approximately equal to (SotR uptime)*rating/600, such that at 100% SotR uptime 600 rating gives 1% damage reduction. In practice, SotR uptime is generally only about 40-50%. If we take the generous assumption of 50% SotR uptime, that 286 rating is only 0.238% reduced damage taken. However, this is absolute damage taken, not relative damage taken. To get relative damage reduction, we’d need to divide by the amount we actually take (i.e. if we only take 70% of the damage that’s coming at us, it’s 0.00238/0.3=0.0079, or ~0.8% relative damage reduction).

In practice, this number is about right. With my stat weights, my TDR is around 71.5%, or 28.5% of raw boss damage taken. So, using our guess of about 0.8% relative damage reduction, how much DTPS must we be seeing in logs for this to equal Colossus absorption?

It should be (0.8%*DTPS)=800, or about 100k DTPS. Note that I’ve assumed that the free 10% spell haste we get from SoI is counteracted by Colossus munching, and haven’t included other haste contributions (spell haste raid buff, haste on gear, bloodlust, etc.). In practice both Windsong uptime and Colossus absorption per second will be a little higher because of those additional haste factors, and generally in Colossus’ favor. For example, in my gear set I have 4.14% haste, for 14.55% total before raid buffs and 20.28% after raid buffs, which means I’d be getting around 962 HPS from colossus and 14.82% uptime on Windsong (222 rating per buff, 310 effective mastery, 0.2583% absolute damage reduction, 0.8611% relative damage reduction), raising the threshold to 111.7k DTPS. These values are well above steady-state damage intake in heroic content (though on par with peak or high-damage periods).

So in 5.1, Windsong will definitely not be the best TDR enchant. Colossus has it beat by a fair bit, and even during high-damage-intake situations they’ll be about equal. As of right now, Colossus’ proc rate is a little lower – on our last Stone Guard 25H kill, it procced 34 times for 272k absorption in about 7 minutes, for about 650 HPS. That’s still well ahead of Windsong’s TDR performance.

In other words, if you are choosing Windsong for reasons of TDR, you’re doing it wrong.

Control Considerations

Now, you might argue that we’re not gearing for hit/exp/haste/mastery for the purposes of TDR, and you’d be right about that. We’re gearing for them because it gives us greater control over our survivability. But I think that’s makes for an even weaker argument for Windsong. Which gives you more reliable damage mitigation (or phrased another way, better smoothing): an 8k absorb every 10-12 seconds, or an uncontrollable proc that may or may not be up when you need it, and has a chance of giving you back-to-back crit procs that don’t help you?

Personally, I’d take the 8k absorb. Because my usual death scenario is a 5-8 second window where I’m bursted down without enough healing. There’s a very good chance that I’ll have one Colossus proc in that window (at roughly 1 proc every 8.3 seconds with 20% raid-buffed haste, the overlap chance is greater than 65%). There’s a much smaller chance that I have a useful Windsong proc covering that window. Admittedly, if it does line up, it’s a much stronger defensive effect than an 8k absorb, but I’d rather have the 8k absorb ~80% of the time than the much larger effect 25% of the time (roughly estimating, 12s*(4/3)/60s=26.6%).

There’s also something to be said for the Living Steel Weapon Chain. A static 200 expertise is always on, so it’s got the whole “consistency” thing in the bag. And it’s expertise, which we value much more highly than expertise or haste, right? Well, not exactly. If you can reach the caps via reforging already, all this enchant does for you is allow you to reforge less of that itemization on gear into expertise, and subsequently keep more mastery or haste. In that sense, it’s not worth 200 expertise, it’s worth 200 of whatever stat you’re reforging into after hit/exp caps – either 200 mastery or 200 haste. It’s only if you can’t reach the caps via just reforging that the enchant keeps its higher value as an expertise source.

Conclusions

Despite some early enthusiasm for Windsong, I think we can conclusively say that it isn’t as attractive as many thought it would be. In fact, despite the fact that we like haste and mastery, I think River’s Song is a stronger enchant. Remember that after hit/exp cap, avoidance is almost as good as haste and mastery, and River’s Song’s superior uptime gives you a lot more avoidance than Windsong gives haste and mastery.

I still think Dancing Steel has some allure as well – the fact that it grants parry might make up for the lower uptime, but that will depend on exactly how lopsided the avoidance on your gear set is. In my setup, parry’s actually being diminished more than dodge, so River’s Song would hold a commanding lead over Dancing Steel in TDR and survivability. Your mileage may vary.

For consistency, I think the Colossus enchant is unmatched. Yes, the absorb bubbles are small, but their reliability is what makes them attractive. Another 8k off of a 100k swing is still a good chunk, and in a longer death scenario I could get two of them. The fact that it’s fairly strong for TDR is a bonus.

I’m mixed on the weapon chain. I think it’s a good option when you’re at low gear levels, and really need that 200 expertise to get closer to the expertise hard cap. Once you can do that with gear and reforging alone, it loses a lot of its allure. If I had to choose between a 200 haste enchant and Colossus, I think Colossus would win every time. So I think the chain is probably worth setting aside once your gear improves.

Posted in Tanking, Theck's Pounding Headaches, Theorycrafting | Tagged , , , , , , , , , , , , | 10 Comments