diff --git a/RotationSolver.Basic/Actions/BaseAction_BasicInfo.cs b/RotationSolver.Basic/Actions/BaseAction_BasicInfo.cs
index 580e6f5b5..3d6f0ac7f 100644
--- a/RotationSolver.Basic/Actions/BaseAction_BasicInfo.cs
+++ b/RotationSolver.Basic/Actions/BaseAction_BasicInfo.cs
@@ -18,7 +18,8 @@ public partial class BaseAction : IBaseAction
///
/// EnoughLevel for using.
///
- public bool EnoughLevel => Service.Player.Level >= _action.ClassJobLevel;
+ public bool EnoughLevel => Service.Player.Level >= Level;
+ public byte Level => _action.ClassJobLevel;
public string Name => _action.Name;
public string Description => string.Empty;
diff --git a/RotationSolver.Basic/Actions/BaseItem.cs b/RotationSolver.Basic/Actions/BaseItem.cs
index 2df7f91f4..8687109d1 100644
--- a/RotationSolver.Basic/Actions/BaseItem.cs
+++ b/RotationSolver.Basic/Actions/BaseItem.cs
@@ -43,6 +43,8 @@ public bool IsEnabled
public bool EnoughLevel => true;
+ public byte Level => 0;
+
public unsafe bool IsCoolingDown => ActionManager.Instance()->IsRecastTimerActive(ActionType.Item, ID);
public BaseItem(uint row, uint a4 = 65535)
diff --git a/RotationSolver.Basic/Actions/IAction.cs b/RotationSolver.Basic/Actions/IAction.cs
index 34831f84b..df920452e 100644
--- a/RotationSolver.Basic/Actions/IAction.cs
+++ b/RotationSolver.Basic/Actions/IAction.cs
@@ -19,4 +19,6 @@ public interface IAction : ITexture
/// Player's level is enough for this action's usage.
///
bool EnoughLevel { get; }
+
+ internal byte Level { get; }
}
diff --git a/RotationSolver.Basic/DataCenter.cs b/RotationSolver.Basic/DataCenter.cs
index 27c181b5c..1e5c156f6 100644
--- a/RotationSolver.Basic/DataCenter.cs
+++ b/RotationSolver.Basic/DataCenter.cs
@@ -196,9 +196,42 @@ public static void SetSpecialType(SpecialCommandType specialType)
public static bool HasPet { get; set; }
+
public static unsafe bool HasCompanion => (IntPtr)Service.RawPlayer == IntPtr.Zero ? false :
(IntPtr)CharacterManager.Instance()->LookupBuddyByOwnerObject(Service.RawPlayer) != IntPtr.Zero;
+ public static float RatioOfMembersIn2minsBurst
+ {
+ get
+ {
+ byte burst = 0, count = 0;
+
+ foreach (var member in PartyMembers)
+ {
+ foreach (var burstInfo in StatusHelper.Burst2Mins)
+ {
+ if (burstInfo.jobs.Contains((ClassJobID)member.ClassJob.Id))
+ {
+ if (member.Level >= burstInfo.level)
+ {
+ var tar = burstInfo.isOnHostile
+ && Service.TargetManager.Target is BattleChara b ? b
+ : Service.Player;
+ if (tar.HasStatus(false, burstInfo.status)
+ && !tar.WillStatusEndGCD(0, 0, false, burstInfo.status))
+ {
+ burst++;
+ }
+ count++;
+ }
+ break;
+ }
+ }
+ }
+ return (float)burst / count;
+ }
+ }
+
#region HP
public static IEnumerable PartyMembersHP { get; set; }
public static float PartyMembersMinHP { get; set; }
diff --git a/RotationSolver.Basic/Helpers/StatusHelper.cs b/RotationSolver.Basic/Helpers/StatusHelper.cs
index 4a0e8666e..e6b6481ec 100644
--- a/RotationSolver.Basic/Helpers/StatusHelper.cs
+++ b/RotationSolver.Basic/Helpers/StatusHelper.cs
@@ -15,32 +15,31 @@ public static class StatusHelper
StatusID.AspectedBenefic, StatusID.Regen1, StatusID.Regen2, StatusID.Regen3
};
- public static StatusID[] TankStanceStatus { get; } = new StatusID[]
+ internal static StatusID[] TankStanceStatus { get; } = new StatusID[]
{
StatusID.Grit, StatusID.RoyalGuard, StatusID.IronWill, StatusID.Defiance
};
- public static StatusID[] NoNeedHealingStatus { get; } = new StatusID[]
+ internal static StatusID[] NoNeedHealingStatus { get; } = new StatusID[]
{
StatusID.Holmgang, StatusID.WillDead, StatusID.WalkingDead,
};
- public static StatusID[] Burst2minsBuff { get; } = new StatusID[]
- {
- //StatusID.Divination,
- StatusID.Brotherhood,
- StatusID.BattleLitany,
- StatusID.ArcaneCircle,
- StatusID.BattleVoice,
- //StatusID.TechnicalStepFinished,
- StatusID.SearingLight,
- StatusID.Embolden,
- };
- public static StatusID[] Burst2minsDeBuff { get; } = new StatusID[]
+ internal record Burst2MinsInfo( StatusID status, bool isOnHostile, byte level, params ClassJobID[] jobs);
+
+ internal static Burst2MinsInfo[] Burst2Mins { get; } = new Burst2MinsInfo[]
{
- StatusID.ChainStratagem,
- //StatusID.Mug,
+ //new Burst2MinsInfo(StatusID.Divination, false, AST_Base.Divination.Level, ClassJobID.Astrologian),
+ new Burst2MinsInfo(StatusID.ChainStratagem, true, SCH_Base.ChainStratagem.Level, ClassJobID.Scholar),
+ new Burst2MinsInfo(StatusID.Brotherhood, false, MNK_Base.Brotherhood.Level, ClassJobID.Monk),
+ new Burst2MinsInfo(StatusID.BattleLitany, false, DRG_Base.BattleLitany.Level, ClassJobID.Dragoon),
+ new Burst2MinsInfo(StatusID.ArcaneCircle, false, RPR_Base.ArcaneCircle.Level, ClassJobID.Reaper),
+ new Burst2MinsInfo(StatusID.BattleVoice, false, BRD_Base.BattleVoice.Level, ClassJobID.Bard),
+ //new Burst2MinsInfo(StatusID.TechnicalStepFinished, false, DNC_Base.TechnicalStep.Level, ClassJobID.Dancer),
+ new Burst2MinsInfo(StatusID.SearingLight, false, SMN_Base.SearingLight.Level, ClassJobID.Summoner),
+ new Burst2MinsInfo(StatusID.Embolden, false, RDM_Base.Embolden.Level, ClassJobID.RedMage),
+ //new Burst2MinsInfo(StatusID.Mug, true, NIN_Base.Mug.Level, ClassJobID.Ninja, ClassJobID.Rogue),
};
public static bool NeedHealing(this BattleChara p) => p.WillStatusEndGCD(2, 0, false, NoNeedHealingStatus);
diff --git a/RotationSolver.Basic/Rotations/CustomRotation_OtherInfo.cs b/RotationSolver.Basic/Rotations/CustomRotation_OtherInfo.cs
index 41569b9b6..ac2ab7f69 100644
--- a/RotationSolver.Basic/Rotations/CustomRotation_OtherInfo.cs
+++ b/RotationSolver.Basic/Rotations/CustomRotation_OtherInfo.cs
@@ -53,15 +53,8 @@ public abstract partial class CustomRotation
protected static IEnumerable WeakenPeople => DataCenter.WeakenPeople;
protected static IEnumerable DyingPeople => DataCenter.DyingPeople;
- protected static byte CountOfMembersIn2minsBurst => (byte)(StatusHelper.Burst2minsBuff.Count(s =>
- {
- if (!Player.HasStatus(false, s)) return false;
- return !Player.WillStatusEndGCD(0, 0, false, s);
- }) + StatusHelper.Burst2minsDeBuff.Count(s =>
- {
- if (!Target.HasStatus(false, s)) return false;
- return !Target.WillStatusEndGCD(0, 0, false, s);
- }));
+ protected static float RatioOfMembersIn2minsBurst => DataCenter.RatioOfMembersIn2minsBurst;
+
///
/// Whether the number of party members is 8.
diff --git a/RotationSolver/UI/RotationConfigWindow_Debug.cs b/RotationSolver/UI/RotationConfigWindow_Debug.cs
index 446b5c207..9e08cfe26 100644
--- a/RotationSolver/UI/RotationConfigWindow_Debug.cs
+++ b/RotationSolver/UI/RotationConfigWindow_Debug.cs
@@ -46,7 +46,6 @@ private unsafe void DrawStatus()
ImGui.Text("Have Companion: " + DataCenter.HasCompanion.ToString());
ImGui.Text("Targetable: " + Service.Player.IsTargetable().ToString());
-
foreach (var status in Service.Player.StatusList)
{
var source = status.SourceId == Service.Player.ObjectId ? "You" : Service.ObjectTable.SearchById(status.SourceId) == null ? "None" : "Others";
@@ -69,6 +68,8 @@ private unsafe void DrawParty()
// }
//}
+ ImGui.Text("Party Burst Ratio: " + DataCenter.RatioOfMembersIn2minsBurst.ToString());
+
ImGui.Text("Party: " + DataCenter.PartyMembers.Count().ToString());
ImGui.Text("CanHealSingleAbility: " + DataCenter.CanHealSingleAbility.ToString());
ImGui.Text("CanHealSingleSpell: " + DataCenter.CanHealSingleSpell.ToString());