From 5f89217e47d30229f58cfc85be00456454712524 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A7=8B=E6=B0=B4?= <1123993881@qq.com> Date: Sat, 1 Apr 2023 22:46:17 +0800 Subject: [PATCH] feat: add an AutoStatus showcase on Control Window. --- .../Configuration/PluginConfiguration.cs | 2 +- RotationSolver.Basic/Data/AutoStatus.cs | 18 ++++++++++ RotationSolver.Basic/DataCenter.cs | 13 ++++++++ .../Rotations/Basic/DRK_Base.cs | 2 +- .../Rotations/Basic/GNB_Base.cs | 2 +- .../Rotations/Basic/PLD_Base.cs | 2 +- .../Rotations/Basic/WAR_Base.cs | 2 +- .../Rotations/CustomRotation_Ability.cs | 30 +++++++++-------- .../Rotations/CustomRotation_Actions.cs | 2 +- .../Rotations/CustomRotation_GCD.cs | 33 ++++++++++++------- .../Rotations/CustomRotation_Invoke.cs | 2 +- RotationSolver.Default/Melee/NIN_Default.cs | 8 +---- RotationSolver/UI/ControlWindow.cs | 2 ++ .../UI/RotationConfigWindow_Param.cs | 2 +- RotationSolver/Updaters/TargetUpdater.cs | 13 +++++--- 15 files changed, 89 insertions(+), 44 deletions(-) create mode 100644 RotationSolver.Basic/Data/AutoStatus.cs diff --git a/RotationSolver.Basic/Configuration/PluginConfiguration.cs b/RotationSolver.Basic/Configuration/PluginConfiguration.cs index e885fa303..927205ea4 100644 --- a/RotationSolver.Basic/Configuration/PluginConfiguration.cs +++ b/RotationSolver.Basic/Configuration/PluginConfiguration.cs @@ -54,7 +54,7 @@ public class PluginConfiguration : IPluginConfiguration public bool RaisePlayerBySwift = true; public bool RaiseBrinkOfDeath = true; public int LessMPNoRaise = 0; - public bool AutoShield = true; + public bool AutoTankStance = true; public bool AddEnemyListToHostile = true; public bool UseAOEWhenManual = false; public bool UseAOEAction = true; diff --git a/RotationSolver.Basic/Data/AutoStatus.cs b/RotationSolver.Basic/Data/AutoStatus.cs new file mode 100644 index 000000000..10ccc0b1e --- /dev/null +++ b/RotationSolver.Basic/Data/AutoStatus.cs @@ -0,0 +1,18 @@ +namespace RotationSolver.Basic.Data; + +[Flags] +public enum AutoStatus : ushort +{ + None = 0, + Interrupt = 1 << 0, + TankStance = 1 << 1, + Provoke = 1 << 2, + DefenseSingle = 1 << 3, + DefenseArea = 1 << 4, + HealSingleAbility = 1 << 5, + HealSingleSpell = 1 << 6, + HealAreaAbility = 1 << 7, + HealAreaSpell = 1 << 8, + Raise = 1 << 9, + Esuna = 1 << 10, +} diff --git a/RotationSolver.Basic/DataCenter.cs b/RotationSolver.Basic/DataCenter.cs index 5c2c5a8b2..1e473aec4 100644 --- a/RotationSolver.Basic/DataCenter.cs +++ b/RotationSolver.Basic/DataCenter.cs @@ -16,6 +16,19 @@ namespace RotationSolver.Basic; public static class DataCenter { public static bool InHighEndDuty { get; set; } = false; + public static AutoStatus AutoStatus { get; private set; } = AutoStatus.None; + public static bool SetAutoStatus(AutoStatus status, bool keep) + { + if (keep) + { + AutoStatus |= status; + } + else + { + AutoStatus &= ~status; + } + return keep; + } private static List NextActs = new List(); public static IBaseAction TimeLineAction { internal get; set; } diff --git a/RotationSolver.Basic/Rotations/Basic/DRK_Base.cs b/RotationSolver.Basic/Rotations/Basic/DRK_Base.cs index 2234ca7d6..ccd26a143 100644 --- a/RotationSolver.Basic/Rotations/Basic/DRK_Base.cs +++ b/RotationSolver.Basic/Rotations/Basic/DRK_Base.cs @@ -46,7 +46,7 @@ protected static bool DarkSideEndAfterGCD(uint gctCount = 0, uint abilityCount = } public sealed override ClassJobID[] JobIDs => new ClassJobID[] { ClassJobID.DarkKnight }; - private sealed protected override IBaseAction Shield => Grit; + private sealed protected override IBaseAction TankStance => Grit; /// /// 重斩 diff --git a/RotationSolver.Basic/Rotations/Basic/GNB_Base.cs b/RotationSolver.Basic/Rotations/Basic/GNB_Base.cs index 60a0df639..efb6a01f2 100644 --- a/RotationSolver.Basic/Rotations/Basic/GNB_Base.cs +++ b/RotationSolver.Basic/Rotations/Basic/GNB_Base.cs @@ -26,7 +26,7 @@ public abstract class GNB_Base : CustomRotation protected static byte AmmoComboStep => JobGauge.AmmoComboStep; public sealed override ClassJobID[] JobIDs => new ClassJobID[] { ClassJobID.Gunbreaker }; - private sealed protected override IBaseAction Shield => RoyalGuard; + private sealed protected override IBaseAction TankStance => RoyalGuard; protected override bool CanHealSingleSpell => false; protected override bool CanHealAreaSpell => false; diff --git a/RotationSolver.Basic/Rotations/Basic/PLD_Base.cs b/RotationSolver.Basic/Rotations/Basic/PLD_Base.cs index 47f26ccf0..c953153c0 100644 --- a/RotationSolver.Basic/Rotations/Basic/PLD_Base.cs +++ b/RotationSolver.Basic/Rotations/Basic/PLD_Base.cs @@ -26,7 +26,7 @@ public abstract class PLD_Base : CustomRotation public sealed override ClassJobID[] JobIDs => new ClassJobID[] { ClassJobID.Paladin, ClassJobID.Gladiator }; - private sealed protected override IBaseAction Shield => IronWill; + private sealed protected override IBaseAction TankStance => IronWill; protected override bool CanHealSingleSpell => DataCenter.PartyMembers.Count() == 1 && base.CanHealSingleSpell; protected override bool CanHealAreaAbility => false; diff --git a/RotationSolver.Basic/Rotations/Basic/WAR_Base.cs b/RotationSolver.Basic/Rotations/Basic/WAR_Base.cs index aa798ff0e..fced92951 100644 --- a/RotationSolver.Basic/Rotations/Basic/WAR_Base.cs +++ b/RotationSolver.Basic/Rotations/Basic/WAR_Base.cs @@ -16,7 +16,7 @@ public abstract class WAR_Base : CustomRotation protected static byte BeastGauge => JobGauge.BeastGauge; public sealed override ClassJobID[] JobIDs => new ClassJobID[] { ClassJobID.Warrior, ClassJobID.Marauder }; - private sealed protected override IBaseAction Shield => Defiance; + private sealed protected override IBaseAction TankStance => Defiance; /// /// �ػ� diff --git a/RotationSolver.Basic/Rotations/CustomRotation_Ability.cs b/RotationSolver.Basic/Rotations/CustomRotation_Ability.cs index 95e182659..9ab90d3a3 100644 --- a/RotationSolver.Basic/Rotations/CustomRotation_Ability.cs +++ b/RotationSolver.Basic/Rotations/CustomRotation_Ability.cs @@ -56,7 +56,9 @@ private bool Ability(byte abilitiesRemaining, IAction nextGCD, out IAction act, private bool InterruptAbility(JobRole role, out IAction act) { act = null; - if (!DataCenter.CanInterruptTargets.Any()) return false; + if (!DataCenter.SetAutoStatus(AutoStatus.Interrupt, DataCenter.CanInterruptTargets.Any())) + return false; + switch (role) { @@ -87,16 +89,15 @@ private bool ShirkOrShield(JobRole role, SpecialCommandType specialType, out IAc break; case SpecialCommandType.EsunaStanceNorth: - if (Shield.CanUse(out act)) return true; + if (TankStance.CanUse(out act)) return true; break; } - if (Service.Config.AutoShield) + if (DataCenter.SetAutoStatus(AutoStatus.TankStance, Service.Config.AutoTankStance + && !DataCenter.AllianceTanks.Any(t => t.CurrentHp != 0 && t.HasStatus(false, StatusHelper.TankStanceStatus)) + && !HasTankStance && TankStance.CanUse(out act))) { - if (!DataCenter.AllianceTanks.Any(t => t.CurrentHp != 0 && t.HasStatus(false, StatusHelper.TankStanceStatus))) - { - if (!HasTankStance && Shield.CanUse(out act)) return true; - } + return true; } return false; @@ -155,16 +156,19 @@ private bool GeneralHealAbility(byte abilitiesRemaining, SpecialCommandType spec private bool AutoDefense(byte abilitiesRemaining, JobRole role, bool helpDefenseAOE, bool helpDefenseSingle, out IAction act) { act = null; - - if (!InCombat || !HasHostilesInRange) return false; + if (!InCombat || !HasHostilesInRange) + { + DataCenter.SetAutoStatus(AutoStatus.Provoke, false); + return false; + } //Auto Provoke - if (role == JobRole.Tank + if (DataCenter.SetAutoStatus(AutoStatus.Provoke, role == JobRole.Tank && (Service.Config.AutoProvokeForTank || DataCenter.AllianceTanks.Count() < 2) - && TargetFilter.ProvokeTarget(DataCenter.HostileTargets, true).Count() != DataCenter.HostileTargets.Count()) - + && TargetFilter.ProvokeTarget(DataCenter.HostileTargets, true).Count() != DataCenter.HostileTargets.Count())) { - if (!HasTankStance && Shield.CanUse(out act)) return true; + + if (!HasTankStance && TankStance.CanUse(out act)) return true; if (Provoke.CanUse(out act, CanUseOption.MustUse)) return true; } diff --git a/RotationSolver.Basic/Rotations/CustomRotation_Actions.cs b/RotationSolver.Basic/Rotations/CustomRotation_Actions.cs index 456b0aee8..a774fb6de 100644 --- a/RotationSolver.Basic/Rotations/CustomRotation_Actions.cs +++ b/RotationSolver.Basic/Rotations/CustomRotation_Actions.cs @@ -220,7 +220,7 @@ internal RoleAction(ActionID actionID, JobRole[] roles, bool isFriendly = false, }; private protected virtual IBaseAction Raise => null; - private protected virtual IBaseAction Shield => null; + private protected virtual IBaseAction TankStance => null; /// /// 当前这个类所有的BaseAction diff --git a/RotationSolver.Basic/Rotations/CustomRotation_GCD.cs b/RotationSolver.Basic/Rotations/CustomRotation_GCD.cs index 23edb47ce..7e5242a8f 100644 --- a/RotationSolver.Basic/Rotations/CustomRotation_GCD.cs +++ b/RotationSolver.Basic/Rotations/CustomRotation_GCD.cs @@ -35,13 +35,14 @@ private IAction GCD(byte abilityRemain, bool helpDefenseAOE, bool helpDefenseSin if (specialType == SpecialCommandType.DefenseSingle && DefenseSingleGCD(out act)) return act; //Auto Defense - if (helpDefenseAOE && DefenseAreaGCD(out act)) return act; - if (helpDefenseSingle && DefenseSingleGCD(out act)) return act; + if (DataCenter.SetAutoStatus(AutoStatus.DefenseArea, helpDefenseAOE) && DefenseAreaGCD(out act)) return act; + if (DataCenter.SetAutoStatus(AutoStatus.DefenseSingle, helpDefenseSingle) && DefenseSingleGCD(out act)) return act; //Esuna - if ((specialType == SpecialCommandType.EsunaStanceNorth || !HasHostilesInRange || Service.Config.EsunaAll) + if (DataCenter.SetAutoStatus(AutoStatus.Esuna, (specialType == SpecialCommandType.EsunaStanceNorth + || !HasHostilesInRange || Service.Config.EsunaAll) && DataCenter.WeakenPeople.Any() - || DataCenter.DyingPeople.Any()) + || DataCenter.DyingPeople.Any())) { if (Job.GetJobRole() == JobRole.Healer && Esuna.CanUse(out act, CanUseOption.MustUse)) return act; } @@ -56,33 +57,41 @@ private IAction GCD(byte abilityRemain, bool helpDefenseAOE, bool helpDefenseSin private bool RaiseSpell(SpecialCommandType specialType, out IAction act, byte actabilityRemain, bool mustUse) { act = null; - if (Raise == null) return false; - if (Player.CurrentMp <= Service.Config.LessMPNoRaise) return false; + if (Raise == null || Player.CurrentMp <= Service.Config.LessMPNoRaise) + { + return DataCenter.SetAutoStatus(AutoStatus.Raise, false); + } - if (specialType == SpecialCommandType.RaiseShirk && DataCenter.DeathPeopleAll.Any()) return true; + if (specialType == SpecialCommandType.RaiseShirk && DataCenter.DeathPeopleAll.Any()) + { + return true; + } if ((Service.Config.RaiseAll ? DataCenter.DeathPeopleAll.Any() : DataCenter.DeathPeopleParty.Any()) && Raise.CanUse(out act)) { if (HasSwift) { - return true; + return DataCenter.SetAutoStatus(AutoStatus.Raise, true); } else if (mustUse) { - if(Swiftcast.CanUse(out act)) return true; + if(Swiftcast.CanUse(out act)) + { + return DataCenter.SetAutoStatus(AutoStatus.Raise, true); + } else { act = Raise; - return true; + return DataCenter.SetAutoStatus(AutoStatus.Raise, true); } } else if (Service.Config.RaisePlayerBySwift && !Swiftcast.IsCoolingDown && actabilityRemain > 0) { - return true; + return DataCenter.SetAutoStatus(AutoStatus.Raise, true); } } - return false; + return DataCenter.SetAutoStatus(AutoStatus.Raise, false); } protected virtual bool EmergencyGCD(out IAction act) diff --git a/RotationSolver.Basic/Rotations/CustomRotation_Invoke.cs b/RotationSolver.Basic/Rotations/CustomRotation_Invoke.cs index dee8b7fb2..eae75c0ff 100644 --- a/RotationSolver.Basic/Rotations/CustomRotation_Invoke.cs +++ b/RotationSolver.Basic/Rotations/CustomRotation_Invoke.cs @@ -50,7 +50,7 @@ public bool TryInvoke(out IAction newAction, out IAction gcdAction) EsunaStanceNorthAbility = role switch { JobRole.Melee => TrueNorth.CanUse(out act) ? act : null, - JobRole.Tank => Shield.CanUse(out act) ? act : null, + JobRole.Tank => TankStance.CanUse(out act) ? act : null, _ => null, }; RaiseShirkGCD = role switch diff --git a/RotationSolver.Default/Melee/NIN_Default.cs b/RotationSolver.Default/Melee/NIN_Default.cs index 20c10b329..2b917674d 100644 --- a/RotationSolver.Default/Melee/NIN_Default.cs +++ b/RotationSolver.Default/Melee/NIN_Default.cs @@ -58,18 +58,12 @@ private static void SetNinjutsu(INinAction act) if(_ninActionAim != act) { _ninActionAim = act; -#if DEBUG - Service.ChatGui.Print("Set " + act.Name); -#endif } } private static void ClearNinjutsu() { if (_ninActionAim != null) { -#if DEBUG - Service.ChatGui.Print("Clear " + _ninActionAim.Name); -#endif _ninActionAim = null; } } @@ -273,7 +267,7 @@ protected override bool GeneralGCD(out IAction act) //No Ninjutsu if (AdjustId(ActionID.Ninjutsu) is ActionID.Ninjutsu or ActionID.RabbitMedium) { - if (!CombatElapsedLess(16) && FleetingRaiju.CanUse(out act)) return true; + if (!CombatElapsedLess(10) && FleetingRaiju.CanUse(out act)) return true; if (Player.HasStatus(true, StatusID.RaijuReady)) return false; if (InBurstStatus && PhantomKamaitachi.CanUse(out act)) return true; diff --git a/RotationSolver/UI/ControlWindow.cs b/RotationSolver/UI/ControlWindow.cs index 6f406290e..9cd833b8a 100644 --- a/RotationSolver/UI/ControlWindow.cs +++ b/RotationSolver/UI/ControlWindow.cs @@ -146,6 +146,8 @@ private static void DrawSpecials() TargetHostileType.TargetsHaveTarget => LocalizationManager.RightLang.ConfigWindow_Param_TargetToHostileType3, _ => string.Empty, }); + + ImGui.Text("Auto: " + DataCenter.AutoStatus.ToString()); } static void DrawCommandAction(IAction gcd, IAction ability, SpecialCommandType command, Vector4 color) diff --git a/RotationSolver/UI/RotationConfigWindow_Param.cs b/RotationSolver/UI/RotationConfigWindow_Param.cs index 0025db841..f7f7ecdec 100644 --- a/RotationSolver/UI/RotationConfigWindow_Param.cs +++ b/RotationSolver/UI/RotationConfigWindow_Param.cs @@ -307,7 +307,7 @@ private void DrawParamAction() LocalizationManager.RightLang.ConfigWindow_Param_UseDefenceAbilityDesc); DrawCheckBox(LocalizationManager.RightLang.ConfigWindow_Param_AutoShield, - ref Service.Config.AutoShield); + ref Service.Config.AutoTankStance); DrawCheckBox(LocalizationManager.RightLang.ConfigWindow_Param_AutoProvokeForTank, ref Service.Config.AutoProvokeForTank, diff --git a/RotationSolver/Updaters/TargetUpdater.cs b/RotationSolver/Updaters/TargetUpdater.cs index 47d2ede7a..045f7a5b3 100644 --- a/RotationSolver/Updaters/TargetUpdater.cs +++ b/RotationSolver/Updaters/TargetUpdater.cs @@ -277,10 +277,15 @@ static void UpdateCanHeal(PlayerCharacter player) } //Delay - DataCenter.CanHealSingleAbility = _healDelay1.Delay(DataCenter.CanHealSingleAbility); - DataCenter.CanHealSingleSpell = _healDelay2.Delay(DataCenter.CanHealSingleSpell); - DataCenter.CanHealAreaAbility = _healDelay3.Delay(DataCenter.CanHealAreaAbility); - DataCenter.CanHealAreaSpell = _healDelay4.Delay(DataCenter.CanHealAreaSpell); + + DataCenter.CanHealSingleAbility = DataCenter.SetAutoStatus(AutoStatus.HealSingleAbility, + _healDelay1.Delay(DataCenter.CanHealSingleAbility)); + DataCenter.CanHealSingleSpell = DataCenter.SetAutoStatus(AutoStatus.HealSingleSpell, + _healDelay2.Delay(DataCenter.CanHealSingleSpell)); + DataCenter.CanHealAreaAbility = DataCenter.SetAutoStatus(AutoStatus.HealAreaAbility, + _healDelay3.Delay(DataCenter.CanHealAreaAbility)); + DataCenter.CanHealAreaSpell = DataCenter.SetAutoStatus(AutoStatus.HealAreaSpell, + _healDelay4.Delay(DataCenter.CanHealAreaSpell)); DataCenter.PartyMembersMinHP = DataCenter.PartyMembersHP.Any() ? DataCenter.PartyMembersHP.Min() : 0; DataCenter.HPNotFull = DataCenter.PartyMembersMinHP < 1;