From 4926315e4ace501b41d8dfbf60d231f5b54e34e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A7=8B=E6=B0=B4?= <1123993881@qq.com> Date: Sun, 4 Feb 2024 15:22:28 +0800 Subject: [PATCH] refactor: only one instance about the rotation. --- DefaultRotations/Healer/AST_Default.cs | 5 +- .../Attributes/JobsAttribute.cs | 9 ++ .../Attributes/RotationAttribute.cs | 17 +++ RotationSolver.Basic/Data/IconSet.cs | 49 +------ .../Rotations/CustomRotation_Ability.cs | 4 +- .../Rotations/CustomRotation_BasicInfo.cs | 34 +++-- .../Rotations/CustomRotation_Invoke.cs | 2 +- .../Rotations/ICustomRotation.cs | 18 +-- .../Getters/RotationGetter.cs | 2 +- .../Properties/Resources.resx | 40 +++--- RotationSolver/Commands/RSCommands_Actions.cs | 1 + .../Commands/RSCommands_BasicInfo.cs | 1 + .../Commands/RSCommands_OtherCommand.cs | 1 + RotationSolver/Data/CustomRotationGroup.cs | 5 - .../{Localization => Data}/UiString.cs | 2 +- .../Localization/EnumTranslations.cs | 4 +- RotationSolver/UI/ConditionDrawer.cs | 1 + RotationSolver/UI/ControlWindow.cs | 1 + RotationSolver/UI/ImGuiHelper.cs | 1 + RotationSolver/UI/RotationConfigWindow.cs | 123 ++++++++++-------- .../UI/RotationConfigWindow_Config.cs | 1 + .../UI/SearchableConfigs/AutoHealCheckBox.cs | 1 + .../UI/SearchableConfigs/CheckBoxSearch.cs | 1 + .../UI/SearchableConfigs/Searchable.cs | 3 +- RotationSolver/Updaters/MajorUpdater.cs | 1 + RotationSolver/Updaters/RotationUpdater.cs | 111 ++++++++-------- RotationSolver/Updaters/SocialUpdater.cs | 1 + 27 files changed, 220 insertions(+), 219 deletions(-) create mode 100644 RotationSolver.Basic/Attributes/JobsAttribute.cs create mode 100644 RotationSolver.Basic/Attributes/RotationAttribute.cs delete mode 100644 RotationSolver/Data/CustomRotationGroup.cs rename RotationSolver/{Localization => Data}/UiString.cs (99%) diff --git a/DefaultRotations/Healer/AST_Default.cs b/DefaultRotations/Healer/AST_Default.cs index 101f31e45..2e7ddaec6 100644 --- a/DefaultRotations/Healer/AST_Default.cs +++ b/DefaultRotations/Healer/AST_Default.cs @@ -1,15 +1,12 @@ namespace DefaultRotations.Healer; +[Rotation(Name = "Default", GameVersion ="6.28")] [RotationDesc(ActionID.DivinationPvE)] [SourceCode(Path = "main/DefaultRotations/Healer/AST_Default.cs")] public sealed class AST_Default : AstrologianRotation { public override CombatType Type => CombatType.PvE; - public override string GameVersion => "6.28"; - - public override string RotationName => "Default"; - protected override IRotationConfigSet CreateConfiguration() => base.CreateConfiguration() .SetFloat(ConfigUnitType.Seconds, CombatType.PvE, "UseEarthlyStarTime", 15, "Use Earthly Star during countdown timer.", 4, 20); diff --git a/RotationSolver.Basic/Attributes/JobsAttribute.cs b/RotationSolver.Basic/Attributes/JobsAttribute.cs new file mode 100644 index 000000000..097e76ea6 --- /dev/null +++ b/RotationSolver.Basic/Attributes/JobsAttribute.cs @@ -0,0 +1,9 @@ +using ECommons.ExcelServices; + +namespace RotationSolver.Basic.Attributes; + +[AttributeUsage(AttributeTargets.Class)] +internal class JobsAttribute(params Job[] jobs) : Attribute +{ + public Job[] Jobs => jobs; +} diff --git a/RotationSolver.Basic/Attributes/RotationAttribute.cs b/RotationSolver.Basic/Attributes/RotationAttribute.cs new file mode 100644 index 000000000..15976e97a --- /dev/null +++ b/RotationSolver.Basic/Attributes/RotationAttribute.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace RotationSolver.Basic.Attributes; + +[AttributeUsage(AttributeTargets.Class)] +public class RotationAttribute : Attribute +{ + public string Name { get; set; } + public string Description { get; set; } + public CombatType Type { get; set; } + + public string GameVersion { get; set; } +} diff --git a/RotationSolver.Basic/Data/IconSet.cs b/RotationSolver.Basic/Data/IconSet.cs index 0d69a2ec1..d18875378 100644 --- a/RotationSolver.Basic/Data/IconSet.cs +++ b/RotationSolver.Basic/Data/IconSet.cs @@ -296,12 +296,12 @@ public static bool GetTexture(this ActionID actionID, out IDalamudTextureWrap te /// /// Get job Icon from rotation. /// - /// + /// /// - public static uint GetJobIcon(ICustomRotation rotation) + public static uint GetJobIcon(JobRole role, Job job) { IconType type = IconType.Gold; - switch (rotation.ClassJob.GetJobRole()) + switch (role) { case JobRole.Tank: type = IconType.Blue; @@ -315,18 +315,7 @@ public static uint GetJobIcon(ICustomRotation rotation) type = IconType.Green; break; } - return GetJobIcon(rotation, type); - } - - /// - /// Get Job Icon from specific type. - /// - /// - /// - /// - public static uint GetJobIcon(ICustomRotation combo, IconType type) - { - return _icons[type][(uint)combo.Jobs[0] - 1]; + return GetJobIcon(job, type); } /// @@ -336,35 +325,7 @@ public static uint GetJobIcon(ICustomRotation combo, IconType type) /// public static uint GetJobIcon(Job job) { - return GetJobIcon(job, Svc.Data.GetExcelSheet()?.GetRow((uint)job)?.GetJobRole() ?? JobRole.None); - } - - /// - /// - /// - /// - /// - /// - public static uint GetJobIcon(Job job, JobRole role) - { - IconType type = IconType.Gold; - - switch (role) - { - case JobRole.Tank: - type = IconType.Blue; - break; - case JobRole.RangedPhysical: - case JobRole.RangedMagical: - case JobRole.Melee: - type = IconType.Red; - break; - case JobRole.Healer: - type = IconType.Green; - break; - } - - return GetJobIcon(job, type); + return GetJobIcon(Svc.Data.GetExcelSheet()?.GetRow((uint)job)?.GetJobRole() ?? JobRole.None, job); } /// diff --git a/RotationSolver.Basic/Rotations/CustomRotation_Ability.cs b/RotationSolver.Basic/Rotations/CustomRotation_Ability.cs index 3ec9ccbb7..21a68760a 100644 --- a/RotationSolver.Basic/Rotations/CustomRotation_Ability.cs +++ b/RotationSolver.Basic/Rotations/CustomRotation_Ability.cs @@ -236,7 +236,7 @@ private bool GeneralUsingAbility(JobRole role, out IAction? act) case JobRole.Healer: case JobRole.RangedMagical: - if (Jobs[0] == ECommons.ExcelServices.Job.BLM) break; + if (Job == ECommons.ExcelServices.Job.BLM) break; if (LucidDreamingPvE.CanUse(out act)) return true; break; @@ -258,7 +258,7 @@ protected virtual bool EmergencyAbility(IAction nextGCD, out IAction? act) { if (nextGCD is BaseAction action) { - if (ClassJob.GetJobRole() is JobRole.Healer or JobRole.RangedMagical && + if (Role is JobRole.Healer or JobRole.RangedMagical && action.Info.CastTime >= 5 && SwiftcastPvE.CanUse(out act)) return true; if (Service.Config.AutoUseTrueNorth diff --git a/RotationSolver.Basic/Rotations/CustomRotation_BasicInfo.cs b/RotationSolver.Basic/Rotations/CustomRotation_BasicInfo.cs index 25c7df504..a6dc7a6bf 100644 --- a/RotationSolver.Basic/Rotations/CustomRotation_BasicInfo.cs +++ b/RotationSolver.Basic/Rotations/CustomRotation_BasicInfo.cs @@ -1,34 +1,44 @@ -using ECommons.ExcelServices; +using ECommons.DalamudServices; +using ECommons.ExcelServices; using Lumina.Excel.GeneratedSheets; namespace RotationSolver.Basic.Rotations; +[Jobs()] partial class CustomRotation : ICustomRotation { public abstract CombatType Type { get; } - public abstract Job[] Jobs { get; } + private Job? _job = null; + public Job Job => _job ??= this.GetType().GetCustomAttribute()?.Jobs[0] ?? Job.ADV; - public abstract string GameVersion { get; } - - public ClassJob ClassJob => Service.GetSheet().GetRow((uint)Jobs[0])!; + private JobRole? _role = null; + public JobRole Role => _role ??= Svc.Data.GetExcelSheet()!.GetRow((uint)Job)!.GetJobRole(); + private string? _name = null; + public string Name + { + get + { + if (_name != null) return _name; - public string Name => ClassJob.Abbreviation + " - " + ClassJob.Name; + var classJob = Svc.Data.GetExcelSheet()?.GetRow((uint)Job)!; - public abstract string RotationName { get; } + return _name = classJob.Abbreviation + " - " + classJob.Name; + } + } public bool IsEnabled { - get => !Service.Config.DisabledJobs.Contains(Jobs.FirstOrDefault()); + get => !Service.Config.DisabledJobs.Contains(Job); set { if (value) { - Service.Config.DisabledJobs.Remove(Jobs.FirstOrDefault()); + Service.Config.DisabledJobs.Remove(Job); } else { - Service.Config.DisabledJobs.Add(Jobs.FirstOrDefault()); + Service.Config.DisabledJobs.Add(Job); } } } @@ -84,7 +94,7 @@ public bool IsEnabled private protected CustomRotation() { - IconID = IconSet.GetJobIcon(this); + IconID = IconSet.GetJobIcon(this.Job); Configs = CreateConfiguration(); } @@ -93,7 +103,7 @@ protected virtual IRotationConfigSet CreateConfiguration() return new RotationConfigSet(); } - public override string ToString() => RotationName; + public override string ToString() => this.GetType().GetCustomAttribute()?.Name ?? this.GetType().Name; /// /// Update your customized field. diff --git a/RotationSolver.Basic/Rotations/CustomRotation_Invoke.cs b/RotationSolver.Basic/Rotations/CustomRotation_Invoke.cs index 90665e960..a63caa21a 100644 --- a/RotationSolver.Basic/Rotations/CustomRotation_Invoke.cs +++ b/RotationSolver.Basic/Rotations/CustomRotation_Invoke.cs @@ -25,7 +25,7 @@ public bool TryInvoke(out IAction? newAction, out IAction? gcdAction) UpdateInfo(); IBaseAction.ActionPreview = true; - UpdateActions(ClassJob.GetJobRole()); + UpdateActions(Role); IBaseAction.ActionPreview = false; CountingOfLastUsing = CountingOfCombatTimeUsing = 0; diff --git a/RotationSolver.Basic/Rotations/ICustomRotation.cs b/RotationSolver.Basic/Rotations/ICustomRotation.cs index 491541166..11a7a2784 100644 --- a/RotationSolver.Basic/Rotations/ICustomRotation.cs +++ b/RotationSolver.Basic/Rotations/ICustomRotation.cs @@ -50,24 +50,14 @@ public interface ICustomRotation : ITexture string WhyNotValid { get; } /// - /// The class job about this rotation. + /// Job /// - ClassJob ClassJob { get; } + Job Job { get; } /// - /// All jobs. + /// /// - Job[] Jobs { get; } - - /// - /// The game version in writing. - /// - string GameVersion { get; } - - /// - /// The name of this rotation. - /// - string RotationName { get; } + JobRole Role { get; } /// /// Configurations about this rotation. diff --git a/RotationSolver.GameData/Getters/RotationGetter.cs b/RotationSolver.GameData/Getters/RotationGetter.cs index 7a88254c1..273593788 100644 --- a/RotationSolver.GameData/Getters/RotationGetter.cs +++ b/RotationSolver.GameData/Getters/RotationGetter.cs @@ -34,9 +34,9 @@ public string GetCode() ///
Number of Actions: {{rotationsGetter.Count}}
///
Number of Traits: {{traitsGetter.Count}}
///
+ [Jobs({{jobs}})] public abstract partial class {{GetName()}} : CustomRotation { - public sealed override Job[] Jobs => new[] { {{jobs}} }; {{jobGauge}} #region Actions diff --git a/RotationSolver.SourceGenerators/Properties/Resources.resx b/RotationSolver.SourceGenerators/Properties/Resources.resx index f878c6a7e..88b1fb6c2 100644 --- a/RotationSolver.SourceGenerators/Properties/Resources.resx +++ b/RotationSolver.SourceGenerators/Properties/Resources.resx @@ -41677,9 +41677,9 @@ namespace RotationSolver.Basic.Rotations.Basic; /// <br>Number of Actions: 46</br> /// <br>Number of Traits: 15</br> /// </summary> +[Jobs(Job.PLD, Job.GLA)] public abstract partial class PaladinRotation : CustomRotation { - public sealed override Job[] Jobs => new[] { Job.PLD, Job.GLA }; static PLDGauge JobGauge => Svc.Gauges.Get<PLDGauge>(); #region Actions @@ -43092,9 +43092,9 @@ private sealed protected override IBaseAction? LimitBreak3 => LastBastionPvE; /// <br>Number of Actions: 45</br> /// <br>Number of Traits: 15</br> /// </summary> +[Jobs(Job.MNK, Job.PGL)] public abstract partial class MonkRotation : CustomRotation { - public sealed override Job[] Jobs => new[] { Job.MNK, Job.PGL }; static MNKGauge JobGauge => Svc.Gauges.Get<MNKGauge>(); #region Actions @@ -44479,9 +44479,9 @@ private sealed protected override IBaseAction? LimitBreak3 => FinalHeavenPvE; /// <br>Number of Actions: 40</br> /// <br>Number of Traits: 15</br> /// </summary> +[Jobs(Job.WAR, Job.MRD)] public abstract partial class WarriorRotation : CustomRotation { - public sealed override Job[] Jobs => new[] { Job.WAR, Job.MRD }; static WARGauge JobGauge => Svc.Gauges.Get<WARGauge>(); #region Actions @@ -45718,9 +45718,9 @@ private sealed protected override IBaseAction? LimitBreak3 => LandWakerPvE; /// <br>Number of Actions: 40</br> /// <br>Number of Traits: 11</br> /// </summary> +[Jobs(Job.DRG, Job.LNC)] public abstract partial class DragoonRotation : CustomRotation { - public sealed override Job[] Jobs => new[] { Job.DRG, Job.LNC }; static DRGGauge JobGauge => Svc.Gauges.Get<DRGGauge>(); #region Actions @@ -46921,9 +46921,9 @@ private sealed protected override IBaseAction? LimitBreak3 => DragonsongDiveP /// <br>Number of Actions: 40</br> /// <br>Number of Traits: 16</br> /// </summary> +[Jobs(Job.BRD, Job.ARC)] public abstract partial class BardRotation : CustomRotation { - public sealed override Job[] Jobs => new[] { Job.BRD, Job.ARC }; static BRDGauge JobGauge => Svc.Gauges.Get<BRDGauge>(); #region Actions @@ -48159,9 +48159,9 @@ private sealed protected override IBaseAction? LimitBreak3 => SagittariusArro /// <br>Number of Actions: 42</br> /// <br>Number of Traits: 16</br> /// </summary> +[Jobs(Job.WHM, Job.CNJ)] public abstract partial class WhiteMageRotation : CustomRotation { - public sealed override Job[] Jobs => new[] { Job.WHM, Job.CNJ }; static WHMGauge JobGauge => Svc.Gauges.Get<WHMGauge>(); #region Actions @@ -49385,9 +49385,9 @@ private sealed protected override IBaseAction? LimitBreak3 => PulseOfLifePvE; /// <br>Number of Actions: 45</br> /// <br>Number of Traits: 21</br> /// </summary> +[Jobs(Job.BLM, Job.THM)] public abstract partial class BlackMageRotation : CustomRotation { - public sealed override Job[] Jobs => new[] { Job.BLM, Job.THM }; static BLMGauge JobGauge => Svc.Gauges.Get<BLMGauge>(); #region Actions @@ -50822,9 +50822,9 @@ private sealed protected override IBaseAction? LimitBreak3 => MeteorPvE; /// <br>Number of Actions: 98</br> /// <br>Number of Traits: 21</br> /// </summary> +[Jobs(Job.SMN, Job.ACN)] public abstract partial class SummonerRotation : CustomRotation { - public sealed override Job[] Jobs => new[] { Job.SMN, Job.ACN }; static SMNGauge JobGauge => Svc.Gauges.Get<SMNGauge>(); #region Actions @@ -53543,9 +53543,9 @@ private sealed protected override IBaseAction? LimitBreak3 => TeraflarePvE; /// <br>Number of Actions: 54</br> /// <br>Number of Traits: 12</br> /// </summary> +[Jobs(Job.SCH)] public abstract partial class ScholarRotation : CustomRotation { - public sealed override Job[] Jobs => new[] { Job.SCH }; static SCHGauge JobGauge => Svc.Gauges.Get<SCHGauge>(); #region Actions @@ -55083,9 +55083,9 @@ private sealed protected override IBaseAction? LimitBreak3 => AngelFeathersPv /// <br>Number of Actions: 88</br> /// <br>Number of Traits: 14</br> /// </summary> +[Jobs(Job.NIN, Job.ROG)] public abstract partial class NinjaRotation : CustomRotation { - public sealed override Job[] Jobs => new[] { Job.NIN, Job.ROG }; static NINGauge JobGauge => Svc.Gauges.Get<NINGauge>(); #region Actions @@ -57504,9 +57504,9 @@ private sealed protected override IBaseAction? LimitBreak3 => ChimatsuriPvE; /// <br>Number of Actions: 45</br> /// <br>Number of Traits: 14</br> /// </summary> +[Jobs(Job.MCH)] public abstract partial class MachinistRotation : CustomRotation { - public sealed override Job[] Jobs => new[] { Job.MCH }; static MCHGauge JobGauge => Svc.Gauges.Get<MCHGauge>(); #region Actions @@ -58865,9 +58865,9 @@ private sealed protected override IBaseAction? LimitBreak3 => SatelliteBeamPv /// <br>Number of Actions: 42</br> /// <br>Number of Traits: 9</br> /// </summary> +[Jobs(Job.DRK)] public abstract partial class DarkKnightRotation : CustomRotation { - public sealed override Job[] Jobs => new[] { Job.DRK }; static DRKGauge JobGauge => Svc.Gauges.Get<DRKGauge>(); #region Actions @@ -60081,9 +60081,9 @@ private sealed protected override IBaseAction? LimitBreak3 => DarkForcePvE; /// <br>Number of Actions: 60</br> /// <br>Number of Traits: 16</br> /// </summary> +[Jobs(Job.AST)] public abstract partial class AstrologianRotation : CustomRotation { - public sealed override Job[] Jobs => new[] { Job.AST }; static ASTGauge JobGauge => Svc.Gauges.Get<ASTGauge>(); #region Actions @@ -61791,9 +61791,9 @@ private sealed protected override IBaseAction? LimitBreak3 => AstralStasisPvE /// <br>Number of Actions: 47</br> /// <br>Number of Traits: 10</br> /// </summary> +[Jobs(Job.SAM)] public abstract partial class SamuraiRotation : CustomRotation { - public sealed override Job[] Jobs => new[] { Job.SAM }; static SAMGauge JobGauge => Svc.Gauges.Get<SAMGauge>(); #region Actions @@ -63193,9 +63193,9 @@ private sealed protected override IBaseAction? LimitBreak3 => DoomOfTheLiving /// <br>Number of Actions: 57</br> /// <br>Number of Traits: 13</br> /// </summary> +[Jobs(Job.RDM)] public abstract partial class RedMageRotation : CustomRotation { - public sealed override Job[] Jobs => new[] { Job.RDM }; static RDMGauge JobGauge => Svc.Gauges.Get<RDMGauge>(); #region Actions @@ -64880,9 +64880,9 @@ private sealed protected override IBaseAction? LimitBreak3 => VermilionScourg /// <br>Number of Actions: 131</br> /// <br>Number of Traits: 6</br> /// </summary> +[Jobs(Job.BLU)] public abstract partial class BlueMageRotation : CustomRotation { - public sealed override Job[] Jobs => new[] { Job.BLU }; #region Actions @@ -68142,9 +68142,9 @@ public abstract partial class BlueMageRotation : CustomRotation /// <br>Number of Actions: 64</br> /// <br>Number of Traits: 9</br> /// </summary> +[Jobs(Job.GNB)] public abstract partial class GunbreakerRotation : CustomRotation { - public sealed override Job[] Jobs => new[] { Job.GNB }; static GNBGauge JobGauge => Svc.Gauges.Get<GNBGauge>(); #region Actions @@ -70007,9 +70007,9 @@ private sealed protected override IBaseAction? LimitBreak3 => GunmetalSoulPvE /// <br>Number of Actions: 59</br> /// <br>Number of Traits: 11</br> /// </summary> +[Jobs(Job.DNC)] public abstract partial class DancerRotation : CustomRotation { - public sealed override Job[] Jobs => new[] { Job.DNC }; static DNCGauge JobGauge => Svc.Gauges.Get<DNCGauge>(); #region Actions @@ -71841,9 +71841,9 @@ private sealed protected override IBaseAction? LimitBreak3 => CrimsonLotusPvE /// <br>Number of Actions: 49</br> /// <br>Number of Traits: 10</br> /// </summary> +[Jobs(Job.RPR)] public abstract partial class ReaperRotation : CustomRotation { - public sealed override Job[] Jobs => new[] { Job.RPR }; static RPRGauge JobGauge => Svc.Gauges.Get<RPRGauge>(); #region Actions @@ -73342,9 +73342,9 @@ private sealed protected override IBaseAction? LimitBreak3 => TheEndPvE; /// <br>Number of Actions: 47</br> /// <br>Number of Traits: 12</br> /// </summary> +[Jobs(Job.SGE)] public abstract partial class SageRotation : CustomRotation { - public sealed override Job[] Jobs => new[] { Job.SGE }; static SGEGauge JobGauge => Svc.Gauges.Get<SGEGauge>(); #region Actions diff --git a/RotationSolver/Commands/RSCommands_Actions.cs b/RotationSolver/Commands/RSCommands_Actions.cs index 1e4f27611..0775fa76c 100644 --- a/RotationSolver/Commands/RSCommands_Actions.cs +++ b/RotationSolver/Commands/RSCommands_Actions.cs @@ -3,6 +3,7 @@ using ECommons.DalamudServices; using ECommons.GameHelpers; using RotationSolver.Basic.Configuration; +using RotationSolver.Data; using RotationSolver.Helpers; using RotationSolver.Localization; using RotationSolver.UI; diff --git a/RotationSolver/Commands/RSCommands_BasicInfo.cs b/RotationSolver/Commands/RSCommands_BasicInfo.cs index da3e957ec..35d9c9c44 100644 --- a/RotationSolver/Commands/RSCommands_BasicInfo.cs +++ b/RotationSolver/Commands/RSCommands_BasicInfo.cs @@ -1,5 +1,6 @@ using Dalamud.Game.Command; using ECommons.DalamudServices; +using RotationSolver.Data; using RotationSolver.Localization; namespace RotationSolver.Commands; diff --git a/RotationSolver/Commands/RSCommands_OtherCommand.cs b/RotationSolver/Commands/RSCommands_OtherCommand.cs index d44d3019b..651b66435 100644 --- a/RotationSolver/Commands/RSCommands_OtherCommand.cs +++ b/RotationSolver/Commands/RSCommands_OtherCommand.cs @@ -1,5 +1,6 @@ using ECommons.DalamudServices; using RotationSolver.Basic.Configuration; +using RotationSolver.Data; using RotationSolver.Localization; using RotationSolver.Updaters; diff --git a/RotationSolver/Data/CustomRotationGroup.cs b/RotationSolver/Data/CustomRotationGroup.cs deleted file mode 100644 index 5162a4b17..000000000 --- a/RotationSolver/Data/CustomRotationGroup.cs +++ /dev/null @@ -1,5 +0,0 @@ -using ECommons.ExcelServices; - -namespace RotationSolver.Data; - -internal record CustomRotationGroup(Job JobId, Job[] ClassJobIds, ICustomRotation[] Rotations); diff --git a/RotationSolver/Localization/UiString.cs b/RotationSolver/Data/UiString.cs similarity index 99% rename from RotationSolver/Localization/UiString.cs rename to RotationSolver/Data/UiString.cs index ab798fa91..6d356593a 100644 --- a/RotationSolver/Localization/UiString.cs +++ b/RotationSolver/Data/UiString.cs @@ -1,6 +1,6 @@ using System.ComponentModel; -namespace RotationSolver.Localization; +namespace RotationSolver.Data; internal enum UiString { [Description("The Condition set you chose, click to modify.")] diff --git a/RotationSolver/Localization/EnumTranslations.cs b/RotationSolver/Localization/EnumTranslations.cs index ff645bd8e..bfaca2292 100644 --- a/RotationSolver/Localization/EnumTranslations.cs +++ b/RotationSolver/Localization/EnumTranslations.cs @@ -1,4 +1,6 @@ -namespace RotationSolver.Localization; +using RotationSolver.Data; + +namespace RotationSolver.Localization; internal static class EnumTranslations { diff --git a/RotationSolver/UI/ConditionDrawer.cs b/RotationSolver/UI/ConditionDrawer.cs index 13e17fe42..ca439b89c 100644 --- a/RotationSolver/UI/ConditionDrawer.cs +++ b/RotationSolver/UI/ConditionDrawer.cs @@ -8,6 +8,7 @@ using ECommons.LanguageHelpers; using Lumina.Excel.GeneratedSheets; using RotationSolver.Basic.Configuration.Conditions; +using RotationSolver.Data; using RotationSolver.Localization; using RotationSolver.Updaters; using Action = System.Action; diff --git a/RotationSolver/UI/ControlWindow.cs b/RotationSolver/UI/ControlWindow.cs index 0a431ac2b..b9736ded4 100644 --- a/RotationSolver/UI/ControlWindow.cs +++ b/RotationSolver/UI/ControlWindow.cs @@ -9,6 +9,7 @@ using RotationSolver.Updaters; using RotationSolver.Helpers; using System.ComponentModel; +using RotationSolver.Data; namespace RotationSolver.UI; diff --git a/RotationSolver/UI/ImGuiHelper.cs b/RotationSolver/UI/ImGuiHelper.cs index 5f5c0bdee..35e86aa45 100644 --- a/RotationSolver/UI/ImGuiHelper.cs +++ b/RotationSolver/UI/ImGuiHelper.cs @@ -7,6 +7,7 @@ using ECommons.ImGuiMethods; using RotationSolver.Basic.Configuration; using RotationSolver.Commands; +using RotationSolver.Data; using RotationSolver.Localization; using RotationSolver.UI.SearchableConfigs; using RotationSolver.UI.SearchableSettings; diff --git a/RotationSolver/UI/RotationConfigWindow.cs b/RotationSolver/UI/RotationConfigWindow.cs index ae3e7fdc3..d9e87e03a 100644 --- a/RotationSolver/UI/RotationConfigWindow.cs +++ b/RotationSolver/UI/RotationConfigWindow.cs @@ -11,6 +11,7 @@ using ECommons.ImGuiMethods; using ExCSS; using FFXIVClientStructs.FFXIV.Client.Game.Fate; +using FFXIVClientStructs.FFXIV.Client.Game.UI; using FFXIVClientStructs.FFXIV.Client.UI; using FFXIVClientStructs.FFXIV.Common.Component.BGCollision; using Lumina.Excel.GeneratedSheets; @@ -364,65 +365,68 @@ private void DrawHeader(float wholeWidth) } var rotation = DataCenter.RightNowRotation; - if (rotation != null) - { - var rotations = RotationUpdater.CustomRotations.FirstOrDefault(i => i.ClassJobIds.Contains((Job)(Player.Object?.ClassJob.Id ?? 0)))?.Rotations ?? []; + if (rotation == null) return; - if (DataCenter.Territory?.IsPvpZone ?? false) - { - rotations = rotations.Where(r => r.Type.HasFlag(CombatType.PvP)).ToArray(); - } - else - { - rotations = rotations.Where(r => r.Type.HasFlag(CombatType.PvE)).ToArray(); - } + var rotations = RotationUpdater.CustomRotations.FirstOrDefault(i => i.ClassJobIds.Contains((Job)(Player.Object?.ClassJob.Id ?? 0)))?.Rotations ?? []; + + var rot = rotation.GetType().GetCustomAttribute(); + + if (rot == null) return; + + if (DataCenter.Territory?.IsPvpZone ?? false) + { + rotations = rotations.Where(r => r.GetType().GetCustomAttribute()?.Type.HasFlag(CombatType.PvP) ?? false).ToArray(); + } + else + { + rotations = rotations.Where(r => r.GetType().GetCustomAttribute()?.Type.HasFlag(CombatType.PvE) ?? false).ToArray(); + } - var iconSize = Math.Max(Scale * MIN_COLUMN_WIDTH, Math.Min(wholeWidth, Scale * JOB_ICON_WIDTH)); - var comboSize = ImGui.CalcTextSize(rotation.RotationName).X; + var iconSize = Math.Max(Scale * MIN_COLUMN_WIDTH, Math.Min(wholeWidth, Scale * JOB_ICON_WIDTH)); + var comboSize = ImGui.CalcTextSize(rot.Name).X; - const string slash = " - "; - var gameVersionSize = ImGui.CalcTextSize(slash + rotation.GameVersion).X + ImGui.GetStyle().ItemSpacing.X; - var gameVersion = UiString.ConfigWindow_Helper_GameVersion.Local() + ": "; - var drawCenter = ImGui.CalcTextSize(slash + gameVersion + rotation.GameVersion).X + iconSize + ImGui.GetStyle().ItemSpacing.X * 3 < wholeWidth; - if (drawCenter) gameVersionSize += ImGui.CalcTextSize(gameVersion).X + ImGui.GetStyle().ItemSpacing.X; + const string slash = " - "; + var gameVersionSize = ImGui.CalcTextSize(slash + rot.GameVersion).X + ImGui.GetStyle().ItemSpacing.X; + var gameVersion = UiString.ConfigWindow_Helper_GameVersion.Local() + ": "; + var drawCenter = ImGui.CalcTextSize(slash + gameVersion + rot.GameVersion).X + iconSize + ImGui.GetStyle().ItemSpacing.X * 3 < wholeWidth; + if (drawCenter) gameVersionSize += ImGui.CalcTextSize(gameVersion).X + ImGui.GetStyle().ItemSpacing.X; - var horizonalWholeWidth = Math.Max(comboSize, gameVersionSize) + iconSize + ImGui.GetStyle().ItemSpacing.X; + var horizonalWholeWidth = Math.Max(comboSize, gameVersionSize) + iconSize + ImGui.GetStyle().ItemSpacing.X; - if (horizonalWholeWidth > wholeWidth) + if (horizonalWholeWidth > wholeWidth) + { + ImGuiHelper.DrawItemMiddle(() => { - ImGuiHelper.DrawItemMiddle(() => - { - DrawRotationIcon(rotation, iconSize); - }, wholeWidth, iconSize); + DrawRotationIcon(rotation, iconSize); + }, wholeWidth, iconSize); - if (Scale * JOB_ICON_WIDTH < wholeWidth) - { - DrawRotationCombo(comboSize, rotations, rotation, gameVersion); - } + if (Scale * JOB_ICON_WIDTH < wholeWidth) + { + DrawRotationCombo(comboSize, rotations, rotation, gameVersion); } - else + } + else + { + ImGuiHelper.DrawItemMiddle(() => { - ImGuiHelper.DrawItemMiddle(() => - { - DrawRotationIcon(rotation, iconSize); + DrawRotationIcon(rotation, iconSize); - ImGui.SameLine(); + ImGui.SameLine(); - using var group = ImRaii.Group(); + using var group = ImRaii.Group(); - DrawRotationCombo(comboSize, rotations, rotation, gameVersion); - ImGui.TextDisabled(slash); - ImGui.SameLine(); + DrawRotationCombo(comboSize, rotations, rotation, gameVersion); + ImGui.TextDisabled(slash); + ImGui.SameLine(); - if (drawCenter) - { - ImGui.TextDisabled(gameVersion); - ImGui.SameLine(); - } - ImGui.Text(rotation.GameVersion); + if (drawCenter) + { + ImGui.TextDisabled(gameVersion); + ImGui.SameLine(); + } + ImGui.Text(rot.GameVersion); - }, wholeWidth, horizonalWholeWidth); - } + }, wholeWidth, horizonalWholeWidth); } } @@ -439,7 +443,7 @@ private void DrawRotationIcon(ICustomRotation rotation, float iconSize) { ImguiTooltips.ShowTooltip(() => { - ImGui.Text(rotation.Name + $" ({rotation.RotationName})"); + ImGui.Text(rotation.Name + $" ({rotation.GetType().GetCustomAttribute()!.Name})"); rotation.Type.Draw(); if (!string.IsNullOrEmpty(rotation.Description)) { @@ -456,14 +460,16 @@ private void DrawRotationIcon(ICustomRotation rotation, float iconSize) } } - private static void DrawRotationCombo(float comboSize, ICustomRotation[] rotations, ICustomRotation rotation, string gameVersion) + private static void DrawRotationCombo(float comboSize, Type[] rotations, ICustomRotation rotation, string gameVersion) { ImGui.SetNextItemWidth(comboSize); const string popUp = "Rotation Solver Select Rotation"; + var rot = rotation.GetType().GetCustomAttribute()!; + using (var color = ImRaii.PushColor(ImGuiCol.Text, rotation.GetColor())) { - if (ImGui.Selectable(rotation.RotationName + "##RotationName:" + rotation.Name)) + if (ImGui.Selectable(rot.Name + "##RotationName:" + rotation.Name)) { if (!ImGui.IsPopupOpen(popUp)) ImGui.OpenPopup(popUp); } @@ -475,7 +481,9 @@ private static void DrawRotationCombo(float comboSize, ICustomRotation[] rotatio { foreach (var r in rotations) { - if (IconSet.GetTexture(r.Type.GetIcon(), out var texture)) + var rAttr = r.GetType().GetCustomAttribute()!; + + if (IconSet.GetTexture(rAttr.Type.GetIcon(), out var texture)) { ImGui.Image(texture.ImGuiHandle, Vector2.One * 20 * Scale); if (ImGui.IsItemHovered()) @@ -487,8 +495,9 @@ private static void DrawRotationCombo(float comboSize, ICustomRotation[] rotatio } } ImGui.SameLine(); - ImGui.PushStyleColor(ImGuiCol.Text, r.GetColor()); - if (ImGui.Selectable(r.RotationName)) + ImGui.PushStyleColor(ImGuiCol.Text, r.GetCustomAttribute() == null + ? ImGuiColors.DalamudWhite : ImGuiColors.DalamudOrange); + if (ImGui.Selectable(rAttr.Name)) { if( DataCenter.Territory?.IsPvpZone ?? false) { @@ -499,13 +508,13 @@ private static void DrawRotationCombo(float comboSize, ICustomRotation[] rotatio Service.Config.RotationChoice = r.GetType().FullName; } } - ImguiTooltips.HoveredTooltip(r.Description); + ImguiTooltips.HoveredTooltip(rAttr.Description); ImGui.PopStyleColor(); } } } - var warning = gameVersion + rotation.GameVersion; + var warning = gameVersion + rot.GameVersion; if (!rotation.IsValid) warning += "\n" + string.Format(UiString.ConfigWindow_Rotation_InvalidRotation .Local(), rotation.GetType().Assembly.GetInfo().Author); @@ -1616,13 +1625,13 @@ private static void DrawRotationsLoaded() ImGui.TableNextColumn(); var lastRole = JobRole.None; - foreach (var jobs in grp.GroupBy(r => r.IconID)) + foreach (var jobs in grp.GroupBy(r => r.GetCustomAttribute()!.Jobs[0])) { - var role = jobs.First().ClassJob.GetJobRole(); + var role = Svc.Data.GetExcelSheet()!.GetRow((uint)jobs.Key)!.GetJobRole(); if (lastRole == role && lastRole != JobRole.None) ImGui.SameLine(); lastRole = role; - if (IconSet.GetTexture(IconSet.GetJobIcon(jobs.First(), IconType.Framed), out var texture, 62574)) + if (IconSet.GetTexture(IconSet.GetJobIcon(jobs.Key, IconType.Framed), out var texture, 62574)) ImGui.Image(texture.ImGuiHandle, Vector2.One * 30 * Scale); ImguiTooltips.HoveredTooltip(string.Join('\n', jobs)); @@ -2422,7 +2431,7 @@ private static unsafe void DrawTargetData() private static void DrawNextAction() { - ImGui.Text(DataCenter.RightNowRotation?.RotationName); + ImGui.Text(DataCenter.RightNowRotation?.GetType().GetCustomAttribute()!.Name); ImGui.Text(DataCenter.SpecialType.ToString()); ImGui.Text("Ability Remain: " + DataCenter.AbilityRemain.ToString()); diff --git a/RotationSolver/UI/RotationConfigWindow_Config.cs b/RotationSolver/UI/RotationConfigWindow_Config.cs index bbaa4b595..de9d18a71 100644 --- a/RotationSolver/UI/RotationConfigWindow_Config.cs +++ b/RotationSolver/UI/RotationConfigWindow_Config.cs @@ -5,6 +5,7 @@ using ECommons.ImGuiMethods; using RotationSolver.Basic.Configuration; using RotationSolver.Basic.Configuration.Conditions; +using RotationSolver.Data; using RotationSolver.Helpers; using RotationSolver.Localization; using RotationSolver.UI.SearchableConfigs; diff --git a/RotationSolver/UI/SearchableConfigs/AutoHealCheckBox.cs b/RotationSolver/UI/SearchableConfigs/AutoHealCheckBox.cs index aa031f761..700952352 100644 --- a/RotationSolver/UI/SearchableConfigs/AutoHealCheckBox.cs +++ b/RotationSolver/UI/SearchableConfigs/AutoHealCheckBox.cs @@ -1,4 +1,5 @@ using RotationSolver.Basic.Configuration; +using RotationSolver.Data; using RotationSolver.Localization; using RotationSolver.UI.SearchableSettings; diff --git a/RotationSolver/UI/SearchableConfigs/CheckBoxSearch.cs b/RotationSolver/UI/SearchableConfigs/CheckBoxSearch.cs index e0fa45252..ef85e51bb 100644 --- a/RotationSolver/UI/SearchableConfigs/CheckBoxSearch.cs +++ b/RotationSolver/UI/SearchableConfigs/CheckBoxSearch.cs @@ -2,6 +2,7 @@ using Dalamud.Interface.Utility; using RotationSolver.Basic.Configuration; using RotationSolver.Basic.Configuration.Conditions; +using RotationSolver.Data; using RotationSolver.Localization; using RotationSolver.UI.SearchableConfigs; diff --git a/RotationSolver/UI/SearchableConfigs/Searchable.cs b/RotationSolver/UI/SearchableConfigs/Searchable.cs index 83852931b..f93daf0b3 100644 --- a/RotationSolver/UI/SearchableConfigs/Searchable.cs +++ b/RotationSolver/UI/SearchableConfigs/Searchable.cs @@ -2,6 +2,7 @@ using ECommons.DalamudServices; using ECommons.ExcelServices; using Lumina.Excel.GeneratedSheets; +using RotationSolver.Data; using RotationSolver.Localization; using RotationSolver.UI.SearchableSettings; @@ -100,7 +101,7 @@ public bool CanDraw if (JobRoles != null) { - var role = DataCenter.RightNowRotation?.ClassJob?.GetJobRole(); + var role = DataCenter.RightNowRotation?.Role; if (role.HasValue) { canDraw = JobRoles.Contains(role.Value); diff --git a/RotationSolver/Updaters/MajorUpdater.cs b/RotationSolver/Updaters/MajorUpdater.cs index e1335836c..2a386cad3 100644 --- a/RotationSolver/Updaters/MajorUpdater.cs +++ b/RotationSolver/Updaters/MajorUpdater.cs @@ -12,6 +12,7 @@ using FFXIVClientStructs.FFXIV.Component.GUI; using RotationSolver.Basic.Configuration; using RotationSolver.Commands; +using RotationSolver.Data; using RotationSolver.Localization; using RotationSolver.UI; using System.Runtime.InteropServices; diff --git a/RotationSolver/Updaters/RotationUpdater.cs b/RotationSolver/Updaters/RotationUpdater.cs index b38600e58..c01369b43 100644 --- a/RotationSolver/Updaters/RotationUpdater.cs +++ b/RotationSolver/Updaters/RotationUpdater.cs @@ -1,6 +1,7 @@ using ECommons.DalamudServices; using ECommons.ExcelServices; using ECommons.GameHelpers; +using Lumina.Excel.GeneratedSheets; using RotationSolver.Basic.Rotations.Duties; using RotationSolver.Data; using RotationSolver.Helpers; @@ -10,6 +11,7 @@ namespace RotationSolver.Updaters; internal static class RotationUpdater { + internal record CustomRotationGroup(Job JobId, Job[] ClassJobIds, Type[] Rotations); internal static SortedList CustomRotationsDict { get; private set; } = []; internal static SortedList AuthorHashes { get; private set; } = []; @@ -51,7 +53,7 @@ public static async Task GetAllCustomRotationsAsync(DownloadOption option) var assemblies = CustomRotationsDict .SelectMany(d => d.Value) .SelectMany(g => g.Rotations) - .Select(r => r.GetType().Assembly.FullName) + .Select(r => r.GetType().Assembly.FullName ?? string.Empty) .Distinct() .ToList(); @@ -128,7 +130,9 @@ private static void LoadRotationsFromLocal(string relayFolder) var customRotationsGroupedByJobRole = new Dictionary>(); foreach (var customRotationGroup in CustomRotations) { - var jobRole = customRotationGroup.Rotations[0].ClassJob.GetJobRole(); + var job = customRotationGroup.Rotations[0].GetType().GetCustomAttribute()?.Jobs[0] ?? Job.ADV; + + var jobRole = Svc.Data.GetExcelSheet()!.GetRow((uint)job)!.GetJobRole(); if (!customRotationsGroupedByJobRole.TryGetValue(jobRole, out var value)) { value = []; @@ -149,27 +153,26 @@ private static void LoadRotationsFromLocal(string relayFolder) private static CustomRotationGroup[] LoadCustomRotationGroup(List assemblies) { - var rotationList = new List(); + var rotationList = new List(); foreach (var assembly in assemblies) { foreach (var type in TryGetTypes(assembly)) { if (type.GetInterfaces().Contains(typeof(ICustomRotation)) - && !type.IsAbstract && !type.IsInterface) + && !type.IsAbstract && !type.IsInterface && type.GetConstructor([]) != null) { - var rotation = GetRotation(type); - if (rotation != null) - { - rotationList.Add(rotation); - } + rotationList.Add(type); } } } - var rotationGroups = new Dictionary>(); + var rotationGroups = new Dictionary>(); foreach (var rotation in rotationList) { - var jobId = rotation.Jobs[0]; + var attr = rotation.GetCustomAttribute(); + if (attr == null) continue; + + var jobId = attr.Jobs[0]; if (!rotationGroups.TryGetValue(jobId, out var value)) { value = []; @@ -184,9 +187,10 @@ private static CustomRotationGroup[] LoadCustomRotationGroup(List asse { var jobId = kvp.Key; var rotations = kvp.Value.ToArray(); - result.Add(new CustomRotationGroup(jobId, rotations[0].Jobs, CreateRotationSet(rotations))); - } + result.Add(new CustomRotationGroup(jobId, rotations[0].GetCustomAttribute()!.Jobs, + rotations)); + } return [.. result]; } @@ -359,32 +363,6 @@ public static Type[] TryGetTypes(Assembly assembly) } } - private static ICustomRotation? GetRotation(Type t) - { - try - { - return (ICustomRotation?)Activator.CreateInstance(t); - } - catch (Exception ex) - { - Svc.Log.Error(ex, $"Failed to load the rotation: {t.Name}"); - return null; - } - } - - private static ICustomRotation[] CreateRotationSet(ICustomRotation[] combos) - { - var result = new List(combos.Length); - - foreach (var combo in combos) - { - if (!result.Any(c => c.RotationName == combo.RotationName)) - { - result.Add(combo); - } - } - return [.. result]; - } public static IEnumerable>? AllGroupedActions => GroupActions(DataCenter.RightNowRotation?.AllActions); @@ -439,39 +417,60 @@ public static void UpdateRotation() if (!group.ClassJobIds.Contains(nowJob)) continue; var rotation = GetChosenRotation(group); - if (rotation != DataCenter.RightNowRotation) + if (rotation != DataCenter.RightNowRotation?.GetType()) { - rotation?.OnTerritoryChanged(); + var instance = GetRotation(rotation); + instance?.OnTerritoryChanged(); + DataCenter.RightNowRotation = instance; } - DataCenter.RightNowRotation = rotation; RightRotationActions = DataCenter.RightNowRotation?.AllActions ?? []; - DataCenter.Job = DataCenter.RightNowRotation?.Jobs[0] ?? Job.ADV; + DataCenter.Job = DataCenter.RightNowRotation?.Job ?? Job.ADV; return; } CustomRotation.MoveTarget = null; DataCenter.RightNowRotation = null; RightRotationActions = []; - DataCenter.Job = DataCenter.RightNowRotation?.Jobs[0] ?? Job.ADV; - } + DataCenter.Job = DataCenter.RightNowRotation?.Job ?? Job.ADV; - internal static ICustomRotation? GetChosenRotation(CustomRotationGroup group) - { - var isPvP = DataCenter.Territory?.IsPvpZone ?? false; + static ICustomRotation? GetRotation(Type? t) + { + if (t == null) return null; + try + { + return (ICustomRotation?)Activator.CreateInstance(t); + } + catch (Exception ex) + { + Svc.Log.Error(ex, $"Failed to load the rotation: {t.Name}"); + return null; + } + } - var rotations = group.Rotations - .Where(r => isPvP ? r.Type.HasFlag(CombatType.PvP): r.Type.HasFlag(CombatType.PvE)); + static Type? GetChosenRotation(CustomRotationGroup group) + { + var isPvP = DataCenter.Territory?.IsPvpZone ?? false; - var name = isPvP ? Service.Config.PvPRotationChoice : Service.Config.RotationChoice; + var rotations = group.Rotations + .Where(r => + { + var rot = r.GetCustomAttribute(); + if (rot == null) return false; + + return isPvP ? rot.Type.HasFlag(CombatType.PvP) : rot.Type.HasFlag(CombatType.PvE); + }); - var rotation = rotations.FirstOrDefault(r => r.GetType().FullName == name); + var name = isPvP ? Service.Config.PvPRotationChoice : Service.Config.RotationChoice; - rotation ??= rotations.FirstOrDefault(r => r.GetType().Assembly.FullName!.Contains("SupportersRotations", StringComparison.OrdinalIgnoreCase)); + var rotation = rotations.FirstOrDefault(r => r.GetType().FullName == name); - rotation ??= rotations.FirstOrDefault(r => r.GetType().Assembly.FullName!.Contains("DefaultRotations", StringComparison.OrdinalIgnoreCase)); + rotation ??= rotations.FirstOrDefault(r => r.GetType().Assembly.FullName!.Contains("SupportersRotations", StringComparison.OrdinalIgnoreCase)); - rotation ??= rotations.FirstOrDefault(); + rotation ??= rotations.FirstOrDefault(r => r.GetType().Assembly.FullName!.Contains("DefaultRotations", StringComparison.OrdinalIgnoreCase)); - return rotation; + rotation ??= rotations.FirstOrDefault(); + + return rotation; + } } } diff --git a/RotationSolver/Updaters/SocialUpdater.cs b/RotationSolver/Updaters/SocialUpdater.cs index c7ae0df6a..2c7b150a5 100644 --- a/RotationSolver/Updaters/SocialUpdater.cs +++ b/RotationSolver/Updaters/SocialUpdater.cs @@ -9,6 +9,7 @@ using RotationSolver.Basic.Configuration; using RotationSolver.Basic.Rotations.Duties; using RotationSolver.Commands; +using RotationSolver.Data; using RotationSolver.Helpers; using RotationSolver.Localization; using System.Diagnostics.CodeAnalysis;