From 7924c557b65c725ccaaae2129cd047d30141097c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A7=8B=E6=B0=B4?= <1123993881@qq.com> Date: Tue, 27 Feb 2024 09:33:30 +0800 Subject: [PATCH] fix: action condition can use fix. --- Directory.Build.props | 2 +- Resources/RotationSolverRecord.json | 2 +- RotationSolver.Basic/Actions/BaseAction.cs | 60 ++++++++++++-- RotationSolver.Basic/Actions/IBaseAction.cs | 6 +- .../Conditions/ActionCondition.cs | 2 +- RotationSolver.Basic/Data/ActionOption.cs | 83 ------------------- RotationSolver.Basic/Data/CanUseOption.cs | 61 ++++++++++++++ .../Rotations/Basic/DancerRotation.cs | 8 +- .../Rotations/Basic/DragoonRotation.cs | 2 +- .../Rotations/Basic/MonkRotation.cs | 2 +- .../Rotations/Basic/ScholarRotation.cs | 2 +- .../Rotations/CustomRotation_Ability.cs | 6 +- .../Rotations/CustomRotation_GCD.cs | 4 +- RotationSolver/UI/ConditionDrawer.cs | 57 ++++++------- RotationSolver/UI/ControlWindow.cs | 2 +- RotationSolver/UI/RotationConfigWindow.cs | 4 +- RotationSolver/Updaters/ActionUpdater.cs | 2 +- 17 files changed, 161 insertions(+), 144 deletions(-) delete mode 100644 RotationSolver.Basic/Data/ActionOption.cs create mode 100644 RotationSolver.Basic/Data/CanUseOption.cs diff --git a/Directory.Build.props b/Directory.Build.props index 2f09d09a7..e1e36a74f 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -3,7 +3,7 @@ net7.0-windows enable ArchiTed - 4.0.3.3 + 4.0.3.4 x64 AnyCPU latest diff --git a/Resources/RotationSolverRecord.json b/Resources/RotationSolverRecord.json index 24b2ffcde..002bca4f1 100644 --- a/Resources/RotationSolverRecord.json +++ b/Resources/RotationSolverRecord.json @@ -1,5 +1,5 @@ { - "ClickingCount": 86231, + "ClickingCount": 86236, "SayingHelloCount": 75, "SaidUsers": [] } \ No newline at end of file diff --git a/RotationSolver.Basic/Actions/BaseAction.cs b/RotationSolver.Basic/Actions/BaseAction.cs index 884bed93b..94010c013 100644 --- a/RotationSolver.Basic/Actions/BaseAction.cs +++ b/RotationSolver.Basic/Actions/BaseAction.cs @@ -6,51 +6,72 @@ namespace RotationSolver.Basic.Actions; public class BaseAction : IBaseAction { + /// public TargetResult? Target { get; set; } = null; + + /// public TargetResult? PreviewTarget { get; private set; } = null; + /// public Action Action { get; } + /// public ActionTargetInfo TargetInfo { get; } + /// public ActionBasicInfo Info { get; } + /// public ActionCooldownInfo Cooldown { get; } ICooldown IAction.Cooldown => Cooldown; + /// public uint ID => Info.ID; + /// public uint AdjustedID => Info.AdjustedID; + /// public float AnimationLockTime => Info.AnimationLockTime; + /// public uint SortKey => Cooldown.CoolDownGroup; - public bool IsCoolingDown => Cooldown.IsCoolingDown; - + /// public uint IconID => ID == 3 ? 104 : Info.IconID; + /// public string Name => Info.Name; + + /// public string Description => string.Empty; + /// public byte Level => Info.Level; + + /// public bool IsEnabled { get => Config.IsEnabled; set => Config.IsEnabled = value; } + + /// public bool IsInCooldown { get => Config.IsInCooldown; set => Config.IsInCooldown = value; } + /// public bool EnoughLevel => Info.EnoughLevel; + /// public ActionSetting Setting { get; set; } + /// public ActionConfig Config { get @@ -68,6 +89,11 @@ public ActionConfig Config } } + /// + /// The default constructor + /// + /// action id + /// is this action a duty action public BaseAction(ActionID actionID, bool isDutyAction = false) { Action = Service.GetSheet().GetRow((uint)actionID)!; @@ -78,8 +104,9 @@ public BaseAction(ActionID actionID, bool isDutyAction = false) Setting = new(); } - public bool CanUse(out IAction act, bool skipStatusProvideCheck = false, bool skipCombo = false, bool ignoreCastingCheck = false, - bool isEmpty = false, bool onLastAbility = false, bool ignoreClippingCheck = false, bool skipAoeCheck = false, byte gcdCountForAbility = 0) + /// + public bool CanUse(out IAction act, bool skipStatusProvideCheck = false, bool skipCombo = false, bool skipCastingCheck = false, + bool usedUp = false, bool onLastAbility = false, bool skipClippingCheck = false, bool skipAoeCheck = false, byte gcdCountForAbility = 0) { act = this!; @@ -87,20 +114,20 @@ public bool CanUse(out IAction act, bool skipStatusProvideCheck = false, bool sk if (IBaseAction.ActionPreview) { - ignoreCastingCheck = ignoreClippingCheck = true; + skipCastingCheck = skipClippingCheck = true; } if (IBaseAction.AllEmpty) { - isEmpty = true; + usedUp = true; } if (IBaseAction.IgnoreClipping) { - ignoreClippingCheck = true; + skipClippingCheck = true; } - if (!Info.BasicCheck(skipStatusProvideCheck, skipCombo, ignoreCastingCheck)) return false; + if (!Info.BasicCheck(skipStatusProvideCheck, skipCombo, skipCastingCheck)) return false; - if (!Cooldown.CooldownCheck(isEmpty, onLastAbility, ignoreClippingCheck, gcdCountForAbility)) return false; + if (!Cooldown.CooldownCheck(usedUp, onLastAbility, skipClippingCheck, gcdCountForAbility)) return false; if (Setting.IsMeleeRange && IActionHelper.IsLastAction(IActionHelper.MovingActions)) return false; //No range actions after moving. @@ -116,6 +143,21 @@ public bool CanUse(out IAction act, bool skipStatusProvideCheck = false, bool sk return true; } + /// + public bool CanUse(out IAction act, CanUseOption option, byte gcdCountForAbility = 0) + { + return CanUse(out act, + option.HasFlag(CanUseOption.SkipStatusProvideCheck), + option.HasFlag(CanUseOption.SkipCombo), + option.HasFlag(CanUseOption.SkipCastingCheck), + option.HasFlag(CanUseOption.UsedUp), + option.HasFlag(CanUseOption.OnLastAbility), + option.HasFlag(CanUseOption.SkipClippingCheck), + option.HasFlag(CanUseOption.SkipAoeCheck), + gcdCountForAbility); + } + + /// public unsafe bool Use() { if (!Target.HasValue) return false; diff --git a/RotationSolver.Basic/Actions/IBaseAction.cs b/RotationSolver.Basic/Actions/IBaseAction.cs index 7e3a45e84..e9e73ad1c 100644 --- a/RotationSolver.Basic/Actions/IBaseAction.cs +++ b/RotationSolver.Basic/Actions/IBaseAction.cs @@ -21,6 +21,8 @@ public interface IBaseAction : IAction ActionSetting Setting { get; set; } internal ActionConfig Config { get; } - bool CanUse(out IAction act, bool skipStatusProvideCheck = false, bool skipCombo = false, bool ignoreCastingCheck = false, - bool isEmpty = false, bool onLastAbility = false, bool ignoreClippingCheck = false, bool skipAoeCheck = false, byte gcdCountForAbility = 0); + bool CanUse(out IAction act, bool skipStatusProvideCheck = false, bool skipCombo = false, bool skipCastingCheck = false, + bool usedUp = false, bool onLastAbility = false, bool skipClippingCheck = false, bool skipAoeCheck = false, byte gcdCountForAbility = 0); + + bool CanUse(out IAction act, CanUseOption option, byte gcdCountForAbility = 0); } diff --git a/RotationSolver.Basic/Configuration/Conditions/ActionCondition.cs b/RotationSolver.Basic/Configuration/Conditions/ActionCondition.cs index 2e82cf63b..7f1c9ef6e 100644 --- a/RotationSolver.Basic/Configuration/Conditions/ActionCondition.cs +++ b/RotationSolver.Basic/Configuration/Conditions/ActionCondition.cs @@ -37,7 +37,7 @@ protected override bool IsTrueInside(ICustomRotation rotation) return !_action.Cooldown.WillHaveOneChargeGCD((uint)Param1, Param2); // Smaller case ActionConditionType.CanUse: - return _action.CanUse(out _); + return _action.CanUse(out _, (CanUseOption)Param1); case ActionConditionType.EnoughLevel: return _action.EnoughLevel; diff --git a/RotationSolver.Basic/Data/ActionOption.cs b/RotationSolver.Basic/Data/ActionOption.cs deleted file mode 100644 index 56ec31966..000000000 --- a/RotationSolver.Basic/Data/ActionOption.cs +++ /dev/null @@ -1,83 +0,0 @@ -namespace RotationSolver.Basic.Data; - -/// -/// The type of action. -/// -[Flags] -public enum ActionOption : byte -{ - /// - /// The normal one. - /// - None = 0, - - /// - /// is a friendly or supporting action - /// - Friendly = 1 << 0, - - /// - /// is hot or dot action - /// - Eot = 1 << 1, - - /// - /// end special after using it - /// - EndSpecial = 1 << 2, - - /// - /// Is a GCD action. - /// - GeneralGCD = 1 << 3, - - /// - /// Is a simple gcd action, without other cooldown. - /// - RealGCD = 1 << 4, - - /// - /// The duty action - /// - DutyAction = 1 << 5, - - /// - /// flag to check this action is heal. - /// - HealFlag = 1 << 6, - - /// - /// Is the action a resource taken action. - /// - UseResources = 1 << 7, - - /// - /// Dot action - /// - Dot = Eot, - - /// - /// Attack action - /// - Attack = None, - - /// - /// Heal action - /// - Heal = Friendly | HealFlag, - - /// - /// Defense action (you need to change the targeting strategy.) - /// - Defense = Friendly, - - /// - /// Hot action - /// - Hot = Heal | Eot, - - /// - /// Some buff - /// - Buff = Friendly, -} diff --git a/RotationSolver.Basic/Data/CanUseOption.cs b/RotationSolver.Basic/Data/CanUseOption.cs new file mode 100644 index 000000000..d26a085b7 --- /dev/null +++ b/RotationSolver.Basic/Data/CanUseOption.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace RotationSolver.Basic.Data; + +/// +/// the option for the +/// +[Flags] +public enum CanUseOption : byte +{ + /// + /// None. + /// + None, + + /// + /// Skip Status Provide Check + /// + [Description("Skip Status Provide Check")] + SkipStatusProvideCheck = 1 << 0, + + /// + /// Skip Combo Check + /// + [Description("Skip Combo Check")] + SkipCombo = 1 << 1, + + /// + /// Skip Casting and Moving Check + /// + [Description("Skip Casting and Moving Check")] + SkipCastingCheck = 1 << 2, + + /// + /// Is it used up all stacks + /// + [Description("Is it used up all stacks")] + UsedUp = 1 << 3, + + /// + /// Is it on the last ability + /// + [Description("Is it on the last ability")] + OnLastAbility = 1 << 4, + + /// + /// Skip clipping Check + /// + [Description("Skip clipping Check")] + SkipClippingCheck = 1 << 5, + + /// + /// Skip aoe Check + /// + [Description("Skip aoe Check")] + SkipAoeCheck = 1 << 6, +} diff --git a/RotationSolver.Basic/Rotations/Basic/DancerRotation.cs b/RotationSolver.Basic/Rotations/Basic/DancerRotation.cs index b75604136..36dae8fdd 100644 --- a/RotationSolver.Basic/Rotations/Basic/DancerRotation.cs +++ b/RotationSolver.Basic/Rotations/Basic/DancerRotation.cs @@ -265,7 +265,7 @@ protected bool ExecuteStepGCD(out IAction? act) [RotationDesc(ActionID.EnAvantPvE)] protected sealed override bool MoveForwardAbility(out IAction act) { - if (EnAvantPvE.CanUse(out act, isEmpty:true)) return true; + if (EnAvantPvE.CanUse(out act, usedUp:true)) return true; return false; } @@ -277,8 +277,8 @@ protected sealed override bool MoveForwardAbility(out IAction act) [RotationDesc(ActionID.CuringWaltzPvE, ActionID.ImprovisationPvE)] protected sealed override bool HealAreaAbility(out IAction act) { - if (CuringWaltzPvE.CanUse(out act, isEmpty: true)) return true; - if (ImprovisationPvE.CanUse(out act, isEmpty: true)) return true; + if (CuringWaltzPvE.CanUse(out act, usedUp: true)) return true; + if (ImprovisationPvE.CanUse(out act, usedUp: true)) return true; return false; } @@ -290,7 +290,7 @@ protected sealed override bool HealAreaAbility(out IAction act) [RotationDesc(ActionID.ShieldSambaPvE)] protected sealed override bool DefenseAreaAbility(out IAction act) { - if (ShieldSambaPvE.CanUse(out act, isEmpty: true)) return true; + if (ShieldSambaPvE.CanUse(out act, usedUp: true)) return true; return false; } } diff --git a/RotationSolver.Basic/Rotations/Basic/DragoonRotation.cs b/RotationSolver.Basic/Rotations/Basic/DragoonRotation.cs index 64a4ab032..889025079 100644 --- a/RotationSolver.Basic/Rotations/Basic/DragoonRotation.cs +++ b/RotationSolver.Basic/Rotations/Basic/DragoonRotation.cs @@ -145,7 +145,7 @@ protected sealed override bool DefenseAreaAbility(out IAction? act) [RotationDesc(ActionID.ElusiveJumpPvE)] protected override bool MoveBackAbility(out IAction? act) { - if (ElusiveJumpPvE.CanUse(out act, ignoreClippingCheck: true)) return true; + if (ElusiveJumpPvE.CanUse(out act, skipClippingCheck: true)) return true; return base.MoveBackAbility(out act); } } \ No newline at end of file diff --git a/RotationSolver.Basic/Rotations/Basic/MonkRotation.cs b/RotationSolver.Basic/Rotations/Basic/MonkRotation.cs index 47cc59d41..1bf588125 100644 --- a/RotationSolver.Basic/Rotations/Basic/MonkRotation.cs +++ b/RotationSolver.Basic/Rotations/Basic/MonkRotation.cs @@ -131,7 +131,7 @@ protected sealed override bool HealAreaAbility(out IAction? act) [RotationDesc(ActionID.RiddleOfEarthPvE)] protected sealed override bool DefenseSingleAbility(out IAction? act) { - if (RiddleOfEarthPvE.CanUse(out act, isEmpty: true)) return true; + if (RiddleOfEarthPvE.CanUse(out act, usedUp: true)) return true; return base.DefenseSingleAbility(out act); } } diff --git a/RotationSolver.Basic/Rotations/Basic/ScholarRotation.cs b/RotationSolver.Basic/Rotations/Basic/ScholarRotation.cs index 5b3c9aa3a..b4f739574 100644 --- a/RotationSolver.Basic/Rotations/Basic/ScholarRotation.cs +++ b/RotationSolver.Basic/Rotations/Basic/ScholarRotation.cs @@ -145,7 +145,7 @@ static partial void ModifyDeploymentTacticsPvE(ref ActionSetting setting) [RotationDesc(ActionID.ExpedientPvE)] protected override bool SpeedAbility(out IAction? act) { - if (InCombat && ExpedientPvE.CanUse(out act, isEmpty: true)) return true; + if (InCombat && ExpedientPvE.CanUse(out act, usedUp: true)) return true; return base.SpeedAbility(out act); } } \ No newline at end of file diff --git a/RotationSolver.Basic/Rotations/CustomRotation_Ability.cs b/RotationSolver.Basic/Rotations/CustomRotation_Ability.cs index 60b0866d9..809f2e68b 100644 --- a/RotationSolver.Basic/Rotations/CustomRotation_Ability.cs +++ b/RotationSolver.Basic/Rotations/CustomRotation_Ability.cs @@ -8,7 +8,7 @@ private bool Ability(IAction nextGCD, out IAction? act) IBaseAction.ForceEnable = true; if (act is IBaseAction a && a != null && !a.Info.IsRealGCD && a.CanUse(out _, - isEmpty: true, skipAoeCheck: true)) return true; + usedUp: true, skipAoeCheck: true)) return true; IBaseAction.ForceEnable = false; if (act is IBaseItem i && i.CanUse(out _, true)) return true; @@ -45,7 +45,7 @@ private bool Ability(IAction nextGCD, out IAction? act) if (DataCenter.MergedStatus.HasFlag(AutoStatus.Positional) && role == JobRole.Melee && !(Player?.HasStatus(false, StatusHelper.NoPositionalStatus) ?? true)) { - if (TrueNorthPvE.CanUse(out act, isEmpty: true, onLastAbility: true)) return true; + if (TrueNorthPvE.CanUse(out act, usedUp: true, onLastAbility: true)) return true; } IBaseAction.TargetOverride = TargetType.Heal; @@ -266,7 +266,7 @@ protected virtual bool EmergencyAbility(IAction nextGCD, out IAction? act) { if (action.Setting.EnemyPositional != action.Target?.Target?.FindEnemyPositional() && (action.Target?.Target?.HasPositional() ?? false)) { - if (TrueNorthPvE.CanUse(out act, isEmpty: true, onLastAbility: true)) return true; + if (TrueNorthPvE.CanUse(out act, usedUp: true, onLastAbility: true)) return true; } } } diff --git a/RotationSolver.Basic/Rotations/CustomRotation_GCD.cs b/RotationSolver.Basic/Rotations/CustomRotation_GCD.cs index b6257690d..f362116c0 100644 --- a/RotationSolver.Basic/Rotations/CustomRotation_GCD.cs +++ b/RotationSolver.Basic/Rotations/CustomRotation_GCD.cs @@ -11,7 +11,7 @@ partial class CustomRotation IBaseAction.ForceEnable = true; if (act is IBaseAction a && a != null && a.Info.IsRealGCD - && a.CanUse(out _, isEmpty: true, skipAoeCheck: true)) return act; + && a.CanUse(out _, usedUp: true, skipAoeCheck: true)) return act; IBaseAction.ForceEnable = false; IBaseAction.ShouldEndSpecial = true; @@ -174,7 +174,7 @@ private bool RaiseSpell(out IAction? act, bool mustUse) bool RaiseAction(out IAction act, bool ignoreCastingCheck) { - if (Player.CurrentMp > Service.Config.LessMPNoRaise && (Raise?.CanUse(out act, ignoreCastingCheck: ignoreCastingCheck) ?? false)) return true; + if (Player.CurrentMp > Service.Config.LessMPNoRaise && (Raise?.CanUse(out act, skipCastingCheck: ignoreCastingCheck) ?? false)) return true; act = null!; return false; diff --git a/RotationSolver/UI/ConditionDrawer.cs b/RotationSolver/UI/ConditionDrawer.cs index 120a02789..cfbfee8c7 100644 --- a/RotationSolver/UI/ConditionDrawer.cs +++ b/RotationSolver/UI/ConditionDrawer.cs @@ -435,37 +435,32 @@ private static void DrawAfter(this ActionCondition actionCondition, ICustomRotat } break; - case ActionConditionType.CanUse: //TODO: canuse - //var popUpId = "Can Use Id" + actionCondition.GetHashCode().ToString(); - //var option = (CanUseOption)actionCondition.Param1; - - //if (ImGui.Selectable($"{option}##CanUse{actionCondition.GetHashCode()}")) - //{ - // if (!ImGui.IsPopupOpen(popUpId)) ImGui.OpenPopup(popUpId); - //} - - //using (var popUp = ImRaii.Popup(popUpId)) - //{ - // if (popUp.Success) - // { - // var showedValues = Enum.GetValues().Where(i => i.GetAttribute() == null); - - // foreach (var value in showedValues) - // { - // var b = option.HasFlag(value); - // if (ImGui.Checkbox(value.ToString(), ref b)) - // { - // option ^= value; - // actionCondition.Param1 = (int)option; - // } - // } - // } - //} - - //if (DrawDragInt($"{LocalizationManager._rightLang.ActionSequencer_AOECount}##AOECount{actionCondition.GetHashCode()}", ref actionCondition.Param2)) - //{ - // actionCondition.Param2 = Math.Max(0, actionCondition.Param2); - //} + case ActionConditionType.CanUse: + var popUpId = "Can Use Id" + actionCondition.GetHashCode().ToString(); + var option = (CanUseOption)actionCondition.Param1; + + if (ImGui.Selectable($"{option}##CanUse{actionCondition.GetHashCode()}")) + { + if (!ImGui.IsPopupOpen(popUpId)) ImGui.OpenPopup(popUpId); + } + + using (var popUp = ImRaii.Popup(popUpId)) + { + if (popUp.Success) + { + var showedValues = Enum.GetValues().Where(i => i.GetAttribute() == null); + + foreach (var value in showedValues) + { + var b = option.HasFlag(value); + if (ImGui.Checkbox(value.Local(), ref b)) + { + option ^= value; + actionCondition.Param1 = (int)option; + } + } + } + } break; case ActionConditionType.CurrentCharges: diff --git a/RotationSolver/UI/ControlWindow.cs b/RotationSolver/UI/ControlWindow.cs index b9736ded4..20a5d22e1 100644 --- a/RotationSolver/UI/ControlWindow.cs +++ b/RotationSolver/UI/ControlWindow.cs @@ -406,7 +406,7 @@ internal static (Vector2, Vector2) DrawIAction(IAction? action, float width, flo if (action is IBaseAction act) { IBaseAction.ForceEnable = true; - canDoIt = act.CanUse(out _, isEmpty: true, ignoreClippingCheck: true, skipAoeCheck: true); + canDoIt = act.CanUse(out _, usedUp: true, skipClippingCheck: true, skipAoeCheck: true); IBaseAction.ForceEnable = false; } else if (action is IBaseItem item) diff --git a/RotationSolver/UI/RotationConfigWindow.cs b/RotationSolver/UI/RotationConfigWindow.cs index e3c46a23f..fdaeb9949 100644 --- a/RotationSolver/UI/RotationConfigWindow.cs +++ b/RotationSolver/UI/RotationConfigWindow.cs @@ -1424,8 +1424,8 @@ private static unsafe void DrawActions() ImGui.Text("Recast One: " + action.Cooldown.RecastTimeOneChargeRaw.ToString()); ImGui.Text("Recast Elapsed: " + action.Cooldown.RecastTimeElapsedRaw.ToString()); - ImGui.Text($"Can Use: {action.CanUse(out _, ignoreClippingCheck: true)} "); - ImGui.Text("IgnoreCastCheck:" + action.CanUse(out _, ignoreClippingCheck: true, ignoreCastingCheck : true).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); diff --git a/RotationSolver/Updaters/ActionUpdater.cs b/RotationSolver/Updaters/ActionUpdater.cs index d54490d75..c70a51979 100644 --- a/RotationSolver/Updaters/ActionUpdater.cs +++ b/RotationSolver/Updaters/ActionUpdater.cs @@ -44,7 +44,7 @@ internal static void UpdateNextAction() { return !action.Setting.IsFriendly && action.Config.IsInMistake && action.Setting.TargetType != TargetType.Move - && action.CanUse(out _, isEmpty: true, skipStatusProvideCheck: true, ignoreClippingCheck: true, skipAoeCheck: true); + && action.CanUse(out _, usedUp: true, skipStatusProvideCheck: true, skipClippingCheck: true, skipAoeCheck: true); } return false; });