Skip to content

Commit

Permalink
WAR L100 support & don't auto turn off recording if it was turned on …
Browse files Browse the repository at this point in the history
…manually.
  • Loading branch information
awgil committed Jul 8, 2024
1 parent e0504bc commit 2af570e
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 51 deletions.
99 changes: 58 additions & 41 deletions BossMod/ActionQueue/Tanks/WAR.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,48 +5,51 @@ public enum AID : uint
None = 0,
Sprint = ClassShared.AID.Sprint,

LandWaker = 4240, // LB3, instant, range 0, AOE 50 circle, targets=self, animLock=3.860
HeavySwing = 31, // L1, instant, GCD, range 3, single-target, targets=hostile
Maim = 37, // L4, instant, GCD, range 3, single-target, targets=hostile
Berserk = 38, // L6, instant, 60.0s CD (group 10), range 0, single-target, targets=self
Overpower = 41, // L10, instant, GCD, range 0, AOE 5 circle, targets=self
Defiance = 48, // L10, instant, 2.0s CD (group 2), range 0, single-target, targets=self
ReleaseDefiance = 32066, // L10, instant, 1.0s CD (group 2), range 0, single-target, targets=self
Tomahawk = 46, // L15, instant, GCD, range 20, single-target, targets=hostile
StormPath = 42, // L26, instant, GCD, range 3, single-target, targets=hostile
ThrillOfBattle = 40, // L30, instant, 90.0s CD (group 16), range 0, single-target, targets=self
InnerBeast = 49, // L35, instant, GCD, range 3, single-target, targets=hostile
Vengeance = 44, // L38, instant, 120.0s CD (group 21), range 0, single-target, targets=self
MythrilTempest = 16462, // L40, instant, GCD, range 0, AOE 5 circle, targets=self
Holmgang = 43, // L42, instant, 240.0s CD (group 23), range 6, single-target, targets=self/hostile
SteelCyclone = 51, // L45, instant, GCD, range 0, AOE 5 circle, targets=self
StormEye = 45, // L50, instant, GCD, range 3, single-target, targets=hostile
Infuriate = 52, // L50, instant, 60.0s CD (group 19/70) (2 charges), range 0, single-target, targets=self
FellCleave = 3549, // L54, instant, GCD, range 3, single-target, targets=hostile
RawIntuition = 3551, // L56, instant, 25.0s CD (group 3), range 0, single-target, targets=self
Equilibrium = 3552, // L58, instant, 60.0s CD (group 14), range 0, single-target, targets=self
Decimate = 3550, // L60, instant, GCD, range 0, AOE 5 circle, targets=self
Onslaught = 7386, // L62, instant, 30.0s CD (group 9/71) (2-3 charges), range 20, single-target, targets=hostile
Upheaval = 7387, // L64, instant, 30.0s CD (group 5), range 3, single-target, targets=hostile
ShakeItOff = 7388, // L68, instant, 90.0s CD (group 17), range 0, AOE 30 circle, targets=self
InnerRelease = 7389, // L70, instant, 60.0s CD (group 11), range 0, single-target, targets=self
ChaoticCyclone = 16463, // L72, instant, GCD, range 0, AOE 5 circle, targets=self
NascentFlash = 16464, // L76, instant, 25.0s CD (group 3), range 30, single-target, targets=party
InnerChaos = 16465, // L80, instant, GCD, range 3, single-target, targets=hostile
Bloodwhetting = 25751, // L82, instant, 25.0s CD (group 3), range 0, single-target, targets=self
Orogeny = 25752, // L86, instant, 30.0s CD (group 5), range 0, AOE 5 circle, targets=self
PrimalRend = 25753, // L90, instant, GCD, range 20, AOE 5 circle, targets=hostile, animLock=1.150
LandWaker = 4240, // LB3, instant, range 0, AOE 50 circle, targets=Self, animLock=3.860
HeavySwing = 31, // L1, instant, GCD, range 3, single-target, targets=Hostile
Maim = 37, // L4, instant, GCD, range 3, single-target, targets=Hostile
Berserk = 38, // L6, instant, 60.0s CD (group 10), range 0, single-target, targets=Self
Overpower = 41, // L10, instant, GCD, range 0, AOE 5 circle, targets=Self
Defiance = 48, // L10, instant, 2.0s CD (group 1), range 0, single-target, targets=Self
ReleaseDefiance = 32066, // L10, instant, 1.0s CD (group 1), range 0, single-target, targets=Self
Tomahawk = 46, // L15, instant, GCD, range 20, single-target, targets=Hostile
StormPath = 42, // L26, instant, GCD, range 3, single-target, targets=Hostile
ThrillOfBattle = 40, // L30, instant, 90.0s CD (group 15), range 0, single-target, targets=Self
InnerBeast = 49, // L35, instant, GCD, range 3, single-target, targets=Hostile
Vengeance = 44, // L38, instant, 120.0s CD (group 21), range 0, single-target, targets=Self
MythrilTempest = 16462, // L40, instant, GCD, range 0, AOE 5 circle, targets=Self
Holmgang = 43, // L42, instant, 240.0s CD (group 24), range 6, single-target, targets=Self/Hostile
SteelCyclone = 51, // L45, instant, GCD, range 0, AOE 5 circle, targets=Self
StormEye = 45, // L50, instant, GCD, range 3, single-target, targets=Hostile
Infuriate = 52, // L50, instant, 60.0s CD (group 19/70) (2 charges), range 0, single-target, targets=Self
FellCleave = 3549, // L54, instant, GCD, range 3, single-target, targets=Hostile
RawIntuition = 3551, // L56, instant, 25.0s CD (group 6), range 0, single-target, targets=Self
Equilibrium = 3552, // L58, instant, 60.0s CD (group 13), range 0, single-target, targets=Self
Decimate = 3550, // L60, instant, GCD, range 0, AOE 5 circle, targets=Self
Onslaught = 7386, // L62, instant, 30.0s CD (group 7/71) (2-3 charges), range 20, single-target, targets=Hostile
Upheaval = 7387, // L64, instant, 30.0s CD (group 8), range 3, single-target, targets=Hostile
ShakeItOff = 7388, // L68, instant, 90.0s CD (group 14), range 0, AOE 30 circle, targets=Self
InnerRelease = 7389, // L70, instant, 60.0s CD (group 11), range 0, single-target, targets=Self
ChaoticCyclone = 16463, // L72, instant, GCD, range 0, AOE 5 circle, targets=Self
NascentFlash = 16464, // L76, instant, 25.0s CD (group 6), range 30, single-target, targets=Party
InnerChaos = 16465, // L80, instant, GCD, range 3, single-target, targets=Hostile
Bloodwhetting = 25751, // L82, instant, 25.0s CD (group 6), range 0, single-target, targets=Self
Orogeny = 25752, // L86, instant, 30.0s CD (group 8), range 0, AOE 5 circle, targets=Self
PrimalRend = 25753, // L90, instant, GCD, range 20, AOE 5 circle, targets=Hostile, animLock=1.150
Damnation = 36923, // L92, instant, 120.0s CD (group 21), range 0, single-target, targets=Self
PrimalWrath = 36924, // L96, instant, 1.0s CD (group 0), range 0, AOE 5 circle, targets=Self
PrimalRuination = 36925, // L100, instant, GCD, range 3, AOE 5 circle, targets=Hostile

// Shared
ShieldWall = ClassShared.AID.ShieldWall, // LB1, instant, range 0, AOE 50 circle, targets=self, animLock=1.930
Stronghold = ClassShared.AID.Stronghold, // LB2, instant, range 0, AOE 50 circle, targets=self, animLock=3.860
Rampart = ClassShared.AID.Rampart, // L8, instant, 90.0s CD (group 46), range 0, single-target, targets=self
LowBlow = ClassShared.AID.LowBlow, // L12, instant, 25.0s CD (group 41), range 3, single-target, targets=hostile
Provoke = ClassShared.AID.Provoke, // L15, instant, 30.0s CD (group 42), range 25, single-target, targets=hostile
Interject = ClassShared.AID.Interject, // L18, instant, 30.0s CD (group 43), range 3, single-target, targets=hostile
Reprisal = ClassShared.AID.Reprisal, // L22, instant, 60.0s CD (group 44), range 0, AOE 5 circle, targets=self
ArmsLength = ClassShared.AID.ArmsLength, // L32, instant, 120.0s CD (group 48), range 0, single-target, targets=self
Shirk = ClassShared.AID.Shirk, // L48, instant, 120.0s CD (group 49), range 25, single-target, targets=party
ShieldWall = ClassShared.AID.ShieldWall, // LB1, instant, range 0, AOE 50 circle, targets=Self, animLock=1.930
Stronghold = ClassShared.AID.Stronghold, // LB2, instant, range 0, AOE 50 circle, targets=Self, animLock=3.860
Rampart = ClassShared.AID.Rampart, // L8, instant, 90.0s CD (group 46), range 0, single-target, targets=Self
LowBlow = ClassShared.AID.LowBlow, // L12, instant, 25.0s CD (group 41), range 3, single-target, targets=Hostile
Provoke = ClassShared.AID.Provoke, // L15, instant, 30.0s CD (group 42), range 25, single-target, targets=Hostile
Interject = ClassShared.AID.Interject, // L18, instant, 30.0s CD (group 43), range 3, single-target, targets=Hostile
Reprisal = ClassShared.AID.Reprisal, // L22, instant, 60.0s CD (group 44), range 0, AOE 5 circle, targets=Self
ArmsLength = ClassShared.AID.ArmsLength, // L32, instant, 120.0s CD (group 48), range 0, single-target, targets=Self
Shirk = ClassShared.AID.Shirk, // L48, instant, 120.0s CD (group 49), range 25, single-target, targets=Party
}

public enum TraitID : uint
Expand All @@ -65,8 +68,14 @@ public enum TraitID : uint
RawIntuitionMastery = 418, // L82, raw intuition -> bloodwhetting
EnhancedNascentFlash = 419, // L82, duration increase
EnhancedEquilibrium = 420, // L84, adds hot
MeleeMastery = 505, // L84, potency increase
MeleeMastery1 = 505, // L84, potency increase
EnhancedOnslaught = 421, // L88, 3rd onslaught charge
VengeanceMastery = 567, // L92
EnhancedRampart = 639, // L94
MeleeMastery2 = 654, // L94
EnhancedInnerRelease = 568, // L96
EnhancedReprisal = 640, // L98
EnhancedPrimalRend = 569, // L100
}

public enum SID : uint
Expand All @@ -78,8 +87,13 @@ public enum SID : uint
InnerRelease = 1177, // applied by Inner Release to self, next 3 GCDs should be free FCs
PrimalRend = 2624, // applied by Inner Release to self, allows casting PR
InnerStrength = 2663, // applied by Inner Release to self, immunes
BurgeoningFury = 3833, // applied by Fell Cleave to self, 3 stacks turns into wrathful
Wrathful = 3901, // 3rd stack of Burgeoning Fury turns into this, allows Primal Wrath
PrimalRuinationReady = 3834, // applied by Primal Rend to self
VengeanceRetaliation = 89, // applied by Vengeance to self, retaliation for physical attacks
VengeanceDefense = 912, // applied by Vengeance to self, -30% damage taken
Damnation = 3832, // applied by Damnation to self, -40% damage taken and retaliation for physical attacks
PrimevalImpulse = 3900, // hot applied after hit under Damnation
Rampart = 1191, // applied by Rampart to self, -20% damage taken
ThrillOfBattle = 87, // applied by Thrill of Battle to self
Holmgang = 409, // applied by Holmgang to self
Expand Down Expand Up @@ -138,6 +152,9 @@ public Definitions(ActionDefinitions d)
d.RegisterSpell(AID.Bloodwhetting);
d.RegisterSpell(AID.Orogeny);
d.RegisterSpell(AID.PrimalRend, instantAnimLock: 1.15f);
d.RegisterSpell(AID.Damnation);
d.RegisterSpell(AID.PrimalWrath);
d.RegisterSpell(AID.PrimalRuination);

Customize(d);
}
Expand Down
24 changes: 21 additions & 3 deletions BossMod/Autorotation/Legacy/LegacyWAR.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ public class State(RotationModule module) : CommonState(module)
public float SurgingTempestLeft; // 0 if buff not up, max 60
public float NascentChaosLeft; // 0 if buff not up, max 30
public float PrimalRendLeft; // 0 if buff not up, max 30
public float PrimalRuinationLeft; // 0 if buff not up, max 30
public float WrathfulLeft; // 0 if buff not up, max 30
public float InnerReleaseLeft; // 0 if buff not up, max 15
public int InnerReleaseStacks; // 0 if buff not up, max 3

Expand All @@ -109,7 +111,7 @@ public class State(RotationModule module) : CommonState(module)

public override string ToString()
{
return $"g={Gauge}, RB={RaidBuffsLeft:f1}, ST={SurgingTempestLeft:f1}, NC={NascentChaosLeft:f1}, PR={PrimalRendLeft:f1}, IR={InnerReleaseStacks}/{InnerReleaseLeft:f1}, IRCD={CD(WAR.AID.Berserk):f1}/{CD(WAR.AID.InnerRelease):f1}, InfCD={CD(WAR.AID.Infuriate):f1}, UphCD={CD(WAR.AID.Upheaval):f1}, OnsCD={CD(WAR.AID.Onslaught):f1}, PotCD={PotionCD:f1}, GCD={GCD:f3}, ALock={AnimationLock:f3}+{AnimationLockDelay:f3}, lvl={Level}";
return $"g={Gauge}, RB={RaidBuffsLeft:f1}, ST={SurgingTempestLeft:f1}, NC={NascentChaosLeft:f1}, PR={PrimalRendLeft:f1}/{PrimalRuinationLeft:f1}, IR={InnerReleaseStacks}/{InnerReleaseLeft:f1}/{WrathfulLeft:f1}, IRCD={CD(WAR.AID.Berserk):f1}/{CD(WAR.AID.InnerRelease):f1}, InfCD={CD(WAR.AID.Infuriate):f1}, UphCD={CD(WAR.AID.Upheaval):f1}, OnsCD={CD(WAR.AID.Onslaught):f1}, PotCD={PotionCD:f1}, GCD={GCD:f3}, ALock={AnimationLock:f3}+{AnimationLockDelay:f3}, lvl={Level}";
}
}

Expand All @@ -129,6 +131,8 @@ public override void Execute(StrategyValues strategy, Actor? primaryTarget)
_state.SurgingTempestLeft = _state.StatusDetails(Player, WAR.SID.SurgingTempest, Player.InstanceID).Left;
_state.NascentChaosLeft = _state.StatusDetails(Player, WAR.SID.NascentChaos, Player.InstanceID).Left;
_state.PrimalRendLeft = _state.StatusDetails(Player, WAR.SID.PrimalRend, Player.InstanceID).Left;
_state.PrimalRuinationLeft = _state.StatusDetails(Player, WAR.SID.PrimalRuinationReady, Player.InstanceID).Left;
_state.WrathfulLeft = _state.StatusDetails(Player, WAR.SID.Wrathful, Player.InstanceID).Left;
(_state.InnerReleaseLeft, _state.InnerReleaseStacks) = _state.StatusDetails(Player, _state.Unlocked(WAR.AID.InnerRelease) ? WAR.SID.InnerRelease : WAR.SID.Berserk, Player.InstanceID);

var aoe = strategy.Option(Track.AOE).As<AOEStrategy>() switch
Expand Down Expand Up @@ -469,6 +473,7 @@ private WAR.AID GetNextBestGCD(StrategyValues strategy, bool aoe)

// forbid automatic PR when out of melee range, to avoid fucking up player positioning when avoiding mechanics
float primalRendWindow = (strategyPR == OffensiveStrategy.Delay || _state.RangeToTarget > 3) ? 0 : MathF.Min(_state.PrimalRendLeft, _state.PositionLockIn);
float primalRuinationWindow = _state.PrimalRuinationLeft; // TODO: reconsider
var irCD = _state.CD(_state.Unlocked(WAR.AID.InnerRelease) ? WAR.AID.InnerRelease : WAR.AID.Berserk);

bool spendGauge = ShouldSpendGauge(strategyGCD, aoe);
Expand All @@ -482,6 +487,8 @@ private WAR.AID GetNextBestGCD(StrategyValues strategy, bool aoe)
float thirdGCDIn = gcdDelay + 5f;
if (primalRendWindow > _state.GCD && primalRendWindow < secondGCDIn)
return WAR.AID.PrimalRend;
if (primalRuinationWindow > _state.GCD && primalRuinationWindow < secondGCDIn)
return WAR.AID.PrimalRuination; // TODO: reconsider
if (_state.NascentChaosLeft > _state.GCD && _state.NascentChaosLeft < secondGCDIn)
return GetNextFCAction(aoe);
if (primalRendWindow > _state.GCD && _state.NascentChaosLeft > _state.GCD && primalRendWindow < thirdGCDIn && _state.NascentChaosLeft < thirdGCDIn)
Expand All @@ -499,9 +506,12 @@ private WAR.AID GetNextBestGCD(StrategyValues strategy, bool aoe)
if (_state.InnerReleaseLeft <= _state.GCD + fcCastsLeft * 2.5f)
return GetNextFCAction(aoe);

// don't delay if it won't give us anything (but still prefer PR under buffs)
// don't delay if it won't give us anything (but still prefer PR under buffs) - TODO: reconsider...
if (spendGauge || _state.InnerReleaseLeft <= _state.RaidBuffsIn)
return primalRendWindow > _state.GCD && spendGauge ? WAR.AID.PrimalRend : GetNextFCAction(aoe);
return !spendGauge ? GetNextFCAction(aoe)
: primalRendWindow > _state.GCD ? WAR.AID.PrimalRend
: primalRuinationWindow > _state.GCD ? WAR.AID.PrimalRuination
: GetNextFCAction(aoe);

// don't delay FC if it can cause infuriate overcap (e.g. we use combo action, gain gauge and then can't spend it in time)
if (_state.CD(WAR.AID.Infuriate) < _state.GCD + (_state.InnerReleaseStacks + 1) * 7.5f)
Expand Down Expand Up @@ -541,6 +551,8 @@ private WAR.AID GetNextBestGCD(StrategyValues strategy, bool aoe)
// 6. if there is no chance we can delay PR until next raid buffs, just cast it now
if (primalRendWindow > _state.GCD && primalRendWindow <= _state.RaidBuffsIn)
return WAR.AID.PrimalRend;
if (primalRuinationWindow > _state.GCD && primalRuinationWindow <= _state.RaidBuffsIn)
return WAR.AID.PrimalRuination;

// TODO: do not spend gauge if we're delaying berserk
if (!spendGauge)
Expand All @@ -555,6 +567,8 @@ private WAR.AID GetNextBestGCD(StrategyValues strategy, bool aoe)
// ok at this point, we just want to spend gauge - either because we're using greedy strategy, or something prevented us from casting combo
if (primalRendWindow > _state.GCD)
return WAR.AID.PrimalRend;
if (primalRuinationWindow > _state.GCD)
return WAR.AID.PrimalRuination;
if (canUseFC)
return GetNextFCAction(aoe);

Expand Down Expand Up @@ -606,6 +620,10 @@ private ActionID GetNextBestOGCD(StrategyValues strategy, float deadline, bool a
if (wantOnslaught && _state.CanWeave(_state.CD(WAR.AID.Onslaught) - 60, onslaughtHeadroom ? 0.8f : 0.6f, deadline))
return ActionID.MakeSpell(WAR.AID.Onslaught);

// 6. primal wrath (TODO: reconsider)
if (_state.WrathfulLeft > _state.AnimationLock && Player.InCombat && _state.CanWeave(WAR.AID.PrimalWrath, 0.6f, deadline))
return ActionID.MakeSpell(WAR.AID.PrimalWrath);

// no suitable oGCDs...
return new();
}
Expand Down
1 change: 1 addition & 0 deletions BossMod/Autorotation/Utility/ClassWARUtility.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
namespace BossMod.Autorotation;

// TODO: dawntrail updates: veng -> damnation, enhanced reprisal (role)
public sealed class ClassWARUtility(RotationModuleManager manager, Actor player) : RoleTankUtility(manager, player)
{
public enum Track { Thrill = SharedTrack.Count, Vengeance, Holmgang, Bloodwhetting, Equilibrium, ShakeItOff }
Expand Down
6 changes: 4 additions & 2 deletions BossMod/Data/ClassRole.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ public enum Class : byte
DNC = 38,
RPR = 39,
SGE = 40,
VPR = 41,
PCT = 42,
}

public enum ClassCategory
Expand Down Expand Up @@ -71,9 +73,9 @@ public static class ClassRole
{
Class.GLA or Class.PLD or Class.MRD or Class.WAR or Class.DRK or Class.GNB => ClassCategory.Tank,
Class.SCH or Class.CNJ or Class.WHM or Class.AST or Class.SGE => ClassCategory.Healer,
Class.LNC or Class.DRG or Class.PGL or Class.MNK or Class.ROG or Class.NIN or Class.SAM or Class.RPR => ClassCategory.Melee,
Class.LNC or Class.DRG or Class.PGL or Class.MNK or Class.ROG or Class.NIN or Class.SAM or Class.RPR or Class.VPR => ClassCategory.Melee,
Class.ARC or Class.BRD or Class.MCH or Class.DNC => ClassCategory.PhysRanged,
Class.THM or Class.BLM or Class.ACN or Class.SMN or Class.RDM => ClassCategory.Caster,
Class.THM or Class.BLM or Class.ACN or Class.SMN or Class.RDM or Class.PCT => ClassCategory.Caster,
Class.BLU => allowLimited ? ClassCategory.Limited : ClassCategory.Caster,
_ => ClassCategory.Undefined
};
Expand Down
5 changes: 1 addition & 4 deletions BossMod/Replay/ReplayManagementConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,9 @@ public class ReplayManagementConfig : ConfigNode
[PropertyDisplay("Show replay management UI")]
public bool ShowUI = false;

[PropertyDisplay("Auto record replays on duty start")]
[PropertyDisplay("Auto record replays on duty start/end")]
public bool AutoRecord = false;

[PropertyDisplay("Auto stop replays on duty end")]
public bool AutoStop = false;

[PropertyDisplay("Max replays to keep before removal")]
[PropertySlider(0, 1000)]
public int MaxReplays = 0;
Expand Down
8 changes: 7 additions & 1 deletion BossMod/Replay/ReplayManagementWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public class ReplayManagementWindow : UIWindow
private readonly EventSubscriptions _subscriptions;
private ReplayRecorder? _recorder;
private string _message = "";
private bool _autoRecording;

private const string _windowID = "###Replay recorder";

Expand Down Expand Up @@ -133,15 +134,20 @@ public override void OnClose()

private bool UpdateAutoRecord(uint cfcId)
{
if (!_config.AutoRecord)
return false; // don't care

if (!IsRecording() && _config.AutoRecord && cfcId != 0)
{
StartRecording();
_autoRecording = true;
return true;
}

if (IsRecording() && _config.AutoStop && cfcId == 0)
if (IsRecording() && _autoRecording && cfcId == 0)
{
StopRecording();
_autoRecording = false;
return true;
}

Expand Down

0 comments on commit 2af570e

Please sign in to comment.