Theorycrafting for Final Fantasy XIV.
This project is maintained by rconcep
from samurai import *
from plotting import *
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
import seaborn as sb
from IPython.display import display
%matplotlib inline
Up to level 3, you only have one weaponskill… so use it.
sam = Samurai()
actions = [('Hakaze'), ('Hakaze'), ('Hakaze'), ('Hakaze'),
('Hakaze'), ('Hakaze'), ('Hakaze'), ('Hakaze')]
df0, average_potency, pps = sam.parse_rotation(actions)
display(df0)
average potency per GCD = 150.0
average potency per second = 62.5
Time | Weaponskill | Ability | Potency | Jinpu | Shifu | Yukikaze | Higanbana | Kenki | Total Potency | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 0.0 | Hakaze | 150.0 | False | False | False | 0 | 0 | 150.0 | |
1 | 2.4 | Hakaze | 150.0 | False | False | False | 0 | 0 | 300.0 | |
2 | 4.8 | Hakaze | 150.0 | False | False | False | 0 | 0 | 450.0 | |
3 | 7.2 | Hakaze | 150.0 | False | False | False | 0 | 0 | 600.0 | |
4 | 9.6 | Hakaze | 150.0 | False | False | False | 0 | 0 | 750.0 | |
5 | 12.0 | Hakaze | 150.0 | False | False | False | 0 | 0 | 900.0 | |
6 | 14.4 | Hakaze | 150.0 | False | False | False | 0 | 0 | 1050.0 | |
7 | 16.8 | Hakaze | 150.0 | False | False | False | 0 | 0 | 1200.0 |
At level 4, you gain the use of Jinpu, which combos from Hakaze and gives you your damage up buff. You’ll definitely want to keep this buff up at all times and it should be simple enough with its 30s duration. The next weaponskill you obtain is Enpi, a ranged attack with a niche use. Level 6 grants you the defensive buff, Third Eye, and level 10 grants you the ability Ageha, an execution ability. Use it whenever available.
sam = Samurai()
actions = [('Hakaze'), ('Jinpu'), ('Hakaze'), ('Jinpu'),
('Hakaze'), ('Jinpu'), ('Hakaze'), ('Jinpu')]
df1, average_potency, pps = sam.parse_rotation(actions)
display(df1)
average potency per GCD = 239.1875
average potency per second = 99.6614583333
Time | Weaponskill | Ability | Potency | Jinpu | Shifu | Yukikaze | Higanbana | Kenki | Total Potency | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 0.0 | Hakaze | 150.0 | False | False | False | 0 | 0 | 150.0 | |
1 | 2.4 | Jinpu | 280.0 | False | False | False | 0 | 0 | 430.0 | |
2 | 4.8 | Hakaze | 172.5 | True | False | False | 0 | 0 | 602.5 | |
3 | 7.2 | Jinpu | 322.0 | True | False | False | 0 | 0 | 924.5 | |
4 | 9.6 | Hakaze | 172.5 | True | False | False | 0 | 0 | 1097.0 | |
5 | 12.0 | Jinpu | 322.0 | True | False | False | 0 | 0 | 1419.0 | |
6 | 14.4 | Hakaze | 172.5 | True | False | False | 0 | 0 | 1591.5 | |
7 | 16.8 | Jinpu | 322.0 | True | False | False | 0 | 0 | 1913.5 |
How does this compare to the previous rotation?
compare_potencies([df0, df1], ['Hakaze only', 'Jinpu combo'])
Level 18 sees the introduction of your haste buff, Shifu. When executed as a combo, Shifu grants you this buff for a duration of 30s in addition to the additional combo potency. At these levels, it’s fairly close as to which buff takes priority, Shifu or Jinpu.
sam = Samurai()
actions = [('Hakaze'), ('Shifu'), ('Hakaze'), ('Jinpu'),
('Hakaze'), ('Shifu'), ('Hakaze'), ('Jinpu')]
df2, average_potency, pps = sam.parse_rotation(actions)
display(df2)
average potency per GCD = 231.125
average potency per second = 105.53652968
Time | Weaponskill | Ability | Potency | Jinpu | Shifu | Yukikaze | Higanbana | Kenki | Total Potency | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 0.00 | Hakaze | 150.0 | False | False | False | 0 | 0 | 150.0 | |
1 | 2.40 | Shifu | 280.0 | False | False | False | 0 | 0 | 430.0 | |
2 | 4.56 | Hakaze | 150.0 | False | True | False | 0 | 0 | 580.0 | |
3 | 6.72 | Jinpu | 280.0 | False | True | False | 0 | 0 | 860.0 | |
4 | 8.88 | Hakaze | 172.5 | True | True | False | 0 | 0 | 1032.5 | |
5 | 11.04 | Shifu | 322.0 | True | True | False | 0 | 0 | 1354.5 | |
6 | 13.20 | Hakaze | 172.5 | True | True | False | 0 | 0 | 1527.0 | |
7 | 15.36 | Jinpu | 322.0 | True | True | False | 0 | 0 | 1849.0 |
compare_potencies([df1, df2], ['Jinpu combo only', 'Jinpu and Shifu combos'])
** Note: The Shifu buff is only accounted for in potency per second calculations.
Level 26 introduces your first AoE ability, Fuga. At this time, it does not combo to or from anything and deals 100 potency to all targets in a frontal cone.
Napkin math says that Fuga should do more potency per GCD for three or more targets. Should we put our Shifu and Jinpu buffs if they’re not up before using Fuga? Depends on how long the encounter is.
dfs_buff = []
pps_buff = []
labels = []
n_target_range = range(2, 8)
for n_targets in n_target_range:
sam = Samurai()
actions = [('Hakaze'), ('Shifu'), ('Hakaze'), ('Jinpu'),
('Fuga'), ('Fuga'), ('Fuga'), ('Fuga'),
('Fuga'), ('Fuga'), ('Fuga'), ('Fuga'),
('Fuga'), ('Fuga'), ('Fuga'), ('Fuga')]
print('number of targets = %s' % n_targets)
df_temp, average_potency, pps = sam.parse_rotation(actions, n_targets=n_targets)
dfs_buff.append(df_temp)
pps_buff.append(pps)
labels.append('%s targets' % n_targets)
print('\n')
number of targets = 2
average potency per GCD = 226.25
average potency per second = 104.022988506
number of targets = 3
average potency per GCD = 312.5
average potency per second = 143.67816092
number of targets = 4
average potency per GCD = 398.75
average potency per second = 183.333333333
number of targets = 5
average potency per GCD = 485.0
average potency per second = 222.988505747
number of targets = 6
average potency per GCD = 571.25
average potency per second = 262.643678161
number of targets = 7
average potency per GCD = 657.5
average potency per second = 302.298850575
compare_n_potencies(dfs_buff, labels)
dfs_no_buff = []
pps_no_buff = []
labels = []
for n_targets in n_target_range:
sam = Samurai()
actions = [('Fuga'), ('Fuga'), ('Fuga'), ('Fuga'),
('Fuga'), ('Fuga'), ('Fuga'), ('Fuga'),
('Fuga'), ('Fuga'), ('Fuga'), ('Fuga'),
('Fuga'), ('Fuga'), ('Fuga'), ('Fuga')]
print('number of targets = %s' % n_targets)
df_temp, average_potency, pps = sam.parse_rotation(actions, n_targets=n_targets)
dfs_no_buff.append(df_temp)
pps_no_buff.append(pps)
labels.append('%s targets' % n_targets)
print('\n')
number of targets = 2
average potency per GCD = 200.0
average potency per second = 83.3333333333
number of targets = 3
average potency per GCD = 300.0
average potency per second = 125.0
number of targets = 4
average potency per GCD = 400.0
average potency per second = 166.666666667
number of targets = 5
average potency per GCD = 500.0
average potency per second = 208.333333333
number of targets = 6
average potency per GCD = 600.0
average potency per second = 250.0
number of targets = 7
average potency per GCD = 700.0
average potency per second = 291.666666667
compare_n_potencies(dfs_no_buff, labels)
The potency over four GCDs to put up Shifu and Jinpu is about 977. If this is more than the potential potency delivered by four Fuga, we need the increased potency from the buffs to make up for this “buff tax.”
fig, axes = plt.subplots(nrows=1, ncols=1, sharex=True, figsize=(12,4))
fig.tight_layout(pad=2)
axes.plot(n_target_range, pps_buff, '-s', label='buffs')
axes.plot(n_target_range, pps_no_buff, ':o', label='no buffs')
axes.set_ylabel('Potency per second')
axes.set_xlabel('Number of Targets')
axes.legend(loc='upper left', framealpha=0.5)
fig.suptitle('Average Potency per second over %s GCDs' % len(actions))
<matplotlib.text.Text at 0x19c86b15fd0>
Over a 16 GCD encounter, buffing before Fuga spam wins every time. Let’s see how the two rotations compare over different encounter lengths.
fig, axes = plt.subplots(nrows=len(dfs_buff), ncols=1, sharex=True, figsize=(12,12))
fig.tight_layout(pad=2)
for k, _ in enumerate(dfs_buff):
ax = axes[k]
xlocs = dfs_buff[k]['Time']
ax.plot(xlocs, dfs_buff[k]['Total Potency'], '-s', label='buffs')
xlocs = dfs_no_buff[k]['Time']
ax.plot(xlocs, dfs_no_buff[k]['Total Potency'], ':o', label='no buffs')
ax.set_ylabel('Cumulative Potency', fontsize=10)
axes[-1].set_xlabel('Time')
axes[-1].set_xticks(xlocs)
ax.legend(loc='upper left', framealpha=0.5, prop={'size': 'small'})
ax.set_title('on %s targets' % n_target_range[k])
fig.tight_layout(pad=3)
There are approximately fourteen GCDs after putting up your first buff, Shifu before you need to refresh it. For small mob counts, the crossover point where putting up buffs before using Fuga is more optimal occurs fairly early on. However, as the number of targets increases, the upfront “cost” of putting the buffs up does not pay off until much later. A sixteen GCD pull is likely to run you dry on TP, even with Invigorate. At these low levels, the pull sizes are likely to be small, so putting up buffs first is probably optimal.
Note that the potency per second of the buffed AoE rotation is greater than that of the single target rotation for pulls of three or more targets.
Level 30 sees the introduction of your first Sen through the Gekko combo finisher (combo from Jinpu) and with it your first Iaijutsu, Higanbana. This powerful single-target weaponskill applies a 60s DoT in addition to initial damage for a total of 940 potency over its duration.
sam = Samurai()
actions = [('Hakaze'), ('Shifu'), ('Hakaze'), ('Jinpu'),
('Gekko'), ('Higanbana'), ('Hakaze'), ('Jinpu'),
('Gekko'), ('Hakaze'), ('Jinpu'), ('Gekko'),
('Hakaze'), ('Shifu')]
df3, average_potency, pps = sam.parse_rotation(actions)
display(df3)
average potency per GCD = 302.23857142857145
average potency per second = 138.823490814
Time | Weaponskill | Ability | Potency | Jinpu | Shifu | Yukikaze | Higanbana | Kenki | Total Potency | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 0.00 | Hakaze | 150.00 | False | False | False | 0 | 0 | 150.00 | |
1 | 2.40 | Shifu | 280.00 | False | False | False | 0 | 0 | 430.00 | |
2 | 4.56 | Hakaze | 150.00 | False | True | False | 0 | 0 | 580.00 | |
3 | 6.72 | Jinpu | 280.00 | False | True | False | 0 | 0 | 860.00 | |
4 | 8.88 | Gekko | 460.00 | True | True | False | 0 | 0 | 1320.00 | |
5 | 11.04 | Higanbana | 276.00 | True | True | False | 0 | 0 | 1596.00 | |
6 | 13.20 | Hakaze | 201.48 | True | True | False | 1 | 0 | 1797.48 | |
7 | 15.36 | Jinpu | 350.98 | True | True | False | 1 | 0 | 2148.46 | |
8 | 17.52 | Gekko | 488.98 | True | True | False | 1 | 0 | 2637.44 | |
9 | 19.68 | Hakaze | 201.48 | True | True | False | 1 | 0 | 2838.92 | |
10 | 21.84 | Jinpu | 350.98 | True | True | False | 1 | 0 | 3189.90 | |
11 | 24.00 | Gekko | 488.98 | True | True | False | 1 | 0 | 3678.88 | |
12 | 26.16 | Hakaze | 201.48 | True | True | False | 1 | 0 | 3880.36 | |
13 | 28.32 | Shifu | 350.98 | True | True | False | 1 | 0 | 4231.34 |
** Note: the potency of the DoT is prorated due to the GCD being shorter than the DoT tick period. So Higanbana’s initial potency is applied on action and the DoT potency is added to subsequent GCDs.
This combo finisher is a massive increase in potency per second (~40%).
plot_potency(df3)
At this point, the average potency of the Gekko combo is 400+280+150=830/3=~276.66 before buffs. The average potency of the Shifu combo is 150+280=430/2=215 before buffs. Therefore, Higanbana is more optimal than the Gekko combo after two DoT ticks. Since it takes approximately 3-4 GCDs to reapply Higanbana (Gekko combo plus cast time of Higanbana), Higanbana may be optimal to clip in single target situations. Depending on the GCD and server tick, this may be close. Additionally, in small mob groups, applying Higanbana to each target may also be optimal.
sam = Samurai()
actions = [('Hakaze'), ('Shifu'), ('Hakaze'), ('Jinpu'),
('Gekko'), ('Higanbana'), ('Hakaze'), ('Jinpu'),
('Gekko'), ('Higanbana'), ('Hakaze'), ('Jinpu'),
('Gekko'), ('Higanbana'), ('Hakaze'), ('Shifu')]
df3_clip, average_potency, pps = sam.parse_rotation(actions)
display(df3_clip)
average potency per GCD = 302.58124999999995
average potency per second = 139.117816092
Time | Weaponskill | Ability | Potency | Jinpu | Shifu | Yukikaze | Higanbana | Kenki | Total Potency | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 0.00 | Hakaze | 150.00 | False | False | False | 0 | 0 | 150.00 | |
1 | 2.40 | Shifu | 280.00 | False | False | False | 0 | 0 | 430.00 | |
2 | 4.56 | Hakaze | 150.00 | False | True | False | 0 | 0 | 580.00 | |
3 | 6.72 | Jinpu | 280.00 | False | True | False | 0 | 0 | 860.00 | |
4 | 8.88 | Gekko | 460.00 | True | True | False | 0 | 0 | 1320.00 | |
5 | 11.04 | Higanbana | 276.00 | True | True | False | 0 | 0 | 1596.00 | |
6 | 13.20 | Hakaze | 201.48 | True | True | False | 1 | 0 | 1797.48 | |
7 | 15.36 | Jinpu | 350.98 | True | True | False | 1 | 0 | 2148.46 | |
8 | 17.52 | Gekko | 488.98 | True | True | False | 1 | 0 | 2637.44 | |
9 | 19.68 | Higanbana | 304.98 | True | True | False | 1 | 0 | 2942.42 | |
10 | 21.84 | Hakaze | 201.48 | True | True | False | 1 | 0 | 3143.90 | |
11 | 24.00 | Jinpu | 350.98 | True | True | False | 1 | 0 | 3494.88 | |
12 | 26.16 | Gekko | 488.98 | True | True | False | 1 | 0 | 3983.86 | |
13 | 28.32 | Higanbana | 304.98 | True | True | False | 1 | 0 | 4288.84 | |
14 | 30.48 | Hakaze | 201.48 | True | True | False | 1 | 0 | 4490.32 | |
15 | 32.64 | Shifu | 350.98 | True | False | False | 1 | 0 | 4841.30 |
In a multi-target situation, the DoT can be applied to different mobs to avoid clipping. This will increase the DoT potency accumulation following each Higanbana application, leading to a slight increase in net potency. Note the reapplication of Shifu to keep the buff up.
Now let’s try applying Higanbana once and not clipping it (e.g., single target situation):
sam = Samurai()
actions = [('Hakaze'), ('Shifu'), ('Hakaze'), ('Jinpu'),
('Gekko'), ('Higanbana'), ('Hakaze'), ('Jinpu'),
('Gekko'), ('Hakaze'), ('Jinpu'), ('Gekko'),
('Hakaze'), ('Shifu'), ('Hakaze'), ('Jinpu')]
df3_noclip, average_potency, pps = sam.parse_rotation(actions)
display(df3_noclip)
average potency per GCD = 298.98749999999995
average potency per second = 137.465517241
Time | Weaponskill | Ability | Potency | Jinpu | Shifu | Yukikaze | Higanbana | Kenki | Total Potency | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 0.00 | Hakaze | 150.00 | False | False | False | 0 | 0 | 150.00 | |
1 | 2.40 | Shifu | 280.00 | False | False | False | 0 | 0 | 430.00 | |
2 | 4.56 | Hakaze | 150.00 | False | True | False | 0 | 0 | 580.00 | |
3 | 6.72 | Jinpu | 280.00 | False | True | False | 0 | 0 | 860.00 | |
4 | 8.88 | Gekko | 460.00 | True | True | False | 0 | 0 | 1320.00 | |
5 | 11.04 | Higanbana | 276.00 | True | True | False | 0 | 0 | 1596.00 | |
6 | 13.20 | Hakaze | 201.48 | True | True | False | 1 | 0 | 1797.48 | |
7 | 15.36 | Jinpu | 350.98 | True | True | False | 1 | 0 | 2148.46 | |
8 | 17.52 | Gekko | 488.98 | True | True | False | 1 | 0 | 2637.44 | |
9 | 19.68 | Hakaze | 201.48 | True | True | False | 1 | 0 | 2838.92 | |
10 | 21.84 | Jinpu | 350.98 | True | True | False | 1 | 0 | 3189.90 | |
11 | 24.00 | Gekko | 488.98 | True | True | False | 1 | 0 | 3678.88 | |
12 | 26.16 | Hakaze | 201.48 | True | True | False | 1 | 0 | 3880.36 | |
13 | 28.32 | Shifu | 350.98 | True | True | False | 1 | 0 | 4231.34 | |
14 | 30.48 | Hakaze | 201.48 | True | True | False | 1 | 0 | 4432.82 | |
15 | 32.64 | Jinpu | 350.98 | True | True | False | 1 | 0 | 4783.80 |
compare_potencies([df3_clip, df3_noclip], ['Clipping', 'No clipping'])
It’s fairly close over this time horizon. The average potency per second is vastly dependent on where the encounter ends more than anything. Regardless if you clip Higanbana or not, it is better than not using Higanbana at all. The bottom line: use your Iaijutsu!
Level 35 introduces an AoE combo with Mangetsu (combo from Fuga). This weaponskill also opens the Getsu Sen. Due to the diminishing AoE scaling, this combo is an average of no less than 100 potency per target over two GCDs. Because Mangetsu opens the Getsu Sen, this allows you to apply Higanbana to individual targets in the group. Depending on group size and encounter duration, this may be optimal.
dfs_higanbana = []
pps_higanbana = []
labels = []
n_target_range = range(2, 8)
for n_targets in n_target_range:
sam = Samurai()
actions = [('Fuga'), ('Mangetsu'), ('Higanbana'), ('Fuga'),
('Mangetsu'), ('Higanbana'), ('Fuga'), ('Mangetsu'),
('Higanbana'), ('Fuga'), ('Mangetsu'), ('Higanbana'),
('Fuga'), ('Mangetsu')]
print('number of targets = %s' % n_targets)
df_temp, average_potency, pps = sam.parse_rotation(actions, n_targets=n_targets)
dfs_higanbana.append(df_temp)
pps_higanbana.append(pps)
labels.append('%s targets' % n_targets)
print('\n')
number of targets = 2
average potency per GCD = 303.7142857142857
average potency per second = 126.547619048
number of targets = 3
average potency per GCD = 408.57142857142856
average potency per second = 170.238095238
number of targets = 4
average potency per GCD = 506.2857142857143
average potency per second = 210.952380952
number of targets = 5
average potency per GCD = 584.8571428571429
average potency per second = 243.69047619
number of targets = 6
average potency per GCD = 656.2857142857143
average potency per second = 273.452380952
number of targets = 7
average potency per GCD = 727.7142857142857
average potency per second = 303.214285714
compare_n_potencies(dfs_higanbana, labels)
dfs_no_higanbana = []
pps_no_higanbana = []
labels = []
n_target_range = range(2, 8)
for n_targets in n_target_range:
sam = Samurai()
actions = [('Fuga'), ('Mangetsu'), ('Fuga'), ('Mangetsu'),
('Fuga'), ('Mangetsu'), ('Fuga'), ('Mangetsu'),
('Fuga'), ('Mangetsu'), ('Fuga'), ('Mangetsu'),
('Fuga'), ('Mangetsu')]
print('number of targets = %s' % n_targets)
df_temp, average_potency, pps = sam.parse_rotation(actions, n_targets=n_targets)
dfs_no_higanbana.append(df_temp)
pps_no_higanbana.append(pps)
labels.append('%s targets' % n_targets)
print('\n')
number of targets = 2
average potency per GCD = 290.0
average potency per second = 120.833333333
number of targets = 3
average potency per GCD = 420.0
average potency per second = 175.0
number of targets = 4
average potency per GCD = 540.0
average potency per second = 225.0
number of targets = 5
average potency per GCD = 650.0
average potency per second = 270.833333333
number of targets = 6
average potency per GCD = 750.0
average potency per second = 312.5
number of targets = 7
average potency per GCD = 850.0
average potency per second = 354.166666667
compare_n_potencies(dfs_no_higanbana, labels)
fig, axes = plt.subplots(nrows=1, ncols=1, sharex=True, figsize=(12,4))
fig.tight_layout(pad=2)
axes.plot(n_target_range, pps_higanbana, '-o', label='Applying Higanbana')
axes.plot(n_target_range, pps_no_higanbana, ':o', label='No Higanbana')
axes.plot(n_target_range, pps_buff, ':o', label='Buffed Fuga spam')
axes.set_ylabel('Potency per second')
axes.set_xlabel('Number of Targets')
axes.legend(loc='upper left', framealpha=0.5)
fig.suptitle('Average Potency per second over %s GCDs' % len(actions))
<matplotlib.text.Text at 0x19c874ec198>
fig, axes = plt.subplots(nrows=len(dfs_higanbana), ncols=1, sharex=True, figsize=(12,12))
fig.tight_layout(pad=2)
for k, _ in enumerate(dfs_higanbana):
ax = axes[k]
xlocs = dfs_higanbana[k]['Time']
ax.plot(xlocs, dfs_higanbana[k]['Total Potency'], '-o', label='Applying Higanbana')
xlocs = dfs_no_higanbana[k]['Time']
ax.plot(xlocs, dfs_no_higanbana[k]['Total Potency'], ':o', label='No Higanbana')
ax.set_ylabel('Cumulative Potency', fontsize=10)
axes[-1].set_xlabel('Time')
axes[-1].set_xticks(xlocs)
ax.legend(loc='upper left', framealpha=0.5, prop={'size': 'small'})
ax.set_title('on %s targets' % n_target_range[k])
fig.tight_layout(pad=3)
Since 3-4 is the typical pull size for leveling dungeons, it is likely optimal to not apply Higanbana to each mob at this level range. However, it is extremely close either way. One advantage for applying Higanbana, however, would be TP relief from executing the AoE weaponskills. Should we buff with Jinpu and Shifu before executing this rotation?
sam = Samurai()
n_targets = 3
actions = [('Hakaze'), ('Shifu'), ('Hakaze'), ('Jinpu'),
('Fuga'), ('Mangetsu'), ('Fuga'), ('Mangetsu'),
('Fuga'), ('Mangetsu'), ('Fuga'), ('Mangetsu'),
('Fuga'), ('Mangetsu'), ('Fuga'), ('Mangetsu')]
df4_buff, average_potency, pps = sam.parse_rotation(actions, n_targets=n_targets)
display(df4_buff)
average potency per GCD = 416.0
average potency per second = 191.264367816
Time | Weaponskill | Ability | Potency | Jinpu | Shifu | Yukikaze | Higanbana | Kenki | Total Potency | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 0.00 | Hakaze | 150.0 | False | False | False | 0 | 0 | 150.0 | |
1 | 2.40 | Shifu | 280.0 | False | False | False | 0 | 0 | 430.0 | |
2 | 4.56 | Hakaze | 150.0 | False | True | False | 0 | 0 | 580.0 | |
3 | 6.72 | Jinpu | 280.0 | False | True | False | 0 | 0 | 860.0 | |
4 | 8.88 | Fuga | 345.0 | True | True | False | 0 | 0 | 1205.0 | |
5 | 11.04 | Mangetsu | 621.0 | True | True | False | 0 | 0 | 1826.0 | |
6 | 13.20 | Fuga | 345.0 | True | True | False | 0 | 0 | 2171.0 | |
7 | 15.36 | Mangetsu | 621.0 | True | True | False | 0 | 0 | 2792.0 | |
8 | 17.52 | Fuga | 345.0 | True | True | False | 0 | 0 | 3137.0 | |
9 | 19.68 | Mangetsu | 621.0 | True | True | False | 0 | 0 | 3758.0 | |
10 | 21.84 | Fuga | 345.0 | True | True | False | 0 | 0 | 4103.0 | |
11 | 24.00 | Mangetsu | 621.0 | True | True | False | 0 | 0 | 4724.0 | |
12 | 26.16 | Fuga | 345.0 | True | True | False | 0 | 0 | 5069.0 | |
13 | 28.32 | Mangetsu | 621.0 | True | True | False | 0 | 0 | 5690.0 | |
14 | 30.48 | Fuga | 345.0 | True | True | False | 0 | 0 | 6035.0 | |
15 | 32.64 | Mangetsu | 621.0 | True | False | False | 0 | 0 | 6656.0 |
sam = Samurai()
n_targets = 3
actions = [('Fuga'), ('Mangetsu'), ('Fuga'), ('Mangetsu'),
('Fuga'), ('Mangetsu'), ('Fuga'), ('Mangetsu'),
('Fuga'), ('Mangetsu'), ('Fuga'), ('Mangetsu'),
('Fuga'), ('Mangetsu'), ('Fuga'), ('Mangetsu')]
df4_no_buff, average_potency, pps = sam.parse_rotation(actions, n_targets=n_targets)
display(df4_no_buff)
average potency per GCD = 420.0
average potency per second = 175.0
Time | Weaponskill | Ability | Potency | Jinpu | Shifu | Yukikaze | Higanbana | Kenki | Total Potency | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 0.0 | Fuga | 300.0 | False | False | False | 0 | 0 | 300.0 | |
1 | 2.4 | Mangetsu | 540.0 | False | False | False | 0 | 0 | 840.0 | |
2 | 4.8 | Fuga | 300.0 | False | False | False | 0 | 0 | 1140.0 | |
3 | 7.2 | Mangetsu | 540.0 | False | False | False | 0 | 0 | 1680.0 | |
4 | 9.6 | Fuga | 300.0 | False | False | False | 0 | 0 | 1980.0 | |
5 | 12.0 | Mangetsu | 540.0 | False | False | False | 0 | 0 | 2520.0 | |
6 | 14.4 | Fuga | 300.0 | False | False | False | 0 | 0 | 2820.0 | |
7 | 16.8 | Mangetsu | 540.0 | False | False | False | 0 | 0 | 3360.0 | |
8 | 19.2 | Fuga | 300.0 | False | False | False | 0 | 0 | 3660.0 | |
9 | 21.6 | Mangetsu | 540.0 | False | False | False | 0 | 0 | 4200.0 | |
10 | 24.0 | Fuga | 300.0 | False | False | False | 0 | 0 | 4500.0 | |
11 | 26.4 | Mangetsu | 540.0 | False | False | False | 0 | 0 | 5040.0 | |
12 | 28.8 | Fuga | 300.0 | False | False | False | 0 | 0 | 5340.0 | |
13 | 31.2 | Mangetsu | 540.0 | False | False | False | 0 | 0 | 5880.0 | |
14 | 33.6 | Fuga | 300.0 | False | False | False | 0 | 0 | 6180.0 | |
15 | 36.0 | Mangetsu | 540.0 | False | False | False | 0 | 0 | 6720.0 |
compare_potencies([df4_buff, df4_no_buff], ['buffs', 'no buffs'])
If the pull is long enough, you should buff first. Ideally, you would shift to a single target rotation as mobs die, possibly letting you refresh buffs that carry over to the next pull.
Level 40 introduces the Kasha combo finisher (combo from Shifu). Equal in potency to the Gekko finisher, this weaponskill opens the Ka Sen. This leads to a maximum of two Sen open and also unlocks the use of the Iaijutsu Tenka Goken. This powerful, AoE weaponskill scales its potency depending on the number of targets from 180 potency up to a maximum of 360 potency for the first target hit. In AoE situations, this is likely the Iaijutsu of choice due to its instantaneous damage. Unfortunately, you do not get the AoE weaponskill to open Ka until level 45. For single target, do we still want to try our shiny new Iaijutsu?
sam = Samurai()
n_targets = 1
actions = [('Hakaze'), ('Shifu'), ('Kasha'), ('Higanbana'),
('Hakaze'), ('Jinpu'), ('Gekko'), ('Hakaze'),
('Shifu'), ('Kasha'), ('Tenka Goken'), ('Hakaze'),
('Jinpu'), ('Gekko'), ('Hakaze'), ('Shifu'),
('Kasha'), ('Tenka Goken')]
df5_tenka, average_potency, pps = sam.parse_rotation(actions, n_targets=n_targets)
display(df5_tenka)
average potency per GCD = 333.57222222222214
average potency per second = 153.484151329
Time | Weaponskill | Ability | Potency | Jinpu | Shifu | Yukikaze | Higanbana | Kenki | Total Potency | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 0.00 | Hakaze | 150.0 | False | False | False | 0 | 0 | 150.0 | |
1 | 2.40 | Shifu | 280.0 | False | False | False | 0 | 0 | 430.0 | |
2 | 4.56 | Kasha | 400.0 | False | True | False | 0 | 0 | 830.0 | |
3 | 6.72 | Higanbana | 240.0 | False | True | False | 0 | 0 | 1070.0 | |
4 | 8.88 | Hakaze | 175.2 | False | True | False | 1 | 0 | 1245.2 | |
5 | 11.04 | Jinpu | 305.2 | False | True | False | 1 | 0 | 1550.4 | |
6 | 13.20 | Gekko | 485.2 | True | True | False | 1 | 0 | 2035.6 | |
7 | 15.36 | Hakaze | 197.7 | True | True | False | 1 | 0 | 2233.3 | |
8 | 17.52 | Shifu | 347.2 | True | True | False | 1 | 0 | 2580.5 | |
9 | 19.68 | Kasha | 485.2 | True | True | False | 1 | 0 | 3065.7 | |
10 | 21.84 | Tenka Goken | 439.2 | True | True | False | 1 | 0 | 3504.9 | |
11 | 24.00 | Hakaze | 197.7 | True | True | False | 1 | 0 | 3702.6 | |
12 | 26.16 | Jinpu | 347.2 | True | True | False | 1 | 0 | 4049.8 | |
13 | 28.32 | Gekko | 485.2 | True | True | False | 1 | 0 | 4535.0 | |
14 | 30.48 | Hakaze | 197.7 | True | True | False | 1 | 0 | 4732.7 | |
15 | 32.64 | Shifu | 347.2 | True | True | False | 1 | 0 | 5079.9 | |
16 | 34.80 | Kasha | 485.2 | True | True | False | 1 | 0 | 5565.1 | |
17 | 36.96 | Tenka Goken | 439.2 | True | True | False | 1 | 0 | 6004.3 |
sam = Samurai()
n_targets = 1
actions = [('Hakaze'), ('Shifu'), ('Kasha'), ('Higanbana'),
('Hakaze'), ('Jinpu'), ('Gekko'), ('Higanbana'),
('Hakaze'), ('Shifu'), ('Kasha'), ('Higanbana'),
('Hakaze'), ('Jinpu'), ('Gekko'), ('Higanbana'),
('Hakaze'), ('Shifu')]
df5_no_tenka, average_potency, pps = sam.parse_rotation(actions, n_targets=n_targets)
display(df5_no_tenka)
average potency per GCD = 310.11666666666656
average potency per second = 142.691717791
Time | Weaponskill | Ability | Potency | Jinpu | Shifu | Yukikaze | Higanbana | Kenki | Total Potency | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 0.00 | Hakaze | 150.00 | False | False | False | 0 | 0 | 150.00 | |
1 | 2.40 | Shifu | 280.00 | False | False | False | 0 | 0 | 430.00 | |
2 | 4.56 | Kasha | 400.00 | False | True | False | 0 | 0 | 830.00 | |
3 | 6.72 | Higanbana | 240.00 | False | True | False | 0 | 0 | 1070.00 | |
4 | 8.88 | Hakaze | 175.20 | False | True | False | 1 | 0 | 1245.20 | |
5 | 11.04 | Jinpu | 305.20 | False | True | False | 1 | 0 | 1550.40 | |
6 | 13.20 | Gekko | 485.20 | True | True | False | 1 | 0 | 2035.60 | |
7 | 15.36 | Higanbana | 301.20 | True | True | False | 1 | 0 | 2336.80 | |
8 | 17.52 | Hakaze | 201.48 | True | True | False | 1 | 0 | 2538.28 | |
9 | 19.68 | Shifu | 350.98 | True | True | False | 1 | 0 | 2889.26 | |
10 | 21.84 | Kasha | 488.98 | True | True | False | 1 | 0 | 3378.24 | |
11 | 24.00 | Higanbana | 304.98 | True | True | False | 1 | 0 | 3683.22 | |
12 | 26.16 | Hakaze | 201.48 | True | True | False | 1 | 0 | 3884.70 | |
13 | 28.32 | Jinpu | 350.98 | True | True | False | 1 | 0 | 4235.68 | |
14 | 30.48 | Gekko | 488.98 | True | True | False | 1 | 0 | 4724.66 | |
15 | 32.64 | Higanbana | 304.98 | True | True | False | 1 | 0 | 5029.64 | |
16 | 34.80 | Hakaze | 201.48 | True | True | False | 1 | 0 | 5231.12 | |
17 | 36.96 | Shifu | 350.98 | True | True | False | 1 | 0 | 5582.10 |
compare_potencies([df5_no_tenka, df5_tenka], ['Higanbana only', 'With Tenka Goken'])
It’s surprisingly close! I would favor using Tenka Goken since it’s fresh though.
With the addition of a second third-level combo finisher plus Tenka Goken, do we want to move away from the AoE weaponskill rotation in favor of a single target one for the standard three mob pull?
sam = Samurai()
n_targets = 3
actions = [('Hakaze'), ('Shifu'), ('Kasha'), ('Higanbana'),
('Hakaze'), ('Jinpu'), ('Gekko'), ('Higanbana'),
('Hakaze'), ('Shifu'), ('Kasha'), ('Hakaze'),
('Jinpu'), ('Gekko'), ('Tenka Goken')]
df6_higanbana, average_potency, pps = sam.parse_rotation(actions, n_targets=n_targets)
display(df6_higanbana)
average potency per GCD = 382.85733333333326
average potency per second = 175.945465686
Time | Weaponskill | Ability | Potency | Jinpu | Shifu | Yukikaze | Higanbana | Kenki | Total Potency | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 0.00 | Hakaze | 150.00 | False | False | False | 0 | 0 | 150.00 | |
1 | 2.40 | Shifu | 280.00 | False | False | False | 0 | 0 | 430.00 | |
2 | 4.56 | Kasha | 400.00 | False | True | False | 0 | 0 | 830.00 | |
3 | 6.72 | Higanbana | 240.00 | False | True | False | 0 | 0 | 1070.00 | |
4 | 8.88 | Hakaze | 175.20 | False | True | False | 1 | 0 | 1245.20 | |
5 | 11.04 | Jinpu | 305.20 | False | True | False | 1 | 0 | 1550.40 | |
6 | 13.20 | Gekko | 485.20 | True | True | False | 1 | 0 | 2035.60 | |
7 | 15.36 | Higanbana | 301.20 | True | True | False | 1 | 0 | 2336.80 | |
8 | 17.52 | Hakaze | 226.68 | True | True | False | 2 | 0 | 2563.48 | |
9 | 19.68 | Shifu | 376.18 | True | True | False | 2 | 0 | 2939.66 | |
10 | 21.84 | Kasha | 514.18 | True | True | False | 2 | 0 | 3453.84 | |
11 | 24.00 | Hakaze | 226.68 | True | True | False | 2 | 0 | 3680.52 | |
12 | 26.16 | Jinpu | 376.18 | True | True | False | 2 | 0 | 4056.70 | |
13 | 28.32 | Gekko | 514.18 | True | True | False | 2 | 0 | 4570.88 | |
14 | 30.48 | Tenka Goken | 1171.98 | True | True | False | 2 | 0 | 5742.86 |
sam = Samurai()
n_targets = 3
actions = [('Hakaze'), ('Shifu'), ('Kasha'), ('Hakaze'),
('Jinpu'), ('Gekko'), ('Tenka Goken'), ('Hakaze'),
('Shifu'), ('Kasha'), ('Hakaze'), ('Jinpu'),
('Gekko'), ('Tenka Goken'), ('Hakaze')]
df6_tenka_only, average_potency, pps = sam.parse_rotation(actions, n_targets=n_targets)
display(df6_tenka_only)
average potency per GCD = 402.47333333333336
average potency per second = 184.960171569
Time | Weaponskill | Ability | Potency | Jinpu | Shifu | Yukikaze | Higanbana | Kenki | Total Potency | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 0.00 | Hakaze | 150.0 | False | False | False | 0 | 0 | 150.0 | |
1 | 2.40 | Shifu | 280.0 | False | False | False | 0 | 0 | 430.0 | |
2 | 4.56 | Kasha | 400.0 | False | True | False | 0 | 0 | 830.0 | |
3 | 6.72 | Hakaze | 150.0 | False | True | False | 0 | 0 | 980.0 | |
4 | 8.88 | Jinpu | 280.0 | False | True | False | 0 | 0 | 1260.0 | |
5 | 11.04 | Gekko | 460.0 | True | True | False | 0 | 0 | 1720.0 | |
6 | 13.20 | Tenka Goken | 1117.8 | True | True | False | 0 | 0 | 2837.8 | |
7 | 15.36 | Hakaze | 172.5 | True | True | False | 0 | 0 | 3010.3 | |
8 | 17.52 | Shifu | 322.0 | True | True | False | 0 | 0 | 3332.3 | |
9 | 19.68 | Kasha | 460.0 | True | True | False | 0 | 0 | 3792.3 | |
10 | 21.84 | Hakaze | 172.5 | True | True | False | 0 | 0 | 3964.8 | |
11 | 24.00 | Jinpu | 322.0 | True | True | False | 0 | 0 | 4286.8 | |
12 | 26.16 | Gekko | 460.0 | True | True | False | 0 | 0 | 4746.8 | |
13 | 28.32 | Tenka Goken | 1117.8 | True | True | False | 0 | 0 | 5864.6 | |
14 | 30.48 | Hakaze | 172.5 | True | True | False | 0 | 0 | 6037.1 |
compare_potencies([df6_tenka_only, df6_higanbana], ['Tenka Goken only', 'Higanbana two targets first'])
Although close, both of these rotation potencies are inferior compared to the previous AoE rotations, even they were without Tenka Goken. However, we can open Getsu using the Mangetsu combo and open Ka using the Kasha combo. Maybe that works better?
sam = Samurai()
n_targets = 3
actions = [('Hakaze'), ('Shifu'), ('Kasha'), ('Higanbana'),
('Hakaze'), ('Jinpu'), ('Gekko'), ('Higanbana'),
('Hakaze'), ('Shifu'), ('Kasha'), ('Fuga'),
('Mangetsu'), ('Tenka Goken'), ('Fuga'), ('Mangetsu'),
('Hakaze'), ('Shifu'), ('Kasha'), ('Tenka Goken')]
df6_aoe_higanbana2, average_potency, pps = sam.parse_rotation(actions, n_targets=n_targets)
display(df6_aoe_higanbana2)
average potency per GCD = 453.178
average potency per second = 208.645488029
Time | Weaponskill | Ability | Potency | Jinpu | Shifu | Yukikaze | Higanbana | Kenki | Total Potency | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 0.00 | Hakaze | 150.00 | False | False | False | 0 | 0 | 150.00 | |
1 | 2.40 | Shifu | 280.00 | False | False | False | 0 | 0 | 430.00 | |
2 | 4.56 | Kasha | 400.00 | False | True | False | 0 | 0 | 830.00 | |
3 | 6.72 | Higanbana | 240.00 | False | True | False | 0 | 0 | 1070.00 | |
4 | 8.88 | Hakaze | 175.20 | False | True | False | 1 | 0 | 1245.20 | |
5 | 11.04 | Jinpu | 305.20 | False | True | False | 1 | 0 | 1550.40 | |
6 | 13.20 | Gekko | 485.20 | True | True | False | 1 | 0 | 2035.60 | |
7 | 15.36 | Higanbana | 301.20 | True | True | False | 1 | 0 | 2336.80 | |
8 | 17.52 | Hakaze | 226.68 | True | True | False | 2 | 0 | 2563.48 | |
9 | 19.68 | Shifu | 376.18 | True | True | False | 2 | 0 | 2939.66 | |
10 | 21.84 | Kasha | 514.18 | True | True | False | 2 | 0 | 3453.84 | |
11 | 24.00 | Fuga | 399.18 | True | True | False | 2 | 0 | 3853.02 | |
12 | 26.16 | Mangetsu | 675.18 | True | True | False | 2 | 0 | 4528.20 | |
13 | 28.32 | Tenka Goken | 1171.98 | True | True | False | 2 | 0 | 5700.18 | |
14 | 30.48 | Fuga | 399.18 | True | True | False | 2 | 0 | 6099.36 | |
15 | 32.64 | Mangetsu | 675.18 | True | True | False | 2 | 0 | 6774.54 | |
16 | 34.80 | Hakaze | 226.68 | True | True | False | 2 | 0 | 7001.22 | |
17 | 36.96 | Shifu | 376.18 | True | True | False | 2 | 0 | 7377.40 | |
18 | 39.12 | Kasha | 514.18 | True | True | False | 2 | 0 | 7891.58 | |
19 | 41.28 | Tenka Goken | 1171.98 | False | True | False | 2 | 0 | 9063.56 |
sam = Samurai()
n_targets = 3
actions = [('Hakaze'), ('Shifu'), ('Kasha'), ('Hakaze'),
('Jinpu'), ('Gekko'), ('Tenka Goken'), ('Hakaze'),
('Shifu'), ('Kasha'), ('Fuga'), ('Mangetsu'),
('Tenka Goken'), ('Hakaze'), ('Shifu'), ('Kasha'),
('Fuga'), ('Mangetsu'), ('Tenka Goken'), ('Hakaze')]
df6_aoe_tenka_only, average_potency, pps = sam.parse_rotation(actions, n_targets=n_targets)
display(df6_aoe_tenka_only)
average potency per GCD = 454.34499999999997
average potency per second = 209.182780847
Time | Weaponskill | Ability | Potency | Jinpu | Shifu | Yukikaze | Higanbana | Kenki | Total Potency | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 0.00 | Hakaze | 150.0 | False | False | False | 0 | 0 | 150.0 | |
1 | 2.40 | Shifu | 280.0 | False | False | False | 0 | 0 | 430.0 | |
2 | 4.56 | Kasha | 400.0 | False | True | False | 0 | 0 | 830.0 | |
3 | 6.72 | Hakaze | 150.0 | False | True | False | 0 | 0 | 980.0 | |
4 | 8.88 | Jinpu | 280.0 | False | True | False | 0 | 0 | 1260.0 | |
5 | 11.04 | Gekko | 460.0 | True | True | False | 0 | 0 | 1720.0 | |
6 | 13.20 | Tenka Goken | 1117.8 | True | True | False | 0 | 0 | 2837.8 | |
7 | 15.36 | Hakaze | 172.5 | True | True | False | 0 | 0 | 3010.3 | |
8 | 17.52 | Shifu | 322.0 | True | True | False | 0 | 0 | 3332.3 | |
9 | 19.68 | Kasha | 460.0 | True | True | False | 0 | 0 | 3792.3 | |
10 | 21.84 | Fuga | 345.0 | True | True | False | 0 | 0 | 4137.3 | |
11 | 24.00 | Mangetsu | 621.0 | True | True | False | 0 | 0 | 4758.3 | |
12 | 26.16 | Tenka Goken | 1117.8 | True | True | False | 0 | 0 | 5876.1 | |
13 | 28.32 | Hakaze | 172.5 | True | True | False | 0 | 0 | 6048.6 | |
14 | 30.48 | Shifu | 322.0 | True | True | False | 0 | 0 | 6370.6 | |
15 | 32.64 | Kasha | 460.0 | True | True | False | 0 | 0 | 6830.6 | |
16 | 34.80 | Fuga | 345.0 | True | True | False | 0 | 0 | 7175.6 | |
17 | 36.96 | Mangetsu | 621.0 | True | True | False | 0 | 0 | 7796.6 | |
18 | 39.12 | Tenka Goken | 1117.8 | False | True | False | 0 | 0 | 8914.4 | |
19 | 41.28 | Hakaze | 172.5 | False | True | False | 0 | 0 | 9086.9 |
compare_potencies([df6_aoe_tenka_only, df6_aoe_higanbana2], ['Tenka Goken only', 'Higanbana two targets first'])
They’re virtually equal, but applying Higanbana twice takes more time to pay off. Using Tenka Goken only is probably better in most cases. Although the inclusion of the AoE weaponskills will scale better with larger pulls, TP sustainability is a concern. As the number of targets dwindles down to 3, it may be better to favor rotations with single target weaponskills.
Thankfully, level 45 introduces the Oka AoE combo (combo from Fuga). This finisher is equal in potency to the Mangetsu finisher, but similarly to Kasha for single target, opens the Ka Sen instead. This opens the AoE rotation of alternating combos to open Ka and Getsu in order to use Tenka Goken. While this is definitely TP unfriendly, it should scale very well with mob size.
dfs_aoe2 = []
pps_aoe2 = []
labels = []
n_target_range = range(2, 8)
for n_targets in n_target_range:
sam = Samurai()
actions = [('Hakaze'), ('Shifu'), ('Kasha'), ('Hakaze'),
('Jinpu'), ('Gekko'), ('Tenka Goken'), ('Fuga'),
('Oka'), ('Fuga'), ('Mangetsu'), ('Tenka Goken'),
('Fuga'), ('Mangetsu'), ('Fuga'), ('Oka'),
('Tenka Goken')]
print('number of targets = %s' % n_targets)
df_temp, average_potency, pps = sam.parse_rotation(actions, n_targets=n_targets)
dfs_aoe2.append(df_temp)
pps_aoe2.append(pps)
labels.append('%s targets' % n_targets)
print('\n')
number of targets = 2
average potency per GCD = 396.92941176470583
average potency per second = 182.57034632
number of targets = 3
average potency per GCD = 525.7294117647059
average potency per second = 241.812770563
number of targets = 4
average potency per GCD = 641.8117647058824
average potency per second = 295.205627706
number of targets = 5
average potency per GCD = 745.1764705882352
average potency per second = 342.748917749
number of targets = 6
average potency per GCD = 835.8235294117648
average potency per second = 384.442640693
number of targets = 7
average potency per GCD = 926.4705882352941
average potency per second = 426.136363636
compare_n_potencies(dfs_aoe2, labels)
fig, axes = plt.subplots(nrows=1, ncols=1, sharex=True, figsize=(12,4))
fig.tight_layout(pad=2)
axes.plot(n_target_range, pps_aoe2, '-o', label='Mangetsu, Oka, and Tenka Goken')
axes.plot(n_target_range, pps_higanbana, '-^', label='Mangetsu and Higanbana only')
axes.plot(n_target_range, pps_no_higanbana, ':^', label='Mangetsu only')
axes.set_ylabel('Potency per second')
axes.set_xlabel('Number of Targets')
axes.legend(loc='upper left', framealpha=0.5)
fig.suptitle('Average Potency per second')
<matplotlib.text.Text at 0x19c86f4bb38>
At 3 targets, the potency of a full duration Higanbana is comparable to Tenka Goken, so applying Higanbana to some targets has merit (especially due to its 1 Sen cost). However, the AoE-centric rotation scales exceptionally well as pull size passes 3. The ability to open up Getsu and Ka with only four GCDs allowing for more frequent Tenka Goken casts facilitates that.
For a pull size of three:
sam = Samurai()
n_targets = 3
actions = [('Hakaze'), ('Shifu'), ('Kasha'), ('Higanbana'),
('Hakaze'), ('Jinpu'), ('Gekko'), ('Higanbana'),
('Fuga'), ('Oka'), ('Fuga'), ('Mangetsu'),
('Tenka Goken'), ('Fuga'), ('Mangetsu'), ('Fuga'),
('Oka'), ('Tenka Goken')]
df7_3, average_potency, pps = sam.parse_rotation(actions, n_targets=n_targets)
display(df7_3)
average potency per GCD = 498.78888888888895
average potency per second = 229.50408998
Time | Weaponskill | Ability | Potency | Jinpu | Shifu | Yukikaze | Higanbana | Kenki | Total Potency | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 0.00 | Hakaze | 150.00 | False | False | False | 0 | 0 | 150.00 | |
1 | 2.40 | Shifu | 280.00 | False | False | False | 0 | 0 | 430.00 | |
2 | 4.56 | Kasha | 400.00 | False | True | False | 0 | 0 | 830.00 | |
3 | 6.72 | Higanbana | 240.00 | False | True | False | 0 | 0 | 1070.00 | |
4 | 8.88 | Hakaze | 175.20 | False | True | False | 1 | 0 | 1245.20 | |
5 | 11.04 | Jinpu | 305.20 | False | True | False | 1 | 0 | 1550.40 | |
6 | 13.20 | Gekko | 485.20 | True | True | False | 1 | 0 | 2035.60 | |
7 | 15.36 | Higanbana | 301.20 | True | True | False | 1 | 0 | 2336.80 | |
8 | 17.52 | Fuga | 399.18 | True | True | False | 2 | 0 | 2735.98 | |
9 | 19.68 | Oka | 675.18 | True | True | False | 2 | 0 | 3411.16 | |
10 | 21.84 | Fuga | 399.18 | True | True | False | 2 | 0 | 3810.34 | |
11 | 24.00 | Mangetsu | 675.18 | True | True | False | 2 | 0 | 4485.52 | |
12 | 26.16 | Tenka Goken | 1171.98 | True | True | False | 2 | 0 | 5657.50 | |
13 | 28.32 | Fuga | 399.18 | True | True | False | 2 | 0 | 6056.68 | |
14 | 30.48 | Mangetsu | 675.18 | True | True | False | 2 | 0 | 6731.86 | |
15 | 32.64 | Fuga | 399.18 | True | False | False | 2 | 0 | 7131.04 | |
16 | 34.80 | Oka | 675.18 | True | False | False | 2 | 0 | 7806.22 | |
17 | 36.96 | Tenka Goken | 1171.98 | True | False | False | 2 | 0 | 8978.20 |
compare_potencies([df7_3, dfs_aoe2[1]], labels=['Higanbana two first', 'Tenka Goken only'])
Once again, Higanbana takes some time to pay off. For pulls reaching the 60 second mark, it may be optimal, especially if we consider that targets start to die, reducing the advantage of Tenka Goken only.
Up to this point, Samurai has no abilities or offensive cooldowns that are used in its regular rotation, save for Ageha. The main themes are always keeping buffs up and making use of Iaijutsu as regularly as you can. Samurai has strong AoE although it is expensive to use. From level 50 going forward, Samurai picks up all of its abilities and at level 52, the Kenki gauge and Hissatsu abilities start to be introduced. Once you master the weaponskill rotation that is completed at level 50, you will need to start learning to manage Kenki and use the Kenki spenders efficiently to become a good samurai.