diff --git a/RotationSolver.Basic/Actions/BaseAction/BaseAction_BasicInfo.cs b/RotationSolver.Basic/Actions/BaseAction/BaseAction_BasicInfo.cs index f91d7c2df..0cc85db5c 100644 --- a/RotationSolver.Basic/Actions/BaseAction/BaseAction_BasicInfo.cs +++ b/RotationSolver.Basic/Actions/BaseAction/BaseAction_BasicInfo.cs @@ -27,33 +27,6 @@ public partial class BaseAction : IBaseAction public string Description => string.Empty; - //public string CateName - //{ - // get - // { - // string result; - - // if (_isFriendly) - // { - // result = LocalizationManager.RightLang.Action_Friendly; - // if (_isEot) - // { - // result += "Hot"; - // } - // } - // else - // { - // result = LocalizationManager.RightLang.Action_Attack; - - // if (_isEot) - // { - // result += "Dot"; - // } - // } - // result += "-" + (IsRealGCD ? "GCD" : LocalizationManager.RightLang.Timeline_Ability); - // return result; - // } - //} public bool IsEnabled { get => !Service.Config.DisabledActions.Contains(ID); diff --git a/RotationSolver.Basic/Configuration/PluginConfiguration.cs b/RotationSolver.Basic/Configuration/PluginConfiguration.cs index 7a626c52c..9985b0441 100644 --- a/RotationSolver.Basic/Configuration/PluginConfiguration.cs +++ b/RotationSolver.Basic/Configuration/PluginConfiguration.cs @@ -156,6 +156,11 @@ public class PluginConfiguration : IPluginConfiguration public bool ShowControlWindow = false; public bool IsControlWindowLock = true; + public Vector4 ControlWindowLockBg = new Vector4(0, 0, 0, 0.5f); + public Vector4 ControlWindowUnlockBg = new Vector4(0, 0, 0, 1); + public float ControlWindowGCDSize = 40; + public float ControlWindow0GCDSize = 30; + public float ControlWindowNextSizeRatio = 1.5f; public void Save() { diff --git a/RotationSolver.Basic/Data/IconSet.cs b/RotationSolver.Basic/Data/IconSet.cs index 699807385..debfba90b 100644 --- a/RotationSolver.Basic/Data/IconSet.cs +++ b/RotationSolver.Basic/Data/IconSet.cs @@ -24,7 +24,7 @@ public static class IconSet { private static readonly Dictionary _textures = new Dictionary(); - public static TextureWrap GetTexture(this ITexture text) => GetTexture(text.IconID); + public static TextureWrap GetTexture(this ITexture text) => GetTexture(text?.IconID ?? 0); public static TextureWrap GetTexture(uint id) { diff --git a/RotationSolver.Basic/Helpers/ActionHelper.cs b/RotationSolver.Basic/Helpers/ActionHelper.cs index 49fe92fa9..2b6ebaa5d 100644 --- a/RotationSolver.Basic/Helpers/ActionHelper.cs +++ b/RotationSolver.Basic/Helpers/ActionHelper.cs @@ -4,9 +4,9 @@ namespace RotationSolver.Basic.Helpers; -internal static class ActionHelper +public static class ActionHelper { - internal const byte GCDCooldownGroup = 58; + public const byte GCDCooldownGroup = 58; internal static ActionCate GetActionType(this Action action) => (ActionCate)action.ActionCategory.Value.RowId; internal static bool IsGeneralGCD(this Action action) => action.CooldownGroup == GCDCooldownGroup; diff --git a/RotationSolver.Basic/Rotations/CustomRotation_Ability.cs b/RotationSolver.Basic/Rotations/CustomRotation_Ability.cs index 812e5dfd2..9395e5479 100644 --- a/RotationSolver.Basic/Rotations/CustomRotation_Ability.cs +++ b/RotationSolver.Basic/Rotations/CustomRotation_Ability.cs @@ -131,6 +131,7 @@ private bool AntiKnockback(JobRole role, SpecialCommandType specialType, out IAc private bool GeneralHealAbility(byte abilitiesRemaining, SpecialCommandType specialType, out IAction act) { act = null; + switch (specialType) { case SpecialCommandType.DefenseArea: @@ -142,7 +143,7 @@ private bool GeneralHealAbility(byte abilitiesRemaining, SpecialCommandType spec break; } - if ((DataCenter.HPNotFull || Job.RowId == (uint)ClassJobID.BlackMage) && InCombat) + if ((DataCenter.HPNotFull || Job.GetJobRole() != JobRole.Healer) && InCombat) { if ((DataCenter.SpecialType == SpecialCommandType.HealArea || CanHealAreaAbility) && HealAreaAbility(abilitiesRemaining, out act)) return true; if ((DataCenter.SpecialType == SpecialCommandType.HealSingle || CanHealSingleAbility) && HealSingleAbility(abilitiesRemaining, out act)) return true; diff --git a/RotationSolver.Basic/Rotations/CustomRotation_BasicInfo.cs b/RotationSolver.Basic/Rotations/CustomRotation_BasicInfo.cs index 22e480bc9..5c8fca91b 100644 --- a/RotationSolver.Basic/Rotations/CustomRotation_BasicInfo.cs +++ b/RotationSolver.Basic/Rotations/CustomRotation_BasicInfo.cs @@ -1,6 +1,7 @@ using Dalamud.Game.ClientState.Objects.Types; using Lumina.Excel.GeneratedSheets; using RotationSolver.Basic; +using RotationSolver.Basic.Actions; using RotationSolver.Basic.Attributes; using RotationSolver.Basic.Configuration.RotationConfig; using RotationSolver.Basic.Data; @@ -44,6 +45,38 @@ public bool IsEnabled public virtual string Description { get; } = 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 EsunaStanceNorthGCD { get; private set; } + + public IAction EsunaStanceNorthAbility { get; private set; } + + public IAction RaiseShirkGCD { get; private set; } + + public IAction RaiseShirkAbility { get; private set; } + + public IAction AntiKnockbackAbility { get; private set; } + /// /// Description about the actions. /// diff --git a/RotationSolver.Basic/Rotations/CustomRotation_GCD.cs b/RotationSolver.Basic/Rotations/CustomRotation_GCD.cs index e50245895..f081a608a 100644 --- a/RotationSolver.Basic/Rotations/CustomRotation_GCD.cs +++ b/RotationSolver.Basic/Rotations/CustomRotation_GCD.cs @@ -25,7 +25,8 @@ private IAction GCD(byte abilityRemain, bool helpDefenseAOE, bool helpDefenseSin } //General Heal - if (DataCenter.HPNotFull && (DataCenter.InCombat || Service.Config.HealOutOfCombat)) + if ((DataCenter.HPNotFull || Job.GetJobRole() != JobRole.Healer) + && (DataCenter.InCombat || Service.Config.HealOutOfCombat)) { if ((specialType == SpecialCommandType.HealArea || CanHealAreaSpell) && HealAreaGCD(out act)) return act; if ((specialType == SpecialCommandType.HealSingle || CanHealSingleSpell) && HealSingleGCD(out act)) return act; @@ -58,10 +59,12 @@ private bool RaiseSpell(SpecialCommandType specialType, out IAction act, byte ac if (Raise == null) return false; if (Player.CurrentMp <= Service.Config.LessMPNoRaise) return false; + if (specialType == SpecialCommandType.RaiseShirk && DataCenter.DeathPeopleAll.Any()) return true; + if ((Service.Config.RaiseAll ? DataCenter.DeathPeopleAll.Any() : DataCenter.DeathPeopleParty.Any()) && Raise.CanUse(out act)) { - if (specialType == SpecialCommandType.RaiseShirk || HasSwift) + if (HasSwift) { return true; } diff --git a/RotationSolver.Basic/Rotations/CustomRotation_Invoke.cs b/RotationSolver.Basic/Rotations/CustomRotation_Invoke.cs index 3c1bb71f1..00b054a56 100644 --- a/RotationSolver.Basic/Rotations/CustomRotation_Invoke.cs +++ b/RotationSolver.Basic/Rotations/CustomRotation_Invoke.cs @@ -15,7 +15,47 @@ public bool TryInvoke(out IAction newAction, out IAction gcdAction) return false; } - MoveTarget = (MoveForwardAbility(1, out var act, recordTarget: false) && act is BaseAction a) ? a.Target : null; + ActionMoveForwardGCD = MoveForwardGCD(out var act) ? act : null; + ActionMoveForwardAbility = MoveForwardAbility(DataCenter.AbilityRemainCount, out act, recordTarget: false) ? act : null; + MoveTarget = act is IBaseAction a ? a.Target : null; + + ActionMoveBackAbility = MoveBackAbility(DataCenter.AbilityRemainCount, out act) ? act : null; + + ActionHealAreaGCD = HealAreaGCD(out act) ? act : null; + ActionHealAreaAbility = HealAreaAbility(DataCenter.AbilityRemainCount, out act) ? act : null; + + ActionHealSingleGCD = HealSingleGCD(out act) ? act : null; + ActionHealSingleAbility = HealSingleAbility(DataCenter.AbilityRemainCount, out act) ? act : null; + + ActionDefenseAreaGCD = DefenseAreaGCD(out act) ? act : null; + ActionDefenseAreaAbility = DefenseAreaAbility(DataCenter.AbilityRemainCount, out act) ? act : null; + + ActionDefenseSingleGCD = DefenseSingleGCD(out act) ? act : null; + ActionDefenseSingleAbility = DefenseSingleAbility(DataCenter.AbilityRemainCount, out act) ? act : null; + + var role = Job.GetJobRole(); + EsunaStanceNorthGCD = role switch + { + JobRole.Healer => DataCenter.WeakenPeople.Any() && Esuna.CanUse(out act, mustUse: true) ? act : null, + _ => null, + }; + EsunaStanceNorthAbility = role switch + { + JobRole.Melee => TrueNorth.CanUse(out act) ? act : null, + JobRole.Tank => Shield.CanUse(out act) ? act : null, + _ => null, + }; + RaiseShirkGCD = role switch + { + JobRole.Healer => DataCenter.DeathPeopleAll.Any() && Raise.CanUse(out act) ? act : null, + _ => null, + }; + RaiseShirkAbility = role switch + { + JobRole.Tank => Shirk.CanUse(out act) ? act : null, + _ => null, + }; + AntiKnockbackAbility = AntiKnockback(role, SpecialCommandType.AntiKnockback, out act) ? act : null; UpdateInfo(); newAction = Invoke(out gcdAction); diff --git a/RotationSolver.Basic/Rotations/ICustomRotation.cs b/RotationSolver.Basic/Rotations/ICustomRotation.cs index b15dd8e91..0b285f841 100644 --- a/RotationSolver.Basic/Rotations/ICustomRotation.cs +++ b/RotationSolver.Basic/Rotations/ICustomRotation.cs @@ -29,5 +29,21 @@ public interface ICustomRotation : ITexture MethodInfo[] AllLast { get; } MethodInfo[] AllGCDs { get; } + IAction ActionHealAreaGCD { get; } + IAction ActionHealAreaAbility { get; } + IAction ActionHealSingleGCD { get; } + IAction ActionHealSingleAbility { get; } + IAction ActionDefenseAreaGCD { get; } + IAction ActionDefenseAreaAbility { get; } + IAction ActionDefenseSingleGCD { get; } + IAction ActionDefenseSingleAbility { get; } + IAction ActionMoveForwardGCD { get; } + IAction ActionMoveForwardAbility { get; } + IAction ActionMoveBackAbility { get; } + IAction EsunaStanceNorthGCD { get; } + IAction EsunaStanceNorthAbility { get; } + IAction RaiseShirkGCD { get; } + IAction RaiseShirkAbility { get; } + IAction AntiKnockbackAbility { get; } bool TryInvoke(out IAction newAction, out IAction gcdAction); } diff --git a/RotationSolver/Commands/RSCommands_BasicInfo.cs b/RotationSolver/Commands/RSCommands_BasicInfo.cs index af241e5aa..d28a85a43 100644 --- a/RotationSolver/Commands/RSCommands_BasicInfo.cs +++ b/RotationSolver/Commands/RSCommands_BasicInfo.cs @@ -1,76 +1,87 @@ using Dalamud.Game.Command; using FFXIVClientStructs.FFXIV.Client.Game.UI; +using Lumina.Excel.GeneratedSheets; using RotationSolver.Basic; using RotationSolver.Basic.Data; using RotationSolver.Localization; using System; using System.Linq; -namespace RotationSolver.Commands +namespace RotationSolver.Commands; + +public static partial class RSCommands { - public static partial class RSCommands + internal static TargetingType TargetingType { - internal static TargetingType TargetingType + get { - get + if (Service.Config.TargetingTypes.Count == 0) { - if (Service.Config.TargetingTypes.Count == 0) - { - Service.Config.TargetingTypes.Add(TargetingType.Big); - Service.Config.TargetingTypes.Add(TargetingType.Small); - Service.Config.Save(); - } - - return Service.Config.TargetingTypes[Service.Config.TargetingIndex %= Service.Config.TargetingTypes.Count]; + Service.Config.TargetingTypes.Add(TargetingType.Big); + Service.Config.TargetingTypes.Add(TargetingType.Small); + Service.Config.Save(); } + + return Service.Config.TargetingTypes[Service.Config.TargetingIndex %= Service.Config.TargetingTypes.Count]; } + } - internal static void Enable() - => Service.CommandManager.AddHandler(Service.Command, new CommandInfo(OnCommand) - { - HelpMessage = LocalizationManager.RightLang.Commands_Rotation, - ShowInHelp = true, - }); + internal static void Enable() + => Service.CommandManager.AddHandler(Service.Command, new CommandInfo(OnCommand) + { + HelpMessage = LocalizationManager.RightLang.Commands_Rotation, + ShowInHelp = true, + }); + + internal static void Disable() => Service.CommandManager.RemoveHandler(Service.Command); - internal static void Disable() => Service.CommandManager.RemoveHandler(Service.Command); + private static void OnCommand(string command, string arguments) + { + DoOneCommand(arguments); + } - private static void OnCommand(string command, string arguments) + private static void DoOneCommand(string str) + { + if (TryGetOneEnum(str, out var stateType)) + { + DoStateCommandType(stateType); + } + else if (TryGetOneEnum(str, out var specialType)) + { + DoSpecialCommandType(specialType); + } + else if (TryGetOneEnum(str, out var otherType)) + { + DoOtherCommand(otherType, str.Substring(otherType.ToString().Length).Trim()); + } + else { - DoOneCommand(arguments); + RotationSolverPlugin.OpenConfigWindow(); } + } - private static void DoOneCommand(string str) + private static bool TryGetOneEnum(string str, out T type) where T : struct, Enum + { + type = default; + try { - if (TryGetOneEnum(str, out var stateType)) - { - DoStateCommandType(stateType); - } - else if (TryGetOneEnum(str, out var specialType)) - { - DoSpecialCommandType(specialType); - } - else if (TryGetOneEnum(str, out var otherType)) - { - DoOtherCommand(otherType, str.Substring(otherType.ToString().Length).Trim()); - } - else - { - RotationSolverPlugin.OpenConfigWindow(); - } + type = Enum.GetValues().First(c => str.StartsWith(c.ToString(), StringComparison.OrdinalIgnoreCase)); + return true; } + catch + { + return false; + } + } - private static bool TryGetOneEnum(string str, out T type) where T : struct, Enum + internal static string GetCommandStr(this T command, string extraCommand = "") + where T : struct, Enum + { + var cmdStr = Service.Command + " " + command.ToString(); + if (!string.IsNullOrEmpty(extraCommand)) { - type = default; - try - { - type = Enum.GetValues().First(c => str.StartsWith(c.ToString(), StringComparison.OrdinalIgnoreCase)); - return true; - } - catch - { - return false; - } + cmdStr += " " + extraCommand; } + return cmdStr; } } diff --git a/RotationSolver/Localization/Localization.json b/RotationSolver/Localization/Localization.json index 767b755eb..9543a72c5 100644 --- a/RotationSolver/Localization/Localization.json +++ b/RotationSolver/Localization/Localization.json @@ -31,6 +31,7 @@ "ConfigWindow_HelpItem_MoveBack": "Open a window to move back.", "ConfigWindow_HelpItem_EndSpecial": "Close special window.", "ConfigWindow_Helper_SwitchRotation": "Click to switch authors", + "ConfigWindow_Helper_HighEndWarning": "This `{0}` rotation is not allowed to be used in High-end Duty!", "ConfigWindow_Helper_GameVersion": "Game Version", "ConfigWindow_Helper_OpenSource": "Open the source code URL", "ConfigWindow_Helper_RunCommand": "Click to execute the command", @@ -172,6 +173,10 @@ "ConfigWindow_Param_ConditionDelete": "Delete", "ConfigWindow_Control_ShowControlWindow": "Show Control Window", "ConfigWindow_Control_IsControlWindowLock": "Lock Control Window", + "ConfigWindow_Control_BackgroundColor": "Control Window's Background", + "ConfigWindow_Control_ControlWindowGCDSize": "GCD icon size", + "ConfigWindow_Control_ControlWindow0GCDSize": "0GCD icon size", + "ConfigWindow_Control_ControlWindowNextSizeRatio": "Next Action Size Ratio", "Timeline_DragdropDescription": "Drag&drop to move,Ctrl+Alt+RightClick to delete.", "Timeline_SearchBar": "Search Bar", "Timeline_MustUse": "MustUse", diff --git a/RotationSolver/Localization/Strings_Major.cs b/RotationSolver/Localization/Strings.cs similarity index 98% rename from RotationSolver/Localization/Strings_Major.cs rename to RotationSolver/Localization/Strings.cs index 429e1f053..169f59f75 100644 --- a/RotationSolver/Localization/Strings_Major.cs +++ b/RotationSolver/Localization/Strings.cs @@ -75,6 +75,7 @@ internal partial class Strings public string ConfigWindow_HelpItem_EndSpecial { get; set; } = "Close special window."; public string ConfigWindow_Helper_SwitchRotation { get; set; } = "Click to switch authors"; + public string ConfigWindow_Helper_HighEndWarning { get; set; } = "This `{0}` rotation is not allowed to be used in High-end Duty!"; public string ConfigWindow_Helper_GameVersion { get; set; } = "Game Version"; public string ConfigWindow_Helper_OpenSource { get; set; } = "Open the source code URL"; public string ConfigWindow_Helper_RunCommand { get; set; } = "Click to execute the command"; @@ -237,6 +238,10 @@ internal partial class Strings public string ConfigWindow_Control_ShowControlWindow { get; set; } = "Show Control Window"; public string ConfigWindow_Control_IsControlWindowLock { get; set; } = "Lock Control Window"; + public string ConfigWindow_Control_BackgroundColor { get; set; } = "Control Window's Background"; + public string ConfigWindow_Control_ControlWindowGCDSize { get; set; } = "GCD icon size"; + public string ConfigWindow_Control_ControlWindow0GCDSize { get; set; } = "0GCD icon size"; + public string ConfigWindow_Control_ControlWindowNextSizeRatio { get; set; } = "Next Action Size Ratio"; #endregion diff --git a/RotationSolver/Localization/Strings_Rotation.cs b/RotationSolver/Localization/Strings_Rotation.cs deleted file mode 100644 index 827e0b623..000000000 --- a/RotationSolver/Localization/Strings_Rotation.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace RotationSolver.Localization; - -internal partial class Strings -{ - //Add your Rotation Translations here as Properties. -} diff --git a/RotationSolver/UI/ControlWindow.cs b/RotationSolver/UI/ControlWindow.cs index 39b18f575..15c83c58a 100644 --- a/RotationSolver/UI/ControlWindow.cs +++ b/RotationSolver/UI/ControlWindow.cs @@ -1,12 +1,23 @@ using Dalamud.Interface.Windowing; using ImGuiNET; using RotationSolver.Basic; +using RotationSolver.Updaters; using System; using System.Collections.Generic; using System.Linq; using System.Net.Sockets; +using System.Numerics; using System.Text; using System.Threading.Tasks; +using RotationSolver.Basic.Data; +using RotationSolver.Basic.Actions; +using RotationSolver.Commands; +using RotationSolver.Basic.Helpers; +using FFXIVClientStructs.FFXIV.Client.Game; +using Dalamud.Interface.Colors; +using RotationSolver.Localization; +using Lumina.Excel.GeneratedSheets; +using ImGuiScene; namespace RotationSolver.UI; @@ -26,16 +37,185 @@ public ControlWindow() public override void PreDraw() { + Vector4 bgColor = Service.Config.IsControlWindowLock + ? Service.Config.ControlWindowLockBg + : Service.Config.ControlWindowUnlockBg; + ImGui.PushStyleColor(ImGuiCol.WindowBg, bgColor); + Flags = _baseFlags; if (Service.Config.IsControlWindowLock) { Flags |= ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoMove | ImGuiWindowFlags.NoMouseInputs; } + + ImGui.PushStyleVar(ImGuiStyleVar.WindowPadding, new Vector2(0, 0)); + ImGui.PushStyleVar(ImGuiStyleVar.WindowBorderSize, 0); + } + + public override void PostDraw() + { + ImGui.PopStyleColor(); + ImGui.PopStyleVar(2); + base.PostDraw(); } - public override void Draw() + static void DrawCommand(T command, Func getHelp = null) where T : struct, Enum { - ImGui.Text("Hello!"); + var cmdStr = command.GetCommandStr(); + + if (ImGui.Button(command.ToString())) + { + Service.CommandManager.ProcessCommand(cmdStr); + } + if (ImGui.IsItemHovered()) + { + var help = getHelp?.Invoke(command); + if (!string.IsNullOrEmpty(help)) + { + ImGui.SetTooltip(help); + } + + if (ImGui.IsMouseDown(ImGuiMouseButton.Right)) + { + ImGui.SetClipboardText(cmdStr); + } + } + } + + public override void Draw() + { + ImGui.Columns(2, "Control Bolder", false); + ImGui.SetColumnWidth(0, DrawNextAction() + ImGui.GetStyle().ColumnsMinSpacing * 2); + + DrawCommand(StateCommandType.Smart, EnumTranslations.ToHelp); + + DrawCommand(StateCommandType.Manual, EnumTranslations.ToHelp); + + DrawCommand(StateCommandType.Cancel, EnumTranslations.ToHelp); + + + ImGui.NextColumn(); + var rotation = RotationUpdater.RightNowRotation; + DrawCommandAction(rotation.ActionHealAreaGCD, rotation.ActionHealAreaAbility, + SpecialCommandType.HealArea, ImGuiColors.HealerGreen); + + ImGui.SameLine(); + + DrawCommandAction(rotation.ActionHealSingleGCD, rotation.ActionHealSingleAbility, + SpecialCommandType.HealSingle, ImGuiColors.HealerGreen); + + ImGui.SameLine(); + + DrawCommandAction(rotation.ActionDefenseAreaGCD, rotation.ActionDefenseAreaAbility, + SpecialCommandType.DefenseArea, ImGuiColors.TankBlue); + + ImGui.SameLine(); + + DrawCommandAction(rotation.ActionDefenseSingleGCD, rotation.ActionDefenseSingleAbility, + SpecialCommandType.DefenseSingle, ImGuiColors.TankBlue); + + DrawCommandAction(rotation.ActionMoveForwardGCD, rotation.ActionMoveForwardAbility, + SpecialCommandType.MoveForward, ImGuiColors.DalamudOrange); + + ImGui.SameLine(); + + DrawCommandAction(null, rotation.ActionMoveBackAbility, + SpecialCommandType.MoveBack, ImGuiColors.DalamudOrange); + + DrawCommandAction(rotation.EsunaStanceNorthGCD, rotation.EsunaStanceNorthAbility, + SpecialCommandType.EsunaStanceNorth, ImGuiColors.ParsedGold); + + ImGui.SameLine(); + + DrawCommandAction(rotation.RaiseShirkGCD, rotation.RaiseShirkAbility, + SpecialCommandType.RaiseShirk, ImGuiColors.ParsedBlue); + + ImGui.SameLine(); + + DrawCommandAction(null, rotation.AntiKnockbackAbility, + SpecialCommandType.AntiKnockback, ImGuiColors.DalamudWhite2); + + ImGui.SetCursorPosY(ImGui.GetCursorPosY() + 5); + + DrawCommand(SpecialCommandType.Burst, EnumTranslations.ToHelp); + + ImGui.SameLine(); + + DrawCommand(SpecialCommandType.EndSpecial, EnumTranslations.ToHelp); + } + + static void DrawCommandAction(IAction gcd, IAction ability, SpecialCommandType command, Vector4 color) + { + var gcdW = Service.Config.ControlWindowGCDSize; + var abilityW = Service.Config.ControlWindow0GCDSize; + var width = gcdW + abilityW + ImGui.GetStyle().ItemSpacing.X + ImGui.GetStyle().ItemInnerSpacing.X * 4; + + ImGui.BeginGroup(); + var str = command.ToString(); + ImGui.SetCursorPosX(ImGui.GetCursorPosX() + width / 2 - ImGui.CalcTextSize(str).X / 2); + ImGui.TextColored(color, str); + + DrawIAction(gcd, gcdW, command); + ImGuiHelper.HoveredString(command.ToHelp()); + + ImGui.SameLine(); + DrawIAction(ability, abilityW, command); + ImGuiHelper.HoveredString(command.ToHelp()); + ImGui.EndGroup(); + } + + static readonly Dictionary _actionIcons = new Dictionary(); + + static TextureWrap GetTexture(IAction action) + { + uint iconId = 0; + if(action != null && !_actionIcons.TryGetValue(action.AdjustedID, out iconId)) + { + _actionIcons[action.AdjustedID] = iconId = + Service.GetSheet().GetRow(action.AdjustedID).Icon; + } + return IconSet.GetTexture(iconId); + } + + static void DrawIAction(IAction action, float width, SpecialCommandType command) + { + if(ImGui.ImageButton(GetTexture(action).ImGuiHandle, new Vector2(width, width))) + { + Service.CommandManager.ProcessCommand(command.GetCommandStr()); + } + } + + static void DrawIAction(IAction action, float width) + { + ImGui.Image(GetTexture(action).ImGuiHandle, new Vector2(width, width)); + } + + static unsafe float DrawNextAction() + { + var group = ActionManager.Instance()->GetRecastGroupDetail(ActionHelper.GCDCooldownGroup - 1); + var remain = group->Total - group->Elapsed; + + var gcd = Service.Config.ControlWindowGCDSize * Service.Config.ControlWindowNextSizeRatio; + var ability = Service.Config.ControlWindow0GCDSize * Service.Config.ControlWindowNextSizeRatio; + var width = gcd + ability + ImGui.GetStyle().ItemSpacing.X; + + var str = "Next Action"; + ImGui.SetCursorPosX(ImGui.GetCursorPosX() + width / 2 - ImGui.CalcTextSize(str).X / 2); + ImGui.TextColored(ImGuiColors.DalamudYellow, str); + str = remain.ToString("F2") + "s"; + + ImGui.SetCursorPosX(ImGui.GetCursorPosX() + width / 2 - ImGui.CalcTextSize(str).X / 2); + ImGui.Text(str); + ImGui.ProgressBar(group->Elapsed / group->Total, new Vector2(width, 5)); + + DrawIAction(ActionUpdater.NextGCDAction, gcd); + + var next = ActionUpdater.NextGCDAction != ActionUpdater.NextAction ? ActionUpdater.NextAction : null; + + ImGui.SameLine(); + DrawIAction(next, ability); + + return width; } } diff --git a/RotationSolver/UI/ImGuiHelper.cs b/RotationSolver/UI/ImGuiHelper.cs index 920216c7a..93c08ec8d 100644 --- a/RotationSolver/UI/ImGuiHelper.cs +++ b/RotationSolver/UI/ImGuiHelper.cs @@ -14,6 +14,7 @@ using RotationSolver.Basic.Data; using RotationSolver.Basic.Helpers; using RotationSolver.Basic.Rotations; +using RotationSolver.Commands; using RotationSolver.Localization; using RotationSolver.Updaters; using System.ComponentModel; @@ -323,11 +324,7 @@ internal static void SearchItems(ref string searchTxt, IEnumerable actions internal static void DisplayCommandHelp(this T command, string extraCommand = "", Func getHelp = null, bool sameLine = true) where T : struct, Enum { - var cmdStr = Service.Command + " " + command.ToString(); - if (!string.IsNullOrEmpty(extraCommand)) - { - cmdStr += " " + extraCommand; - } + var cmdStr = command.GetCommandStr(extraCommand); if (ImGui.Button(cmdStr)) { @@ -446,7 +443,7 @@ public unsafe static void Display(this ICustomRotation rotation, ICustomRotation ImGui.Text(rotation.GetAuthor()); if (!rotation.IsAllowed(out _)) { - var showStr = $"This `{rotation}` rotation is not allowed to be used in High-end Duty!" + var showStr = string.Format(LocalizationManager.RightLang.ConfigWindow_Helper_HighEndWarning, rotation) + string.Join("", SocialUpdater.HighEndDuties.Select(x => x.PlaceName?.Value?.Name.ToString()) .Where(s => !string.IsNullOrEmpty(s)).Select(t => "\n - " + t)); diff --git a/RotationSolver/UI/OverlayWindow.cs b/RotationSolver/UI/OverlayWindow.cs index c274c8f39..aa829c99f 100644 --- a/RotationSolver/UI/OverlayWindow.cs +++ b/RotationSolver/UI/OverlayWindow.cs @@ -129,7 +129,7 @@ private static void DrawTarget(BattleChara tar, uint color, float radius, out Ve const int COUNT = 20; private static void DrawPositional() { - if (ActionUpdater.NextGCDAction == null) return; + if (ActionUpdater.NextGCDAction == null || !ActionUpdater.NextGCDAction.IsMeleeAction()) return; Vector3 pPosition = ActionUpdater.NextGCDAction.Target.Position; Service.GameGui.WorldToScreen(pPosition, out var scrPos); diff --git a/RotationSolver/UI/RotationConfigWindow_Control.cs b/RotationSolver/UI/RotationConfigWindow_Control.cs index 1501f6b69..0af542301 100644 --- a/RotationSolver/UI/RotationConfigWindow_Control.cs +++ b/RotationSolver/UI/RotationConfigWindow_Control.cs @@ -1,8 +1,10 @@ -using RotationSolver.Basic; +using ImGuiNET; +using RotationSolver.Basic; using RotationSolver.Localization; using System; using System.Collections.Generic; using System.Linq; +using System.Numerics; using System.Text; using System.Threading.Tasks; @@ -19,5 +21,39 @@ private void DrawControlTab() DrawCheckBox(LocalizationManager.RightLang.ConfigWindow_Control_IsControlWindowLock, ref Service.Config.IsControlWindowLock); + + if (Service.Config.IsControlWindowLock) + { + DrawColor4(LocalizationManager.RightLang.ConfigWindow_Control_BackgroundColor, + ref Service.Config.ControlWindowLockBg); + } + else + { + DrawColor4(LocalizationManager.RightLang.ConfigWindow_Control_BackgroundColor, + ref Service.Config.ControlWindowUnlockBg); + } + + DrawFloatNumber(LocalizationManager.RightLang.ConfigWindow_Control_ControlWindowGCDSize, + ref Service.Config.ControlWindowGCDSize); + + DrawFloatNumber(LocalizationManager.RightLang.ConfigWindow_Control_ControlWindow0GCDSize, + ref Service.Config.ControlWindow0GCDSize); + + + DrawFloatNumber(LocalizationManager.RightLang.ConfigWindow_Control_ControlWindowNextSizeRatio, + ref Service.Config.ControlWindowNextSizeRatio); + } + + private static void DrawColor4(string name, ref Vector4 value, string description = "") + { + ImGui.SetNextItemWidth(210); + if (ImGui.ColorEdit4(name, ref value)) + { + Service.Config.Save(); + } + if (!string.IsNullOrEmpty(description) && ImGui.IsItemHovered()) + { + ImGui.SetTooltip(description); + } } } diff --git a/RotationSolver/UI/RotationConfigWindow_Major.cs b/RotationSolver/UI/RotationConfigWindow_Major.cs index 1fd0c9fb3..9d46ec96a 100644 --- a/RotationSolver/UI/RotationConfigWindow_Major.cs +++ b/RotationSolver/UI/RotationConfigWindow_Major.cs @@ -57,11 +57,13 @@ public override unsafe void Draw() ImGui.EndTabItem(); } +#if DEBUG if (ImGui.BeginTabItem(LocalizationManager.RightLang.ConfigWindow_ControlItem)) { DrawControlTab(); ImGui.EndTabItem(); } +#endif if (ImGui.BeginTabItem(LocalizationManager.RightLang.ConfigWindow_HelpItem)) { diff --git a/RotationSolver/UI/RotationConfigWindow_Param.cs b/RotationSolver/UI/RotationConfigWindow_Param.cs index 475242714..4a2c369e7 100644 --- a/RotationSolver/UI/RotationConfigWindow_Param.cs +++ b/RotationSolver/UI/RotationConfigWindow_Param.cs @@ -186,7 +186,7 @@ private void DrawParamDisplay() { ImGuiHelper.Spacing(); - DrawColor(LocalizationManager.RightLang.ConfigWindow_Param_TeachingModeColor, + DrawColor3(LocalizationManager.RightLang.ConfigWindow_Param_TeachingModeColor, ref Service.Config.TeachingModeColor); } @@ -199,7 +199,7 @@ private void DrawParamDisplay() { ImGuiHelper.Spacing(); - DrawColor(LocalizationManager.RightLang.ConfigWindow_Param_MovingTargetColor, + DrawColor3(LocalizationManager.RightLang.ConfigWindow_Param_MovingTargetColor, ref Service.Config.MovingTargetColor); } @@ -210,12 +210,12 @@ private void DrawParamDisplay() { ImGuiHelper.Spacing(); - DrawColor(LocalizationManager.RightLang.ConfigWindow_Param_TargetColor, + DrawColor3(LocalizationManager.RightLang.ConfigWindow_Param_TargetColor, ref Service.Config.TargetColor); ImGuiHelper.Spacing(); - DrawColor(LocalizationManager.RightLang.ConfigWindow_Params_SubTargetColor, + DrawColor3(LocalizationManager.RightLang.ConfigWindow_Params_SubTargetColor, ref Service.Config.SubTargetColor); } } @@ -514,7 +514,7 @@ private static void DrawIntNumber(string name, ref int value, float speed = 0.2f } } - private static void DrawColor(string name, ref Vector3 value, string description = "") + private static void DrawColor3(string name, ref Vector3 value, string description = "") { ImGui.SetNextItemWidth(210); if (ImGui.ColorEdit3(name, ref value)) diff --git a/RotationSolver/Updaters/ActionUpdater.cs b/RotationSolver/Updaters/ActionUpdater.cs index 8551d5a48..af417ff40 100644 --- a/RotationSolver/Updaters/ActionUpdater.cs +++ b/RotationSolver/Updaters/ActionUpdater.cs @@ -41,7 +41,7 @@ internal static void UpdateNextAction() { NextAction = newAction; - if (gcdAction is IBaseAction GcdAction && GcdAction.IsMeleeAction()) + if (gcdAction is IBaseAction GcdAction) { NextGCDAction = GcdAction;