diff --git a/RotationSolver.Basic/Actions/ActionBasicInfo.cs b/RotationSolver.Basic/Actions/ActionBasicInfo.cs
index 4ef37d51b..578bd4c42 100644
--- a/RotationSolver.Basic/Actions/ActionBasicInfo.cs
+++ b/RotationSolver.Basic/Actions/ActionBasicInfo.cs
@@ -5,7 +5,10 @@
namespace RotationSolver.Basic.Actions;
-public struct ActionBasicInfo
+///
+/// The action info for the .
+///
+public readonly struct ActionBasicInfo
{
internal static readonly uint[] ActionsNoNeedCasting =
[
@@ -15,25 +18,65 @@ public struct ActionBasicInfo
];
private readonly IBaseAction _action;
+
+ ///
+ /// The name of the action.
+ ///
public readonly string Name => _action.Action.Name;
+
+ ///
+ /// The ID of the action.
+ ///
public readonly uint ID => _action.Action.RowId;
+
+ ///
+ /// The icon of the action.
+ ///
public readonly uint IconID => ID == (uint)ActionID.SprintPvE ? 104u : _action.Action.Icon;
+ ///
+ /// The adjust id of this action.
+ ///
public readonly uint AdjustedID => (uint)Service.GetAdjustedActionId((ActionID)ID);
+ ///
+ /// The attack type of this action.
+ ///
public readonly AttackType AttackType => (AttackType)(_action.Action.AttackType.Value?.RowId ?? byte.MaxValue);
+ ///
+ /// The aspect of this action.
+ ///
+ public Aspect Aspect { get; }
+
+ ///
+ /// The animation lock time of this action.
+ ///
public readonly float AnimationLockTime => OtherConfiguration.AnimationLockTime?.TryGetValue(AdjustedID, out var time) ?? false ? time : 0.6f;
+ ///
+ /// The level of this action.
+ ///
public readonly byte Level => _action.Action.ClassJobLevel;
+
+ ///
+ /// If this action is enough level to use.
+ ///
public readonly bool EnoughLevel => Player.Level >= Level;
+ ///
+ /// If this action a pvp action.
+ ///
public readonly bool IsPvP => _action.Action.IsPvP;
+
///
/// Casting time.
///
public readonly unsafe float CastTime => ((ActionID)AdjustedID).GetCastTime();
+ ///
+ /// How many mp does this action needs.
+ ///
public readonly unsafe uint MPNeed
{
get
@@ -47,6 +90,9 @@ public readonly unsafe uint MPNeed
}
}
+ ///
+ /// Is thia action on the slot.
+ ///
public readonly bool IsOnSlot
{
get
@@ -64,12 +110,32 @@ public readonly bool IsOnSlot
return IsPvP == DataCenter.Territory?.IsPvpZone;
}
}
+
+ ///
+ /// Is this action is a lb action.
+ ///
public bool IsLimitBreak { get; }
+
+ ///
+ /// Is this action a general gcd.
+ ///
public bool IsGeneralGCD { get; }
+
+ ///
+ /// Is this action a real gcd.
+ ///
public bool IsRealGCD { get; }
+
+ ///
+ /// Is this action a duty action.
+ ///
public bool IsDutyAction { get; }
- public Aspect Aspect { get; }
+ ///
+ /// The basic way to create a basic info
+ ///
+ /// the action
+ /// if it is a duty action.
public ActionBasicInfo(IBaseAction action, bool isDutyAction)
{
_action = action;
@@ -81,7 +147,7 @@ public ActionBasicInfo(IBaseAction action, bool isDutyAction)
Aspect = (Aspect)_action.Action.Aspect;
}
- internal readonly bool BasicCheck(bool skipStatusProvideCheck, bool skipCombo, bool ignoreCastingCheck)
+ internal readonly bool BasicCheck(bool skipStatusProvideCheck, bool skipComboCheck, bool skipCastingCheck)
{
if (!_action.Config.IsEnabled || !IsOnSlot) return false;
@@ -112,7 +178,7 @@ internal readonly bool BasicCheck(bool skipStatusProvideCheck, bool skipCombo, b
if (CustomRotation.LimitBreakLevel <= 1) return false;
}
- if (!skipCombo && IsGeneralGCD)
+ if (!skipComboCheck && IsGeneralGCD)
{
if (!CheckForCombo()) return false;
}
@@ -134,7 +200,7 @@ internal readonly bool BasicCheck(bool skipStatusProvideCheck, bool skipCombo, b
//Is knocking back.
if (DateTime.Now > DataCenter.KnockbackStart && DateTime.Now < DataCenter.KnockbackFinished) return false;
- if (DataCenter.NoPoslock && DataCenter.IsMoving && !ignoreCastingCheck) return false;
+ if (DataCenter.NoPoslock && DataCenter.IsMoving && !skipCastingCheck) return false;
}
if (IsGeneralGCD && _action.Setting.StatusProvide?.Length > 0 && _action.Setting.IsFriendly
diff --git a/RotationSolver.Basic/Actions/ActionConfig.cs b/RotationSolver.Basic/Actions/ActionConfig.cs
index 695214103..4ea840efc 100644
--- a/RotationSolver.Basic/Actions/ActionConfig.cs
+++ b/RotationSolver.Basic/Actions/ActionConfig.cs
@@ -6,19 +6,48 @@
public class ActionConfig()
{
private bool _isEnable = true;
+
+ ///
+ /// If this action is enabled.
+ ///
public bool IsEnabled
{
get => IBaseAction.ForceEnable || _isEnable;
set => _isEnable = value;
}
+ ///
+ /// Should check the status for this action.
+ ///
+ public bool ShouldCheckStatus { get; set; } = true;
+
+ ///
+ /// The status count in gcd for adding the status.
+ ///
public byte StatusGcdCount { get; set; } = 2;
+
+ ///
+ /// The aoe count of this action.
+ ///
public byte AoeCount { get; set; } = 3;
+
+ ///
+ /// How many ttk should this action use.
+ ///
public float TimeToKill { get; set; } = 0;
- public bool ShouldCheckStatus { get; set; } = true;
+ ///
+ /// The heal ratio for the auto heal.
+ ///
public float AutoHealRatio { get; set; } = 0.8f;
+ ///
+ /// Is this action in the cd window.
+ ///
public bool IsInCooldown { get; set; } = true;
+
+ ///
+ /// Is this action should be a mistake action.
+ ///
public bool IsInMistake { get; set; }
}
diff --git a/RotationSolver.Basic/Actions/ActionCooldownInfo.cs b/RotationSolver.Basic/Actions/ActionCooldownInfo.cs
index 201169214..ddcdb4a0a 100644
--- a/RotationSolver.Basic/Actions/ActionCooldownInfo.cs
+++ b/RotationSolver.Basic/Actions/ActionCooldownInfo.cs
@@ -2,9 +2,17 @@
using FFXIVClientStructs.FFXIV.Client.Game;
namespace RotationSolver.Basic.Actions;
+
+///
+/// The action cooldown information.
+///
public readonly struct ActionCooldownInfo : ICooldown
{
private readonly IBaseAction _action;
+
+ ///
+ /// The cd group.
+ ///
public byte CoolDownGroup { get; }
unsafe RecastDetail* CoolDownDetail => ActionIdHelper.GetCoolDownDetail(CoolDownGroup);
@@ -61,6 +69,10 @@ namespace RotationSolver.Basic.Actions;
float RecastTimeElapsedOneChargeRaw => RecastTimeElapsedRaw % RecastTimeOneChargeRaw;
+ ///
+ /// The default constructor.
+ ///
+ /// the action.
public ActionCooldownInfo(IBaseAction action)
{
_action = action;
diff --git a/RotationSolver.Basic/Actions/ActionSetting.cs b/RotationSolver.Basic/Actions/ActionSetting.cs
index 3739bacb0..1c80ef255 100644
--- a/RotationSolver.Basic/Actions/ActionSetting.cs
+++ b/RotationSolver.Basic/Actions/ActionSetting.cs
@@ -5,16 +5,51 @@
///
public class ActionSetting()
{
+ ///
+ /// The Ninjutsu action of this action.
+ ///
public IBaseAction[]? Ninjutsu { get; set; } = null;
+
+ ///
+ /// The override of the .
+ ///
public Func? MPOverride { get; set; } = null;
+
+ ///
+ /// Is this action in the melee range.
+ ///
public bool IsMeleeRange { get; set; } = false;
+
+ ///
+ /// Is this status is added by the plyer.
+ ///
public bool StatusFromSelf { get; set; } = true;
+
+ ///
+ /// The status that it provides to the target.
+ ///
public StatusID[]? TargetStatusProvide { get; set; } = null;
+
+ ///
+ /// The status that it needs on the target.
+ ///
public StatusID[]? TargetStatusNeed { get; set; } = null;
+
+ ///
+ /// Can the target be targeted.
+ ///
public Func CanTarget { get; set; } = t => true;
+
+ ///
+ /// The additional not combo ids.
+ ///
public ActionID[]? ComboIdsNot { get; set; }
+ ///
+ /// The additional combo ids.
+ ///
public ActionID[]? ComboIds { get; set; }
+
///
/// Status that this action provides.
///
@@ -25,14 +60,25 @@ public class ActionSetting()
///
public StatusID[]? StatusNeed { get; set; } = null;
+ ///
+ /// Your custom rotation check for your rotation.
+ ///
public Func? RotationCheck { get; set; } = null;
+
internal Func? ActionCheck { get; set; } = null;
internal Func? CreateConfig { get; set; } = null;
+ ///
+ /// Is this action friendly.
+ ///
public bool IsFriendly { get; set; }
private TargetType _type = TargetType.Big;
+
+ ///
+ /// The strategy to target the target.
+ ///
public TargetType TargetType
{
get
@@ -56,8 +102,14 @@ public TargetType TargetType
set => _type = value;
}
+ ///
+ /// The enemy positional for this action.
+ ///
public EnemyPositional EnemyPositional { get; set; } = EnemyPositional.None;
+ ///
+ /// Should end the special.
+ ///
public bool EndSpecial { get; set; }
}
diff --git a/RotationSolver.Basic/Actions/ActionTargetInfo.cs b/RotationSolver.Basic/Actions/ActionTargetInfo.cs
index ccbbc0d45..322def838 100644
--- a/RotationSolver.Basic/Actions/ActionTargetInfo.cs
+++ b/RotationSolver.Basic/Actions/ActionTargetInfo.cs
@@ -9,17 +9,31 @@
namespace RotationSolver.Basic.Actions;
-public struct ActionTargetInfo(IBaseAction _action)
+///
+/// The target info
+///
+/// the input action.
+public struct ActionTargetInfo(IBaseAction action)
{
- public readonly bool TargetArea => _action.Action.TargetArea;
-
- public readonly float Range => ActionManager.GetActionRange(_action.Info.ID);
+ ///
+ /// The range of this action.
+ ///
+ public readonly float Range => ActionManager.GetActionRange(action.Info.ID);
- public readonly float EffectRange => (ActionID)_action.Info.ID == ActionID.LiturgyOfTheBellPvE ? 20 : _action.Action.EffectRange;
+ ///
+ /// The effect range of this action.
+ ///
+ public readonly float EffectRange => (ActionID)action.Info.ID == ActionID.LiturgyOfTheBellPvE ? 20 : action.Action.EffectRange;
- public readonly bool IsSingleTarget => _action.Action.CastType == 1;
+ ///
+ /// Is this action single target.
+ ///
+ public readonly bool IsSingleTarget => action.Action.CastType == 1;
+ ///
+ /// Is this action target are.
+ ///
- public readonly bool IsTargetArea => _action.Action.TargetArea;
+ public readonly bool IsTargetArea => action.Action.TargetArea;
private static bool NoAOE
{
@@ -41,7 +55,7 @@ private static bool NoAOE
#region Target Finder.
//The delay of finding the targets.
private readonly ObjectListDelay _canTargets = new (() => Service.Config.TargetDelay);
- public readonly IEnumerable GetCanTargets(bool skipStatusProvideCheck, TargetType type)
+ private readonly IEnumerable GetCanTargets(bool skipStatusProvideCheck, TargetType type)
{
var items = TargetFilter.GetObjectInRadius(DataCenter.AllTargets, Range);
var objs = new List(items.Count());
@@ -54,15 +68,15 @@ public readonly IEnumerable GetCanTargets(bool skipStatusProvideChe
objs.Add(obj);
}
- _canTargets.Delay(objs.Where(CanUseTo).Where(InViewTarget).Where(_action.Setting.CanTarget));
+ _canTargets.Delay(objs.Where(CanUseTo).Where(InViewTarget).Where(action.Setting.CanTarget));
return _canTargets;
}
- public readonly IEnumerable GetCanAffects(bool skipStatusProvideCheck, TargetType type)
+ private readonly IEnumerable GetCanAffects(bool skipStatusProvideCheck, TargetType type)
{
if (EffectRange == 0) return [];
- var items = TargetFilter.GetObjectInRadius(_action.Setting.IsFriendly
+ var items = TargetFilter.GetObjectInRadius(action.Setting.IsFriendly
? DataCenter.PartyMembers
: DataCenter.AllHostileTargets,
Range + EffectRange);
@@ -111,8 +125,8 @@ private readonly unsafe bool CanUseTo(GameObject tar)
var tarAddress = tar.Struct();
if (tarAddress == null) return false;
- if ((ActionID)_action.Info.ID != ActionID.AethericMimicryPvE
- && !ActionManager.CanUseActionOnTarget(_action.Info.AdjustedID, tarAddress)) return false;
+ if ((ActionID)action.Info.ID != ActionID.AethericMimicryPvE
+ && !ActionManager.CanUseActionOnTarget(action.Info.AdjustedID, tarAddress)) return false;
return tar.CanSee();
}
@@ -140,18 +154,18 @@ private readonly bool GeneralCheck(BattleChara gameObject, bool skipStatusProvid
private readonly bool CheckStatus(GameObject gameObject, bool skipStatusProvideCheck)
{
- if (!_action.Config.ShouldCheckStatus) return true;
+ if (!action.Config.ShouldCheckStatus) return true;
- if (_action.Setting.TargetStatusNeed != null)
+ if (action.Setting.TargetStatusNeed != null)
{
if (gameObject.WillStatusEndGCD(0, 0,
- _action.Setting.StatusFromSelf, _action.Setting.TargetStatusNeed)) return false;
+ action.Setting.StatusFromSelf, action.Setting.TargetStatusNeed)) return false;
}
- if (_action.Setting.TargetStatusProvide != null && !skipStatusProvideCheck)
+ if (action.Setting.TargetStatusProvide != null && !skipStatusProvideCheck)
{
- if (!gameObject.WillStatusEndGCD(_action.Config.StatusGcdCount, 0,
- _action.Setting.StatusFromSelf, _action.Setting.TargetStatusProvide)) return false;
+ if (!gameObject.WillStatusEndGCD(action.Config.StatusGcdCount, 0,
+ action.Setting.StatusFromSelf, action.Setting.TargetStatusProvide)) return false;
}
return true;
@@ -159,14 +173,14 @@ private readonly bool CheckStatus(GameObject gameObject, bool skipStatusProvideC
private readonly bool CheckResistance(GameObject gameObject)
{
- if (_action.Info.AttackType == AttackType.Magic)
+ if (action.Info.AttackType == AttackType.Magic)
{
if (gameObject.HasStatus(false, StatusHelper.MagicResistance))
{
return false;
}
}
- else if(_action.Info.Aspect != Aspect.Piercing) // Physic
+ else if(action.Info.Aspect != Aspect.Piercing) // Physic
{
if (gameObject.HasStatus(false, StatusHelper.PhysicResistancec))
{
@@ -188,7 +202,7 @@ private readonly bool CheckTimeToKill(GameObject gameObject)
{
if (gameObject is not BattleChara b) return false;
var time = b.GetTimeToKill();
- return float.IsNaN(time) || time >= _action.Config.TimeToKill;
+ return float.IsNaN(time) || time >= action.Config.TimeToKill;
}
#endregion
@@ -206,7 +220,7 @@ private readonly bool CheckTimeToKill(GameObject gameObject)
{
return new(player, [], player.Position);
}
- var type = _action.Setting.TargetType;
+ var type = action.Setting.TargetType;
var canTargets = GetCanTargets(skipStatusProvideCheck, type);
var canAffects = GetCanAffects(skipStatusProvideCheck, type);
@@ -219,7 +233,7 @@ private readonly bool CheckTimeToKill(GameObject gameObject)
{
var t = Svc.Targets.Target as BattleChara;
- if (t == null || !_action.Setting.CanTarget(t)) return null;
+ if (t == null || !action.Setting.CanTarget(t)) return null;
if (type == TargetType.Move)
{
@@ -235,7 +249,7 @@ private readonly bool CheckTimeToKill(GameObject gameObject)
else
{
var effects = GetAffects(t, canAffects).ToArray();
- if (effects.Length >= _action.Config.AoeCount || skipAoeCheck)
+ if (effects.Length >= action.Config.AoeCount || skipAoeCheck)
{
return new(t, effects, t.Position);
}
@@ -244,12 +258,12 @@ private readonly bool CheckTimeToKill(GameObject gameObject)
}
var targets = GetMostCanTargetObjects(canTargets, canAffects,
- skipAoeCheck ? 0 : _action.Config.AoeCount);
- if (type == TargetType.BeAttacked && !_action.Setting.IsFriendly)
+ skipAoeCheck ? 0 : action.Config.AoeCount);
+ if (type == TargetType.BeAttacked && !action.Setting.IsFriendly)
{
type = TargetType.Big;
}
- var target = FindTargetByType(targets, type, _action.Config.AutoHealRatio, _action.Setting.IsMeleeRange);
+ var target = FindTargetByType(targets, type, action.Config.AutoHealRatio, action.Setting.IsMeleeRange);
if (target == null) return null;
return new(target, [.. GetAffects(target, canAffects)], target.Position);
@@ -258,11 +272,11 @@ private readonly bool CheckTimeToKill(GameObject gameObject)
private readonly TargetResult? FindTargetArea(IEnumerable canTargets, IEnumerable canAffects,
float range, PlayerCharacter player)
{
- if (_action.Setting.TargetType is TargetType.Move)
+ if (action.Setting.TargetType is TargetType.Move)
{
return FindTargetAreaMove(range);
}
- else if (_action.Setting.IsFriendly)
+ else if (action.Setting.IsFriendly)
{
if (!Service.Config.UseGroundBeneficialAbility) return null;
if (!Service.Config.UseGroundBeneficialAbilityWhenMoving && DataCenter.IsMoving) return null;
@@ -271,7 +285,7 @@ private readonly bool CheckTimeToKill(GameObject gameObject)
}
else
{
- return FindTargetAreaHostile(canTargets, canAffects, _action.Config.AoeCount);
+ return FindTargetAreaHostile(canTargets, canAffects, action.Config.AoeCount);
}
}
@@ -311,7 +325,7 @@ private readonly bool CheckTimeToKill(GameObject gameObject)
{
var availableCharas = DataCenter.AllTargets.Where(b => b.ObjectId != Player.Object.ObjectId);
var target = FindTargetByType(TargetFilter.GetObjectInRadius(availableCharas, range),
- TargetType.Move, _action.Config.AutoHealRatio, _action.Setting.IsMeleeRange);
+ TargetType.Move, action.Config.AutoHealRatio, action.Setting.IsMeleeRange);
if (target == null) return null;
return new(target, [], target.Position);
}
@@ -335,7 +349,7 @@ private readonly bool CheckTimeToKill(GameObject gameObject)
DataCenter.TerritoryContentType == TerritoryContentType.Raids
&& DataCenter.AllianceMembers.Count(p => p is PlayerCharacter) == 8)
{
- pts = pts.Union(new Vector3[] { Vector3.Zero, new(100, 0, 100) }).ToArray();
+ pts = pts.Union([Vector3.Zero, new(100, 0, 100)]).ToArray();
}
}
@@ -373,7 +387,7 @@ private readonly bool CheckTimeToKill(GameObject gameObject)
{
var effectRange = EffectRange;
var attackT = FindTargetByType(DataCenter.AllianceMembers.GetObjectInRadius(range + effectRange),
- TargetType.BeAttacked, _action.Config.AutoHealRatio, _action.Setting.IsMeleeRange);
+ TargetType.BeAttacked, action.Config.AutoHealRatio, action.Setting.IsMeleeRange);
if (attackT == null)
{
@@ -425,7 +439,7 @@ private readonly IEnumerable GetAffects(BattleChara tar, IEnumerabl
private readonly IEnumerable GetMostCanTargetObjects(IEnumerable canTargets, IEnumerable canAffects, int aoeCount)
{
if (IsSingleTarget || EffectRange <= 0) return canTargets;
- if (!_action.Setting.IsFriendly && NoAOE) return [];
+ if (!action.Setting.IsFriendly && NoAOE) return [];
List objectMax = new(canTargets.Count());
@@ -474,7 +488,7 @@ private readonly bool CanGetTarget(GameObject target, GameObject subTarget)
Vector3 dir = target.Position - pPos;
Vector3 tdir = subTarget.Position - pPos;
- switch (_action.Action.CastType)
+ switch (action.Action.CastType)
{
case 2: // Circle
return Vector3.Distance(target.Position, subTarget.Position) - subTarget.HitboxRadius <= EffectRange;
@@ -495,7 +509,7 @@ private readonly bool CanGetTarget(GameObject target, GameObject subTarget)
return dis <= EffectRange && dis >= 8;
}
- Svc.Log.Debug(_action.Action.Name.RawString + "'s CastType is not valid! The value is " + _action.Action.CastType.ToString());
+ Svc.Log.Debug(action.Action.Name.RawString + "'s CastType is not valid! The value is " + action.Action.CastType.ToString());
return false;
}
#endregion
@@ -799,64 +813,35 @@ private readonly bool CanGetTarget(GameObject target, GameObject subTarget)
#endregion
}
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
public enum TargetType : byte
{
- ///
- /// Find the target whose hit box is biggest.
- ///
Big,
-
- ///
- /// Find the target whose hit box is smallest.
- ///
Small,
-
- ///
- /// Find the target whose hp is highest.
- ///
HighHP,
-
- ///
- /// Find the target whose hp is lowest.
- ///
LowHP,
-
- ///
- /// Find the target whose max hp is highest.
- ///
HighMaxHP,
-
- ///
- /// Find the target whose max hp is lowest.
- ///
LowMaxHP,
-
-
Interrupt,
-
Provoke,
-
Death,
-
Dispel,
-
Move,
-
BeAttacked,
-
Heal,
-
Tank,
-
Melee,
-
Range,
-
Physical,
-
Magical,
-
Self,
}
-
+#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member
+
+///
+/// The target result
+///
+/// the target.
+/// the targets that be affected by this action.
+/// the position to use this action.
public readonly record struct TargetResult(BattleChara? Target, BattleChara[] AffectedTargets, Vector3? Position);
\ No newline at end of file
diff --git a/RotationSolver.Basic/Actions/BaseAction.cs b/RotationSolver.Basic/Actions/BaseAction.cs
index 94010c013..1c5b015d4 100644
--- a/RotationSolver.Basic/Actions/BaseAction.cs
+++ b/RotationSolver.Basic/Actions/BaseAction.cs
@@ -4,6 +4,10 @@
using Action = Lumina.Excel.GeneratedSheets.Action;
namespace RotationSolver.Basic.Actions;
+
+///
+/// The base action for all actions.
+///
public class BaseAction : IBaseAction
{
///
@@ -39,7 +43,7 @@ public class BaseAction : IBaseAction
public uint SortKey => Cooldown.CoolDownGroup;
///
- public uint IconID => ID == 3 ? 104 : Info.IconID;
+ public uint IconID => Info.IconID;
///
public string Name => Info.Name;
@@ -105,7 +109,7 @@ public BaseAction(ActionID actionID, bool isDutyAction = false)
}
///
- public bool CanUse(out IAction act, bool skipStatusProvideCheck = false, bool skipCombo = false, bool skipCastingCheck = false,
+ public bool CanUse(out IAction act, bool skipStatusProvideCheck = false, bool skipComboCheck = false, bool skipCastingCheck = false,
bool usedUp = false, bool onLastAbility = false, bool skipClippingCheck = false, bool skipAoeCheck = false, byte gcdCountForAbility = 0)
{
act = this!;
@@ -125,7 +129,7 @@ public bool CanUse(out IAction act, bool skipStatusProvideCheck = false, bool sk
skipClippingCheck = true;
}
- if (!Info.BasicCheck(skipStatusProvideCheck, skipCombo, skipCastingCheck)) return false;
+ if (!Info.BasicCheck(skipStatusProvideCheck, skipComboCheck, skipCastingCheck)) return false;
if (!Cooldown.CooldownCheck(usedUp, onLastAbility, skipClippingCheck, gcdCountForAbility)) return false;
@@ -148,7 +152,7 @@ public bool CanUse(out IAction act, CanUseOption option, byte gcdCountForAbility
{
return CanUse(out act,
option.HasFlag(CanUseOption.SkipStatusProvideCheck),
- option.HasFlag(CanUseOption.SkipCombo),
+ option.HasFlag(CanUseOption.SkipComboCheck),
option.HasFlag(CanUseOption.SkipCastingCheck),
option.HasFlag(CanUseOption.UsedUp),
option.HasFlag(CanUseOption.OnLastAbility),
@@ -165,7 +169,7 @@ public unsafe bool Use()
var target = Target.Value;
var adjustId = AdjustedID;
- if (TargetInfo.TargetArea)
+ if (TargetInfo.IsTargetArea)
{
if (adjustId != ID) return false;
if (!target.Position.HasValue) return false;
diff --git a/RotationSolver.Basic/Actions/BaseItem.cs b/RotationSolver.Basic/Actions/BaseItem.cs
index 5d1ae08e4..1238187d2 100644
--- a/RotationSolver.Basic/Actions/BaseItem.cs
+++ b/RotationSolver.Basic/Actions/BaseItem.cs
@@ -56,6 +56,9 @@ readonly struct ItemCooldown(uint id) : ICooldown
///
public string Name => _item.Name;
+ ///
+ /// The item configs.
+ ///
public ItemConfig Config
{
get
@@ -124,7 +127,8 @@ public bool IsInCooldown
///
protected virtual bool CanUseThis => true;
- public ICooldown Cooldown => throw new NotImplementedException();
+ ///
+ public ICooldown Cooldown { get; }
///
/// Create by row.
@@ -149,6 +153,7 @@ public unsafe BaseItem(Item item)
_ => 65535, //TODO: better A4!
};
SortKey = (uint)ActionManager.Instance()->GetRecastGroup((int)ActionType.Item, ID);
+ Cooldown = new ItemCooldown(ID);
}
///
diff --git a/RotationSolver.Basic/Actions/IBaseAction.cs b/RotationSolver.Basic/Actions/IBaseAction.cs
index e9e73ad1c..4c45d771f 100644
--- a/RotationSolver.Basic/Actions/IBaseAction.cs
+++ b/RotationSolver.Basic/Actions/IBaseAction.cs
@@ -2,6 +2,9 @@
namespace RotationSolver.Basic.Actions;
+///
+/// The interface of the base action.
+///
public interface IBaseAction : IAction
{
internal static TargetType? TargetOverride { get; set; } = null;
@@ -12,17 +15,64 @@ public interface IBaseAction : IAction
internal static bool AllEmpty { get; set; } = false;
internal static bool ShouldEndSpecial { get; set; } = false;
+ ///
+ /// The action itself.
+ ///
Action Action { get; }
+
+ ///
+ /// The target to use on.
+ ///
TargetResult? Target { get; set; }
+
+ ///
+ /// The target for preview.
+ ///
TargetResult? PreviewTarget { get; }
+
+ ///
+ /// The information about the target.
+ ///
ActionTargetInfo TargetInfo { get; }
+
+ ///
+ /// The basic information of this action.
+ ///
ActionBasicInfo Info { get; }
+
+ ///
+ /// The cd information.
+ ///
new ActionCooldownInfo Cooldown { get; }
+
+ ///
+ /// The setting to use this action.
+ ///
ActionSetting Setting { get; set; }
- internal ActionConfig Config { get; }
+ internal ActionConfig Config { get; }
- bool CanUse(out IAction act, bool skipStatusProvideCheck = false, bool skipCombo = false, bool skipCastingCheck = false,
+ ///
+ /// Can I use this action.
+ ///
+ /// The return action
+ /// Skip Status Provide Check
+ /// Skip Combo Check
+ /// Skip Casting and Moving Check
+ /// Is it used up all stacks
+ /// Is it on the last ability
+ /// Skip clipping Check
+ /// Skip aoe Check
+ /// the gcd count for the ability.
+ /// can I use it
+ bool CanUse(out IAction act, bool skipStatusProvideCheck = false, bool skipComboCheck = false, bool skipCastingCheck = false,
bool usedUp = false, bool onLastAbility = false, bool skipClippingCheck = false, bool skipAoeCheck = false, byte gcdCountForAbility = 0);
+ ///
+ /// Can I use this action.
+ ///
+ /// The return action
+ /// The options
+ /// the gcd count for the ability.
+ /// can I use it
bool CanUse(out IAction act, CanUseOption option, byte gcdCountForAbility = 0);
}
diff --git a/RotationSolver.Basic/Actions/ICooldown.cs b/RotationSolver.Basic/Actions/ICooldown.cs
index 69b3afd12..ae27861a0 100644
--- a/RotationSolver.Basic/Actions/ICooldown.cs
+++ b/RotationSolver.Basic/Actions/ICooldown.cs
@@ -1,9 +1,25 @@
namespace RotationSolver.Basic.Actions;
+
+///
+/// The cd information.
+///
public interface ICooldown
{
internal float RecastTimeOneChargeRaw { get; }
internal float RecastTimeElapsedRaw { get; }
+
+ ///
+ /// Is still in cooling down.
+ ///
bool IsCoolingDown { get; }
+
+ ///
+ /// The mac charges.
+ ///
ushort MaxCharges { get; }
+
+ ///
+ /// The current charges.
+ ///
ushort CurrentCharges { get; }
}
diff --git a/RotationSolver.Basic/Actions/ItemConfig.cs b/RotationSolver.Basic/Actions/ItemConfig.cs
index 82f35e1aa..62ed40689 100644
--- a/RotationSolver.Basic/Actions/ItemConfig.cs
+++ b/RotationSolver.Basic/Actions/ItemConfig.cs
@@ -1,6 +1,17 @@
namespace RotationSolver.Basic.Actions;
+
+///
+/// The item config.
+///
public class ItemConfig
{
+ ///
+ /// Is in the cooldown window.
+ ///
public bool IsInCooldown { get; set; }
+
+ ///
+ /// Is this action enabled.
+ ///
public bool IsEnabled { get; set; }
}
diff --git a/RotationSolver.Basic/Attributes/DutyTerritoryAttribute.cs b/RotationSolver.Basic/Attributes/DutyTerritoryAttribute.cs
index 4b9b7bd79..0b524bc45 100644
--- a/RotationSolver.Basic/Attributes/DutyTerritoryAttribute.cs
+++ b/RotationSolver.Basic/Attributes/DutyTerritoryAttribute.cs
@@ -1,8 +1,15 @@
namespace RotationSolver.Basic.Attributes;
+///
+/// The duty territory attribute. which contains the
+///
+///
[AttributeUsage(AttributeTargets.Class)]
public class DutyTerritoryAttribute(params uint[] territoryIds) : Attribute
{
+ ///
+ /// The terriotry ids.
+ ///
public uint[] TerritoryIds => territoryIds;
}
diff --git a/RotationSolver.Basic/Attributes/IDAttribute.cs b/RotationSolver.Basic/Attributes/IDAttribute.cs
index 7bb902337..8f426a571 100644
--- a/RotationSolver.Basic/Attributes/IDAttribute.cs
+++ b/RotationSolver.Basic/Attributes/IDAttribute.cs
@@ -1,7 +1,7 @@
namespace RotationSolver.Basic.Attributes;
[AttributeUsage(AttributeTargets.Property)]
-public class IDAttribute(uint id) : Attribute
+internal class IDAttribute(uint id) : Attribute
{
public uint ID => id;
}
diff --git a/RotationSolver.Basic/Attributes/RangeAttribute.cs b/RotationSolver.Basic/Attributes/RangeAttribute.cs
index e5a9ed216..cd7de460f 100644
--- a/RotationSolver.Basic/Attributes/RangeAttribute.cs
+++ b/RotationSolver.Basic/Attributes/RangeAttribute.cs
@@ -1,30 +1,73 @@
namespace RotationSolver.Basic.Attributes;
+///
+/// The range of the configs.
+///
+/// min value
+/// max value
+/// the unit type
+/// the speed.
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class RangeAttribute(float minValue, float maxValue, ConfigUnitType unitType, float speed = 0.005f) : Attribute
{
+ ///
+ /// Min Value
+ ///
public float MinValue => minValue;
+
+ ///
+ /// Max Value
+ ///
public float MaxValue => maxValue;
+
+ ///
+ /// Speed
+ ///
public float Speed => speed;
+
+ ///
+ /// The unit type.
+ ///
public ConfigUnitType UnitType => unitType;
}
+///
+/// The config unit type.
+///
public enum ConfigUnitType : byte
{
+ ///
+ /// None unit type.
+ ///
None,
+ ///
+ ///
+ ///
[Description("Time Unit, in seconds.")]
Seconds,
+ ///
+ ///
+ ///
[Description("Angle Unit, in degrees.")]
Degree,
+ ///
+ ///
+ ///
[Description("Distance Unit, in yalms.")]
Yalms,
+ ///
+ ///
+ ///
[Description("Ratio Unit, as percentage.")]
Percent,
+ ///
+ ///
+ ///
[Description("Display Unit, in pixels.")]
Pixels,
}
\ No newline at end of file
diff --git a/RotationSolver.Basic/Attributes/RotationAttribute.cs b/RotationSolver.Basic/Attributes/RotationAttribute.cs
index 242cf8407..38f843a92 100644
--- a/RotationSolver.Basic/Attributes/RotationAttribute.cs
+++ b/RotationSolver.Basic/Attributes/RotationAttribute.cs
@@ -1,12 +1,30 @@
namespace RotationSolver.Basic.Attributes;
+///
+/// Your custom rotation attribute.
+///
+/// the name of this rotation.
+/// the type of this rotation.
[AttributeUsage(AttributeTargets.Class)]
public class RotationAttribute(string name, CombatType type) : Attribute
{
+ ///
+ /// The name of this rotation.
+ ///
public string Name => name;
+
+ ///
+ /// The type of this rotation.
+ ///
public CombatType Type => type;
+ ///
+ /// Your description about this rotation.
+ ///
public string? Description { get; set; }
+ ///
+ /// The Game version of this rotation.
+ ///
public string? GameVersion { get; set; }
}
diff --git a/RotationSolver.Basic/Attributes/UIAttributes.cs b/RotationSolver.Basic/Attributes/UIAttributes.cs
index b8f033b3d..408fac99e 100644
--- a/RotationSolver.Basic/Attributes/UIAttributes.cs
+++ b/RotationSolver.Basic/Attributes/UIAttributes.cs
@@ -1,21 +1,59 @@
namespace RotationSolver.Basic.Attributes;
+///
+/// The attribute for the ui configs.
+///
+///
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class UIAttribute(string name) : Attribute
{
+ ///
+ /// The name of this config.
+ ///
public string Name => name;
+
+ ///
+ /// The description about this ui item.
+ ///
public string Description { get; set; } = "";
+
+ ///
+ /// The parent of this ui item.
+ ///
public string Parent { get; set; } = "";
+
+ ///
+ /// The filter to get this ui item.
+ ///
public string Filter { get; set; } = "";
+
+ ///
+ /// The order of this item.
+ ///
public byte Order { get; set; } = 0;
+
+ ///
+ /// The section of this item.
+ ///
public byte Section { get; set; } = 0;
+ ///
+ /// The action id
+ ///
public ActionID Action { get; set; }
+ ///
+ /// The filter for the pvp.
+ ///
public JobFilterType PvPFilter { get; set; }
+
+ ///
+ /// The filter for the pve.
+ ///
public JobFilterType PvEFilter { get; set; }
}
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
public enum JobFilterType : byte
{
None,
@@ -28,6 +66,7 @@ public enum JobFilterType : byte
Tank,
Melee,
}
+#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
internal class JobConfigAttribute : Attribute
diff --git a/RotationSolver.Basic/Configuration/Conditions/IConditionConverter.cs b/RotationSolver.Basic/Configuration/Conditions/IConditionConverter.cs
index 32dfb726e..8e7c31ef5 100644
--- a/RotationSolver.Basic/Configuration/Conditions/IConditionConverter.cs
+++ b/RotationSolver.Basic/Configuration/Conditions/IConditionConverter.cs
@@ -4,7 +4,7 @@ namespace RotationSolver.Basic.Configuration.Conditions;
internal class IConditionConverter : JsonCreationConverter
{
- protected override ICondition Create(JObject jObject)
+ protected override ICondition? Create(JObject jObject)
{
if (FieldExists(nameof(ConditionSet.Conditions), jObject))
{
@@ -48,7 +48,7 @@ private static bool FieldExists(string fieldName, JObject jObject)
internal abstract class JsonCreationConverter : JsonConverter
{
- protected abstract T Create(JObject jObject);
+ protected abstract T? Create(JObject jObject);
public override bool CanConvert(Type objectType)
{
@@ -57,20 +57,23 @@ public override bool CanConvert(Type objectType)
public override bool CanWrite => false;
- public sealed override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+ public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
{
}
- public sealed override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+ public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
{
// Load JObject from stream
JObject jObject = JObject.Load(reader);
// Create target object based on JObject
- T target = Create(jObject);
+ var target = Create(jObject);
// Populate the object properties
- serializer.Populate(jObject.CreateReader(), target);
+ if (target != null)
+ {
+ serializer.Populate(jObject.CreateReader(), target);
+ }
return target;
}
diff --git a/RotationSolver.Basic/Data/BeneficialAreaStrategy.cs b/RotationSolver.Basic/Data/BeneficialAreaStrategy.cs
index 04c1628e4..d5ae4b209 100644
--- a/RotationSolver.Basic/Data/BeneficialAreaStrategy.cs
+++ b/RotationSolver.Basic/Data/BeneficialAreaStrategy.cs
@@ -1,15 +1,31 @@
namespace RotationSolver.Basic.Data;
+
+///
+/// The way to place the beneficial area action.
+///
public enum BeneficialAreaStrategy : byte
{
+ ///
+ /// On predefined location
+ ///
[Description("On predefined location")]
OnLocations,
+ ///
+ /// Only on predefined location
+ ///
[Description("Only on predefined location")]
OnlyOnLocations,
+ ///
+ /// On target
+ ///
[Description("On target")]
OnTarget,
+ ///
+ /// On the calculated location
+ ///
[Description("On the calculated location")]
OnCalculated,
}
\ No newline at end of file
diff --git a/RotationSolver.Basic/Data/CanUseOption.cs b/RotationSolver.Basic/Data/CanUseOption.cs
index d26a085b7..3d11060a0 100644
--- a/RotationSolver.Basic/Data/CanUseOption.cs
+++ b/RotationSolver.Basic/Data/CanUseOption.cs
@@ -27,7 +27,7 @@ public enum CanUseOption : byte
/// Skip Combo Check
///
[Description("Skip Combo Check")]
- SkipCombo = 1 << 1,
+ SkipComboCheck = 1 << 1,
///
/// Skip Casting and Moving Check
diff --git a/RotationSolver.Basic/Data/ObjectListDelay.cs b/RotationSolver.Basic/Data/ObjectListDelay.cs
index e0d943088..24dacb538 100644
--- a/RotationSolver.Basic/Data/ObjectListDelay.cs
+++ b/RotationSolver.Basic/Data/ObjectListDelay.cs
@@ -14,11 +14,15 @@ namespace RotationSolver.Basic.Data;
public class ObjectListDelay(Func<(float min, float max)> getRange)
: IEnumerable where T : GameObject
{
- IEnumerable _list = Array.Empty();
+ IEnumerable _list = [];
readonly Func<(float min, float max)> _getRange = getRange;
SortedList _revealTime = [];
readonly Random _ran = new(DateTime.Now.Millisecond);
+ ///
+ /// The default creator from the config.
+ ///
+ /// the way to get the config.
public ObjectListDelay(Func getRange)
: this(() =>
{
diff --git a/RotationSolver.Basic/Data/RandomDelay.cs b/RotationSolver.Basic/Data/RandomDelay.cs
index e768add33..aea427f58 100644
--- a/RotationSolver.Basic/Data/RandomDelay.cs
+++ b/RotationSolver.Basic/Data/RandomDelay.cs
@@ -20,6 +20,10 @@ public struct RandomDelay(Func<(float min, float max)> getRange)
///
public readonly Func<(float min, float max)> GetRange => getRange;
+ ///
+ /// The constructor for the config.
+ ///
+ /// The way to get the config.
public RandomDelay(Func getRange)
: this(() =>
{
@@ -66,6 +70,12 @@ public bool Delay(bool originData)
return false;
}
+ ///
+ /// The delay to get the item.
+ ///
+ /// the type of anything.
+ /// original data.
+ /// the value.
public T? Delay(T? originData) where T : class
{
var b = originData != null;
diff --git a/RotationSolver.Basic/Helpers/ActionIdHelper.cs b/RotationSolver.Basic/Helpers/ActionIdHelper.cs
index 571a01692..3e7b91829 100644
--- a/RotationSolver.Basic/Helpers/ActionIdHelper.cs
+++ b/RotationSolver.Basic/Helpers/ActionIdHelper.cs
@@ -3,19 +3,38 @@
using Action = Lumina.Excel.GeneratedSheets.Action;
namespace RotationSolver.Basic.Helpers;
-public static class ActionIdHelper
+
+///
+/// The helper for the action id.
+///
+public static class ActionIdHelper
{
+ ///
+ /// Is this action cooling down.
+ ///
+ /// the action id.
+ ///
public unsafe static bool IsCoolingDown(this ActionID actionID)
{
return IsCoolingDown(actionID.GetAction().GetCoolDownGroup());
}
+ ///
+ /// Is this action cooling down.
+ ///
+ ///
+ ///
public unsafe static bool IsCoolingDown(byte cdGroup)
{
var detail = GetCoolDownDetail(cdGroup);
return detail != null && detail->IsActive != 0;
}
+ ///
+ /// The cd details
+ ///
+ ///
+ ///
public static unsafe RecastDetail* GetCoolDownDetail(byte cdGroup) => ActionManager.Instance()->GetRecastGroupDetail(cdGroup - 1);
@@ -24,6 +43,11 @@ private static Action GetAction(this ActionID actionID)
return Svc.Data.GetExcelSheet()!.GetRow((uint)actionID)!;
}
+ ///
+ /// The cast time.
+ ///
+ ///
+ ///
public unsafe static float GetCastTime(this ActionID actionID)
{
return ActionManager.GetAdjustedCastTime(ActionType.Action, (uint)actionID) / 1000f; ;
diff --git a/RotationSolver.Basic/Helpers/ObjectHelper.cs b/RotationSolver.Basic/Helpers/ObjectHelper.cs
index a4331dfc8..8e1f248c0 100644
--- a/RotationSolver.Basic/Helpers/ObjectHelper.cs
+++ b/RotationSolver.Basic/Helpers/ObjectHelper.cs
@@ -30,10 +30,10 @@ public static class ObjectHelper
return Service.GetSheet().GetRow(obj.DataId);
}
- public static bool CanProvoke(this GameObject target)
+ internal static bool CanProvoke(this GameObject target)
{
//Removed the listed names.
- IEnumerable names = Array.Empty();
+ IEnumerable names = [];
if (OtherConfiguration.NoProvokeNames.TryGetValue(Svc.ClientState.TerritoryType, out var ns1))
names = names.Union(ns1);
@@ -54,23 +54,13 @@ public static bool CanProvoke(this GameObject target)
return false;
}
- ///
- /// Is the target have positional.
- ///
- ///
- ///
- public static bool HasPositional(this GameObject obj)
+ internal static bool HasPositional(this GameObject obj)
{
if (obj == null) return false;
return !(obj.GetObjectNPC()?.Unknown10 ?? false);
}
- ///
- /// Is this target belongs to other players.
- ///
- ///
- ///
- public static unsafe bool IsOthersPlayers(this GameObject obj)
+ internal static unsafe bool IsOthersPlayers(this GameObject obj)
{
//SpecialType but no NamePlateIcon
if (_eventType.Contains(obj.GetEventType()))
@@ -80,7 +70,7 @@ public static unsafe bool IsOthersPlayers(this GameObject obj)
return false;
}
- public static bool IsAttackable(this BattleChara battleChara)
+ internal static bool IsAttackable(this BattleChara battleChara)
{
//Dead.
if (battleChara.CurrentHp <= 1) return false;
@@ -90,7 +80,7 @@ public static bool IsAttackable(this BattleChara battleChara)
if (Svc.ClientState == null) return false;
//In No Hostiles Names
- IEnumerable names = Array.Empty();
+ IEnumerable names = [];
if (OtherConfiguration.NoHostileNames.TryGetValue(Svc.ClientState.TerritoryType, out var ns1))
names = names.Union(ns1);
@@ -142,7 +132,7 @@ public static bool IsAttackable(this BattleChara battleChara)
};
}
- public static unsafe bool IsInEnemiesList(this BattleChara battleChara)
+ internal static unsafe bool IsInEnemiesList(this BattleChara battleChara)
{
var addons = Service.GetAddons();
@@ -161,26 +151,16 @@ public static unsafe bool IsInEnemiesList(this BattleChara battleChara)
return false;
}
- ///
- /// Is this target an enemy (can be attacked).
- ///
- ///
- ///
- public static unsafe bool IsEnemy(this GameObject obj)
+ internal static unsafe bool IsEnemy(this GameObject obj)
=> obj != null
&& ActionManager.CanUseActionOnTarget((uint)ActionID.BlizzardPvE, obj.Struct());
- ///
- /// Is alliance (can be healed).
- ///
- ///
- ///
- public static unsafe bool IsAlliance(this GameObject obj)
+ internal static unsafe bool IsAlliance(this GameObject obj)
=> obj != null && obj.ObjectId is not 0 and not GameObject.InvalidGameObjectId
&& (!(DataCenter.Territory?.IsPvpZone ?? false) && obj is PlayerCharacter
|| ActionManager.CanUseActionOnTarget((uint)ActionID.CurePvE, obj.Struct()));
- public static bool IsParty(this GameObject gameObject)
+ internal static bool IsParty(this GameObject gameObject)
{
if (gameObject.ObjectId == Player.Object.ObjectId) return true;
if (Svc.Party.Any(p => p.GameObject?.ObjectId == gameObject.ObjectId)) return true;
@@ -188,12 +168,12 @@ public static bool IsParty(this GameObject gameObject)
return false;
}
- public static bool IsTargetOnSelf(this BattleChara battleChara)
+ internal static bool IsTargetOnSelf(this BattleChara battleChara)
{
return battleChara.TargetObject?.TargetObject == battleChara;
}
- public static bool IsDeathToRaise(this GameObject obj)
+ internal static bool IsDeathToRaise(this GameObject obj)
{
if (obj == null) return false;
if (!obj.IsDead) return false;
@@ -210,12 +190,10 @@ public static bool IsDeathToRaise(this GameObject obj)
return true;
}
- public static bool IsAlive(this GameObject obj)
+ internal static bool IsAlive(this GameObject obj)
{
if (obj is BattleChara b && b.CurrentHp <= 1) return false;
-
if (!obj.IsTargetable) return false;
-
return true;
}
@@ -258,16 +236,11 @@ or 71344 //Major Quest
internal static unsafe uint GetNamePlateIcon(this GameObject obj) => obj.Struct()->NamePlateIconId;
internal static unsafe EventHandlerType GetEventType(this GameObject obj) => obj.Struct()->EventId.Type;
- ///
- /// The sub kind of the target.
- ///
- ///
- ///
- public static unsafe BattleNpcSubKind GetBattleNPCSubKind(this GameObject obj) => (BattleNpcSubKind)obj.Struct()->SubKind;
+ internal static unsafe BattleNpcSubKind GetBattleNPCSubKind(this GameObject obj) => (BattleNpcSubKind)obj.Struct()->SubKind;
internal static unsafe uint FateId(this GameObject obj) => obj.Struct()->FateId;
- static readonly Dictionary _effectRangeCheck = new();
+ static readonly Dictionary _effectRangeCheck = [];
internal static bool CanInterrupt(this GameObject o)
{
if (o is not BattleChara b) return false;
@@ -287,19 +260,9 @@ internal static bool CanInterrupt(this GameObject o)
return _effectRangeCheck[id] = true;
}
- ///
- /// Is object a dummy.
- ///
- ///
- ///
- public static bool IsDummy(this BattleChara obj) => obj?.NameId == 541;
+ internal static bool IsDummy(this BattleChara obj) => obj?.NameId == 541;
- ///
- /// Is character a boss? Calculate from ttk.
- ///
- ///
- ///
- public static bool IsBossFromTTK(this BattleChara obj)
+ internal static bool IsBossFromTTK(this BattleChara obj)
{
if (obj == null) return false;
@@ -311,12 +274,7 @@ public static bool IsBossFromTTK(this BattleChara obj)
return false;
}
- ///
- /// Is character a boss? Calculated from the icon.
- ///
- ///
- ///
- public static bool IsBossFromIcon(this BattleChara obj)
+ internal static bool IsBossFromIcon(this BattleChara obj)
{
if (obj == null) return false;
@@ -328,37 +286,21 @@ public static bool IsBossFromIcon(this BattleChara obj)
return false;
}
- ///
- /// Is character a dying? Current HP is below a certain amount. It is for running out of resources.
- ///
- ///
- ///
- public static bool IsDying(this BattleChara b)
+ internal static bool IsDying(this BattleChara b)
{
if (b == null) return false;
if (b.IsDummy() && !Service.Config.ShowTargetTimeToKill) return false;
return b.GetTimeToKill() <= Service.Config.DyingTimeToKill || b.GetHealthRatio() < 0.02f;
}
- ///
- /// Whether the character is in combat.
- ///
- ///
- ///
- public static unsafe bool InCombat(this BattleChara obj)
+ internal static unsafe bool InCombat(this BattleChara obj)
{
return obj.Struct()->Character.InCombat;
}
private static readonly TimeSpan CheckSpan = TimeSpan.FromSeconds(2.5);
- ///
- /// How many seconds will the target die.
- ///
- ///
- /// whole time to die.
- ///
- public static float GetTimeToKill(this BattleChara b, bool wholeTime = false)
+ internal static float GetTimeToKill(this BattleChara b, bool wholeTime = false)
{
if (b == null) return float.NaN;
if (b.IsDummy()) return 999.99f;
@@ -388,12 +330,7 @@ public static float GetTimeToKill(this BattleChara b, bool wholeTime = false)
return (float)timespan.TotalSeconds / ratioReduce * (wholeTime ? 1 : ratioNow);
}
- ///
- /// Whether the target is attacked.
- ///
- ///
- ///
- public static bool IsAttacked(this BattleChara b)
+ internal static bool IsAttacked(this BattleChara b)
{
foreach (var (id, time) in DataCenter.AttackedTargets)
{
@@ -405,12 +342,7 @@ public static bool IsAttacked(this BattleChara b)
return false;
}
- ///
- /// Can the player see the object.
- ///
- ///
- ///
- public static unsafe bool CanSee(this GameObject b)
+ internal static unsafe bool CanSee(this GameObject b)
{
var point = Player.Object.Position + Vector3.UnitY * Player.GameObject->Height;
var tarPt = b.Position + Vector3.UnitY * b.Struct()->Height;
@@ -451,24 +383,13 @@ internal static EnemyPositional FindEnemyPositional(this GameObject enemy)
return EnemyPositional.Flank;
}
- ///
- /// Get the face vector
- ///
- ///
- ///
- public static Vector2 GetFaceVector(this GameObject obj)
+ internal static Vector2 GetFaceVector(this GameObject obj)
{
float rotation = obj.Rotation;
return new((float)Math.Cos(rotation), (float)Math.Sin(rotation));
}
- ///
- /// Get two vector's angle
- ///
- ///
- ///
- ///
- public static double AngleTo(this Vector2 vec1, Vector2 vec2)
+ internal static double AngleTo(this Vector2 vec1, Vector2 vec2)
{
return Math.Acos(Vector2.Dot(vec1, vec2) / vec1.Length() / vec2.Length());
}
diff --git a/RotationSolver.Basic/Helpers/TargetFilter.cs b/RotationSolver.Basic/Helpers/TargetFilter.cs
index 838a462d0..05b3f310e 100644
--- a/RotationSolver.Basic/Helpers/TargetFilter.cs
+++ b/RotationSolver.Basic/Helpers/TargetFilter.cs
@@ -60,11 +60,18 @@ public static bool IsJobCategory(this GameObject obj, JobRole role)
return obj.IsJobs(validJobs);
}
+ ///
+ /// Is the target in the jobs.
+ ///
+ ///
+ ///
+ ///
public static bool IsJobs(this GameObject obj, params Job[] validJobs)
{
return obj.IsJobs(new SortedSet( validJobs.Select(j => (byte)(uint)j)));
}
- public static bool IsJobs(this GameObject obj, SortedSet validJobs)
+
+ private static bool IsJobs(this GameObject obj, SortedSet validJobs)
{
if(obj is not BattleChara b) return false;
return validJobs.Contains((byte?)b.ClassJob.GameData?.RowId ?? 0);
diff --git a/RotationSolver.Basic/Rotations/Basic/BlackMageRotation.cs b/RotationSolver.Basic/Rotations/Basic/BlackMageRotation.cs
index c974535ec..c4548f4c5 100644
--- a/RotationSolver.Basic/Rotations/Basic/BlackMageRotation.cs
+++ b/RotationSolver.Basic/Rotations/Basic/BlackMageRotation.cs
@@ -56,7 +56,7 @@ partial class BlackMageRotation
///
///
///
- public static float EnochianTime => EnochianTimeRaw + DataCenter.WeaponRemain;
+ public static float EnochianTime => EnochianTimeRaw - DataCenter.WeaponRemain;
///
///
@@ -79,7 +79,7 @@ protected static bool EnchinaEndAfterGCD(uint gcdCount = 0, float offset = 0)
///
///
///
- protected static float ElementTime => ElementTimeRaw + DataCenter.WeaponRemain;
+ protected static float ElementTime => ElementTimeRaw - DataCenter.WeaponRemain;
///
///
diff --git a/RotationSolver.Basic/Rotations/Basic/DragoonRotation.cs b/RotationSolver.Basic/Rotations/Basic/DragoonRotation.cs
index 889025079..6ce6c833f 100644
--- a/RotationSolver.Basic/Rotations/Basic/DragoonRotation.cs
+++ b/RotationSolver.Basic/Rotations/Basic/DragoonRotation.cs
@@ -23,7 +23,7 @@ partial class DragoonRotation
///
///
///
- public static float LOTDTime => LOTDTimeRaw + DataCenter.WeaponRemain;
+ public static float LOTDTime => LOTDTimeRaw - DataCenter.WeaponRemain;
///
///
diff --git a/RotationSolver.Basic/Rotations/Basic/MachinistRotation.cs b/RotationSolver.Basic/Rotations/Basic/MachinistRotation.cs
index 9014e2156..7a22740be 100644
--- a/RotationSolver.Basic/Rotations/Basic/MachinistRotation.cs
+++ b/RotationSolver.Basic/Rotations/Basic/MachinistRotation.cs
@@ -26,7 +26,7 @@ partial class MachinistRotation
///
///
///
- public static float OverheatTime => OverheatTimeRemainingRaw + DataCenter.WeaponRemain;
+ public static float OverheatTime => OverheatTimeRemainingRaw - DataCenter.WeaponRemain;
///
///
diff --git a/RotationSolver.Basic/Rotations/Basic/NinjaRotation.cs b/RotationSolver.Basic/Rotations/Basic/NinjaRotation.cs
index fe78e9253..b0695f51c 100644
--- a/RotationSolver.Basic/Rotations/Basic/NinjaRotation.cs
+++ b/RotationSolver.Basic/Rotations/Basic/NinjaRotation.cs
@@ -115,6 +115,9 @@ static partial void ModifyDotonPvE(ref ActionSetting setting)
setting.StatusProvide = [StatusID.Doton];
}
+ ///
+ ///
+ ///
public NinjaRotation()
{
FumaShurikenPvE.Setting.Ninjutsu = [TenPvE];
diff --git a/RotationSolver.Basic/Rotations/Basic/ScholarRotation.cs b/RotationSolver.Basic/Rotations/Basic/ScholarRotation.cs
index b4f739574..f1858785d 100644
--- a/RotationSolver.Basic/Rotations/Basic/ScholarRotation.cs
+++ b/RotationSolver.Basic/Rotations/Basic/ScholarRotation.cs
@@ -21,7 +21,7 @@ partial class ScholarRotation
///
///
///
- public static float SeraphTime => SeraphTimeRaw + DataCenter.WeaponRemain;
+ public static float SeraphTime => SeraphTimeRaw - DataCenter.WeaponRemain;
#endregion
private sealed protected override IBaseAction Raise => ResurrectionPvE;
diff --git a/RotationSolver.Basic/Rotations/CustomRotation_Actions.cs b/RotationSolver.Basic/Rotations/CustomRotation_Actions.cs
index ad7132cf6..146bb5357 100644
--- a/RotationSolver.Basic/Rotations/CustomRotation_Actions.cs
+++ b/RotationSolver.Basic/Rotations/CustomRotation_Actions.cs
@@ -132,6 +132,9 @@ static partial void ModifySprintPvP(ref ActionSetting setting)
private protected virtual IBaseAction? LimitBreak3 => null;
private protected virtual IBaseAction? LimitBreakPvP => null;
+ ///
+ /// All actions of this rotation.
+ ///
public virtual IAction[] AllActions =>
[
.. AllBaseActions.Where(i =>
@@ -150,14 +153,29 @@ .. HpPotions.Where(i => i.HasIt),
.. AllItems.Where(i => i.HasIt),
];
+ ///
+ /// All traits of this action.
+ ///
public virtual IBaseTrait[] AllTraits { get; } = [];
PropertyInfo[]? _allBools;
+
+ ///
+ /// All bools of this rotation.
+ ///
public PropertyInfo[] AllBools => _allBools ??= GetType().GetStaticProperties();
PropertyInfo[]? _allBytes;
+
+ ///
+ /// All bytes or integers of this rotation.
+ ///
public PropertyInfo[] AllBytesOrInt => _allBytes ??= GetType().GetStaticProperties().Union(GetType().GetStaticProperties()).ToArray();
PropertyInfo[]? _allFloats;
+
+ ///
+ /// All floats of this rotation.
+ ///
public PropertyInfo[] AllFloats => _allFloats ??= GetType().GetStaticProperties();
}
diff --git a/RotationSolver.Basic/Rotations/CustomRotation_BasicInfo.cs b/RotationSolver.Basic/Rotations/CustomRotation_BasicInfo.cs
index 19fc7fd28..07d9690fd 100644
--- a/RotationSolver.Basic/Rotations/CustomRotation_BasicInfo.cs
+++ b/RotationSolver.Basic/Rotations/CustomRotation_BasicInfo.cs
@@ -4,15 +4,20 @@
namespace RotationSolver.Basic.Rotations;
-[Jobs()]
partial class CustomRotation : ICustomRotation
{
private Job? _job = null;
+
+ ///
public Job Job => _job ??= this.GetType().GetCustomAttribute()?.Jobs[0] ?? Job.ADV;
private JobRole? _role = null;
+
+ ///
public JobRole Role => _role ??= Svc.Data.GetExcelSheet()!.GetRow((uint)Job)!.GetJobRole();
private string? _name = null;
+
+ ///
public string Name
{
get
@@ -25,6 +30,7 @@ public string Name
}
}
+ ///
public bool IsEnabled
{
get => !Service.Config.DisabledJobs.Contains(Job);
@@ -41,52 +47,83 @@ public bool IsEnabled
}
}
+ ///
public uint IconID { get; }
+ ///
public IRotationConfigSet Configs { get; }
+ ///
public static Vector3? MoveTarget { get; internal set; }
+ ///
public string Description => this.GetType().GetCustomAttribute()?.Description ?? string.Empty;
+ ///
public IAction? ActionHealAreaGCD { get; private set; }
+ ///
public IAction? ActionHealAreaAbility { get; private set; }
+ ///
public IAction? ActionHealSingleGCD { get; private set; }
+ ///
public IAction? ActionHealSingleAbility { get; private set; }
+ ///
public IAction? ActionDefenseAreaGCD { get; private set; }
+ ///
public IAction? ActionDefenseAreaAbility { get; private set; }
+ ///
public IAction? ActionDefenseSingleGCD { get; private set; }
+ ///
public IAction? ActionDefenseSingleAbility { get; private set; }
+ ///
public IAction? ActionMoveForwardGCD { get; private set; }
+ ///
public IAction? ActionMoveForwardAbility { get; private set; }
+ ///
public IAction? ActionMoveBackAbility { get; private set; }
+ ///
public IAction? ActionSpeedAbility { get; private set; }
+ ///
public IAction? ActionDispelStancePositionalGCD { get; private set; }
+ ///
public IAction? ActionDispelStancePositionalAbility { get; private set; }
+ ///
public IAction? ActionRaiseShirkGCD { get; private set; }
+ ///
public IAction? ActionRaiseShirkAbility { get; private set; }
+ ///
public IAction? ActionAntiKnockbackAbility { get; private set; }
+ ///
+ /// Is this action valid.
+ ///
[Description("Is this rotation valid")]
public bool IsValid { get; private set; } = true;
+
+ ///
+ /// Why this action is not valid.
+ ///
public string WhyNotValid { get; private set; } = string.Empty;
+ ///
+ /// Should show the status to the users.
+ ///
[Description("Show the status")]
public virtual bool ShowStatus => false;
@@ -96,11 +133,16 @@ private protected CustomRotation()
Configs = CreateConfiguration();
}
+ ///
+ /// The way to create the configurations.
+ ///
+ ///
protected virtual IRotationConfigSet CreateConfiguration()
{
return new RotationConfigSet();
}
+ ///
public override string ToString() => this.GetType().GetCustomAttribute()?.Name ?? this.GetType().Name;
///
diff --git a/RotationSolver.Basic/Rotations/CustomRotation_GCD.cs b/RotationSolver.Basic/Rotations/CustomRotation_GCD.cs
index f362116c0..6bd24dea7 100644
--- a/RotationSolver.Basic/Rotations/CustomRotation_GCD.cs
+++ b/RotationSolver.Basic/Rotations/CustomRotation_GCD.cs
@@ -181,12 +181,22 @@ bool RaiseAction(out IAction act, bool ignoreCastingCheck)
}
}
+ ///
+ /// The gcd for raising.
+ ///
+ /// the action.
+ ///
protected virtual bool RaiseGCD(out IAction? act)
{
if (DataCenter.RightNowDutyRotation?.RaiseGCD(out act) ?? false) return true;
act = null; return false;
}
+ ///
+ /// The gcd for dispeling.
+ ///
+ /// the action.
+ ///
protected virtual bool DispelGCD(out IAction? act)
{
if (EsunaPvE.CanUse(out act)) return true;
diff --git a/RotationSolver.Basic/Rotations/CustomRotation_OtherInfo.cs b/RotationSolver.Basic/Rotations/CustomRotation_OtherInfo.cs
index a3647b332..ea9f2ebb3 100644
--- a/RotationSolver.Basic/Rotations/CustomRotation_OtherInfo.cs
+++ b/RotationSolver.Basic/Rotations/CustomRotation_OtherInfo.cs
@@ -110,7 +110,7 @@ partial class CustomRotation
///
/// The player's target, or null if no valid target. (null clears the target)
///
- protected static BattleChara CurrentTarget => Svc.Targets.Target is BattleChara b ? b : null;
+ protected static BattleChara? CurrentTarget => Svc.Targets.Target is BattleChara b ? b : null;
///
/// The last attacked hostile target.
diff --git a/RotationSolver.Basic/Rotations/Duties/BozjaRotation.cs b/RotationSolver.Basic/Rotations/Duties/BozjaRotation.cs
index 0b6952b58..43a9fe8d5 100644
--- a/RotationSolver.Basic/Rotations/Duties/BozjaRotation.cs
+++ b/RotationSolver.Basic/Rotations/Duties/BozjaRotation.cs
@@ -1,5 +1,8 @@
namespace RotationSolver.Basic.Rotations.Duties;
+///
+/// The bozja action.
+///
[DutyTerritory] //TODO: the bozja territory ids!
public abstract class BozjaRotation : DutyRotation
{
diff --git a/RotationSolver.Basic/Rotations/Duties/DutyRotation.cs b/RotationSolver.Basic/Rotations/Duties/DutyRotation.cs
index 9a1e8aad1..84efc739b 100644
--- a/RotationSolver.Basic/Rotations/Duties/DutyRotation.cs
+++ b/RotationSolver.Basic/Rotations/Duties/DutyRotation.cs
@@ -1,4 +1,5 @@
namespace RotationSolver.Basic.Rotations.Duties;
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
partial class DutyRotation
{
@@ -128,3 +129,4 @@ internal IAction[] AllActions
}
}
}
+#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member
diff --git a/RotationSolver/Data/UiString.cs b/RotationSolver/Data/UiString.cs
index 56d31eb99..f09d16187 100644
--- a/RotationSolver/Data/UiString.cs
+++ b/RotationSolver/Data/UiString.cs
@@ -123,6 +123,9 @@ internal enum UiString
[Description("How many targets are needed to use this action.")]
ConfigWindow_Actions_AoeCount,
+ [Description("Should this action check the stauts.")]
+ ConfigWindow_Actions_CheckStatus,
+
[Description("How many gcds are needed to add the status.")]
ConfigWindow_Actions_GcdCount,
diff --git a/RotationSolver/UI/ConditionDrawer.cs b/RotationSolver/UI/ConditionDrawer.cs
index cfbfee8c7..22463934f 100644
--- a/RotationSolver/UI/ConditionDrawer.cs
+++ b/RotationSolver/UI/ConditionDrawer.cs
@@ -82,7 +82,7 @@ internal static void DrawCondition(bool? tag)
private static IEnumerable GetAllMethods(this Type? type, Func> getFunc)
{
- if (type == null || getFunc == null) return Array.Empty();
+ if (type == null || getFunc == null) return [];
var methods = getFunc(type);
return methods.Union(type.BaseType.GetAllMethods(getFunc));
diff --git a/RotationSolver/UI/RotationConfigWindow.cs b/RotationSolver/UI/RotationConfigWindow.cs
index fdaeb9949..8d9762701 100644
--- a/RotationSolver/UI/RotationConfigWindow.cs
+++ b/RotationSolver/UI/RotationConfigWindow.cs
@@ -2,6 +2,7 @@
using Dalamud.Interface.Internal;
using Dalamud.Interface.Utility;
using Dalamud.Interface.Utility.Raii;
+using Dalamud.Interface.Utility.Table;
using Dalamud.Interface.Windowing;
using Dalamud.Utility;
using ECommons.DalamudServices;
@@ -1405,105 +1406,76 @@ private static unsafe void DrawActions()
ImGui.TableNextColumn();
- if (Service.Config.InDebug)
- {
- if (_activeAction is IBaseAction action)
- {
+ DrawConfigsOfAction();
+ DrawActionDebug();
- try
- {
-#if DEBUG
- ImGui.Text("Is Real GCD: " + action.Info.IsRealGCD.ToString());
- ImGui.Text("Status: " + FFXIVClientStructs.FFXIV.Client.Game.ActionManager.Instance()->GetActionStatus(FFXIVClientStructs.FFXIV.Client.Game.ActionType.Action, action.AdjustedID).ToString());
- ImGui.Text("Cast Time: " + action.Info.CastTime.ToString());
- ImGui.Text("MP: " + action.Info.MPNeed.ToString());
-#endif
- ImGui.Text("AttackType: " + action.Info.AttackType.ToString());
- ImGui.Text("Aspect: " + action.Info.Aspect.ToString());
- ImGui.Text("Has One:" + action.Cooldown.HasOneCharge.ToString());
- ImGui.Text("Recast One: " + action.Cooldown.RecastTimeOneChargeRaw.ToString());
- ImGui.Text("Recast Elapsed: " + action.Cooldown.RecastTimeElapsedRaw.ToString());
-
- ImGui.Text($"Can Use: {action.CanUse(out _, skipClippingCheck: true)} ");
- ImGui.Text("IgnoreCastCheck:" + action.CanUse(out _, skipClippingCheck: true, skipCastingCheck : true).ToString());
- if (action.Target != null)
- {
- ImGui.Text("Target Name: " + action.Target.Value.Target?.Name ?? string.Empty);
- }
- }
- catch
- {
+ ImGui.TextWrapped(UiString.ConfigWindow_Actions_ConditionDescription.Local());
+ _sequencerList?.Draw();
+ }
- }
- }
- else if (_activeAction is IBaseItem item)
- {
- try
- {
- ImGui.Text("Status: " + FFXIVClientStructs.FFXIV.Client.Game.ActionManager.Instance()->GetActionStatus(FFXIVClientStructs.FFXIV.Client.Game.ActionType.Item, item.ID).ToString());
- ImGui.Text("Status HQ: " + FFXIVClientStructs.FFXIV.Client.Game.ActionManager.Instance()->GetActionStatus(FFXIVClientStructs.FFXIV.Client.Game.ActionType.Item, item.ID + 1000000).ToString());
- var remain = FFXIVClientStructs.FFXIV.Client.Game.ActionManager.Instance()->GetRecastTime(FFXIVClientStructs.FFXIV.Client.Game.ActionType.Item, item.ID) - FFXIVClientStructs.FFXIV.Client.Game.ActionManager.Instance()->GetRecastTimeElapsed(FFXIVClientStructs.FFXIV.Client.Game.ActionType.Item, item.ID);
- ImGui.Text("remain: " + remain.ToString());
- ImGui.Text("CanUse: " + item.CanUse(out _, true).ToString());
+ static void DrawConfigsOfAction()
+ {
+ if (_activeAction == null) return;
- if (item is HpPotionItem healPotionItem)
- {
- ImGui.Text("MaxHP:" + healPotionItem.MaxHp.ToString());
- }
- }
- catch
- {
+ var enable = _activeAction.IsEnabled;
+ if (ImGui.Checkbox($"{_activeAction.Name}##{_activeAction.Name} Enabled", ref enable))
+ {
+ _activeAction.IsEnabled = enable;
+ }
- }
- }
+ const string key = "Action Enable Popup";
+ var cmd = ToCommandStr(OtherCommandType.ToggleActions, _activeAction.ToString()!);
+ ImGuiHelper.DrawHotKeysPopup(key, cmd);
+ ImGuiHelper.ExecuteHotKeysPopup(key, cmd, string.Empty, false);
+
+ enable = _activeAction.IsInCooldown;
+ if (ImGui.Checkbox($"{UiString.ConfigWindow_Actions_ShowOnCDWindow.Local()}##{_activeAction.Name}InCooldown", ref enable))
+ {
+ _activeAction.IsInCooldown = enable;
}
- if (_activeAction != null)
+ if (_activeAction is IBaseAction a)
{
- var enable = _activeAction.IsEnabled;
- if (ImGui.Checkbox($"{_activeAction.Name}##{_activeAction.Name} Enabled", ref enable))
+ DrawConfigsOfBaseAction(a);
+ }
+
+ ImGui.Separator();
+
+ static void DrawConfigsOfBaseAction(IBaseAction a)
+ {
+ var config = a.Config;
+
+ if (Service.Config.MistakeRatio > 0
+ && !a.Setting.IsFriendly
+ && a.Setting.TargetType != TargetType.Move)
{
- _activeAction.IsEnabled = enable;
+ var enable = config.IsInMistake;
+ if (ImGui.Checkbox($"{UiString.ConfigWindow_Actions_IsInMistake.Local()}##{a.Name}InMistake", ref enable))
+ {
+ config.IsInMistake = enable;
+ }
}
- const string key = "Action Enable Popup";
- var cmd = ToCommandStr(OtherCommandType.ToggleActions, _activeAction.ToString()!);
- ImGuiHelper.DrawHotKeysPopup(key, cmd);
- ImGuiHelper.ExecuteHotKeysPopup(key, cmd, string.Empty, false);
+ ImGui.Separator();
- enable = _activeAction.IsInCooldown;
- if (ImGui.Checkbox($"{UiString.ConfigWindow_Actions_ShowOnCDWindow.Local()}##{_activeAction.Name}InCooldown", ref enable))
+ var ttk = config.TimeToKill;
+ ImGui.SetNextItemWidth(Scale * 150);
+ if (ImGui.DragFloat($"{UiString.ConfigWindow_Actions_TTK.Local()}##{a}",
+ ref ttk, 0.1f, 0, 120, $"{ttk:F2}{ConfigUnitType.Seconds.ToSymbol()}"))
{
- _activeAction.IsInCooldown = enable;
+ config.TimeToKill = ttk;
}
+ ImguiTooltips.HoveredTooltip(ConfigUnitType.Seconds.Local());
- if (_activeAction is IBaseAction a)
+ if (a.Setting.StatusProvide != null || a.Setting.TargetStatusProvide != null)
{
- var config = a.Config;
-
- if (Service.Config.MistakeRatio > 0
- && !a.Setting.IsFriendly
- && a.Setting.TargetType != TargetType.Move)
- {
- enable = config.IsInMistake;
- if (ImGui.Checkbox($"{UiString.ConfigWindow_Actions_IsInMistake.Local()}##{a.Name}InMistake", ref enable))
- {
- config.IsInMistake = enable;
- }
- }
-
- ImGui.Separator();
-
- var ttk = config.TimeToKill;
- ImGui.SetNextItemWidth(Scale * 150);
- if (ImGui.DragFloat($"{UiString.ConfigWindow_Actions_TTK.Local()}##{a}",
- ref ttk, 0.1f, 0, 120, $"{ttk:F2}{ConfigUnitType.Seconds.ToSymbol()}"))
+ var shouldStatus = config.ShouldCheckStatus;
+ if (ImGui.Checkbox($"{UiString.ConfigWindow_Actions_CheckStatus.Local()}##{a}", ref shouldStatus))
{
- config.TimeToKill = ttk;
+ config.ShouldCheckStatus = shouldStatus;
}
- ImguiTooltips.HoveredTooltip(ConfigUnitType.Seconds.Local());
- if (a.Setting.StatusProvide != null || a.Setting.TargetStatusProvide != null)
+ if (shouldStatus)
{
var statusGcdCount = (int)config.StatusGcdCount;
ImGui.SetNextItemWidth(Scale * 150);
@@ -1513,33 +1485,84 @@ private static unsafe void DrawActions()
config.StatusGcdCount = (byte)statusGcdCount;
}
}
+ }
- if (!a.TargetInfo.IsSingleTarget)
+ if (!a.TargetInfo.IsSingleTarget)
+ {
+ var aoeCount = (int)config.AoeCount;
+ ImGui.SetNextItemWidth(Scale * 150);
+ if (ImGui.DragInt($"{UiString.ConfigWindow_Actions_AoeCount.Local()}##{a}",
+ ref aoeCount, 0.05f, 1, 10))
{
- var aoeCount = (int)config.AoeCount;
- ImGui.SetNextItemWidth(Scale * 150);
- if (ImGui.DragInt($"{UiString.ConfigWindow_Actions_AoeCount.Local()}##{a}",
- ref aoeCount, 0.05f, 1, 10))
- {
- config.AoeCount = (byte)aoeCount;
- }
+ config.AoeCount = (byte)aoeCount;
}
+ }
- var ratio = config.AutoHealRatio;
- ImGui.SetNextItemWidth(Scale * 150);
- if (ImGui.DragFloat($"{UiString.ConfigWindow_Actions_HealRatio.Local()}##{a}",
- ref ratio, 0.002f, 0, 1, $"{ratio * 100:F1}{ConfigUnitType.Percent.ToSymbol()}"))
+ var ratio = config.AutoHealRatio;
+ ImGui.SetNextItemWidth(Scale * 150);
+ if (ImGui.DragFloat($"{UiString.ConfigWindow_Actions_HealRatio.Local()}##{a}",
+ ref ratio, 0.002f, 0, 1, $"{ratio * 100:F1}{ConfigUnitType.Percent.ToSymbol()}"))
+ {
+ config.AutoHealRatio = ratio;
+ }
+ ImguiTooltips.HoveredTooltip(ConfigUnitType.Percent.Local());
+
+ }
+ }
+
+ static void DrawActionDebug()
+ {
+ if (!Service.Config.InDebug) return;
+
+ if (_activeAction is IBaseAction action)
+ {
+
+ try
+ {
+#if DEBUG
+ ImGui.Text("Is Real GCD: " + action.Info.IsRealGCD.ToString());
+ ImGui.Text("Status: " + FFXIVClientStructs.FFXIV.Client.Game.ActionManager.Instance()->GetActionStatus(FFXIVClientStructs.FFXIV.Client.Game.ActionType.Action, action.AdjustedID).ToString());
+ ImGui.Text("Cast Time: " + action.Info.CastTime.ToString());
+ ImGui.Text("MP: " + action.Info.MPNeed.ToString());
+#endif
+ ImGui.Text("AttackType: " + action.Info.AttackType.ToString());
+ ImGui.Text("Aspect: " + action.Info.Aspect.ToString());
+ ImGui.Text("Has One:" + action.Cooldown.HasOneCharge.ToString());
+ ImGui.Text("Recast One: " + action.Cooldown.RecastTimeOneChargeRaw.ToString());
+ ImGui.Text("Recast Elapsed: " + action.Cooldown.RecastTimeElapsedRaw.ToString());
+
+ ImGui.Text($"Can Use: {action.CanUse(out _, skipClippingCheck: true)} ");
+ ImGui.Text("IgnoreCastCheck:" + action.CanUse(out _, skipClippingCheck: true, skipCastingCheck: true).ToString());
+ if (action.Target != null)
{
- config.AutoHealRatio = ratio;
+ ImGui.Text("Target Name: " + action.Target.Value.Target?.Name ?? string.Empty);
}
- ImguiTooltips.HoveredTooltip(ConfigUnitType.Percent.Local());
}
+ catch
+ {
- ImGui.Separator();
+ }
}
+ else if (_activeAction is IBaseItem item)
+ {
+ try
+ {
+ ImGui.Text("Status: " + FFXIVClientStructs.FFXIV.Client.Game.ActionManager.Instance()->GetActionStatus(FFXIVClientStructs.FFXIV.Client.Game.ActionType.Item, item.ID).ToString());
+ ImGui.Text("Status HQ: " + FFXIVClientStructs.FFXIV.Client.Game.ActionManager.Instance()->GetActionStatus(FFXIVClientStructs.FFXIV.Client.Game.ActionType.Item, item.ID + 1000000).ToString());
+ var remain = FFXIVClientStructs.FFXIV.Client.Game.ActionManager.Instance()->GetRecastTime(FFXIVClientStructs.FFXIV.Client.Game.ActionType.Item, item.ID) - FFXIVClientStructs.FFXIV.Client.Game.ActionManager.Instance()->GetRecastTimeElapsed(FFXIVClientStructs.FFXIV.Client.Game.ActionType.Item, item.ID);
+ ImGui.Text("remain: " + remain.ToString());
+ ImGui.Text("CanUse: " + item.CanUse(out _, true).ToString());
- ImGui.TextWrapped(UiString.ConfigWindow_Actions_ConditionDescription.Local());
- _sequencerList?.Draw();
+ if (item is HpPotionItem healPotionItem)
+ {
+ ImGui.Text("MaxHP:" + healPotionItem.MaxHp.ToString());
+ }
+ }
+ catch
+ {
+
+ }
+ }
}
}
diff --git a/RotationSolver/Updaters/SocialUpdater.cs b/RotationSolver/Updaters/SocialUpdater.cs
index 06c4c5300..f780adba3 100644
--- a/RotationSolver/Updaters/SocialUpdater.cs
+++ b/RotationSolver/Updaters/SocialUpdater.cs
@@ -20,6 +20,9 @@ namespace RotationSolver.Updaters;
internal class SocialUpdater
{
+#if DEBUG
+#else
+
private static readonly List _macroToAuthor =
[
"blush",
@@ -30,6 +33,7 @@ internal class SocialUpdater
"cheer",
"stroke",
];
+#endif
private static readonly HashSet saidAuthors = [];
@@ -68,7 +72,7 @@ internal static void Enable()
static async void DutyState_DutyCompleted(object? sender, ushort e)
{
- if (DataCenter.PartyMembers.Count() < 2) return;
+ if (DataCenter.PartyMembers.Length < 2) return;
await Task.Delay(new Random().Next(4000, 6000));
@@ -91,6 +95,10 @@ static void ClientState_TerritoryChanged(ushort id)
DataCenter.Territory = territory;
+#if DEBUG
+ Svc.Log.Debug($"Move to {DataCenter.TerritoryName} ({id})");
+#endif
+
_dutyRotations ??= [..RotationUpdater.TryGetTypes(typeof(SocialUpdater).Assembly)
.Where(t => t.IsAssignableTo(typeof(DutyRotation)) && !t.IsAbstract)];