diff --git a/Benchmark/Program.cs b/Benchmark/Program.cs index 832c8cd..377620b 100644 --- a/Benchmark/Program.cs +++ b/Benchmark/Program.cs @@ -77,11 +77,11 @@ internal static class Program Console.WriteLine($"{state.Quality} {state.CP} {state.Progress} {state.Durability}"); //return; - var (_, s) = Solver.Crafty.Solver.SearchStepwiseFurcated(config, state, a => Console.WriteLine(a)); + var (_, s) = Solver.Crafty.Solver.SearchStepwiseFurcated(config, state, a => Console.WriteLine(a), default); Console.WriteLine($"Qual: {s.Quality}/{s.Input.Recipe.MaxQuality}"); return; - Solver.Crafty.Solver.SearchStepwiseFurcated(config, input); + Solver.Crafty.Solver.SearchStepwiseFurcated(config, new(input), null, default); //Benchmark(() => ); } diff --git a/Craftimizer/SimulatorUtils.cs b/Craftimizer/SimulatorUtils.cs index 4d30def..806f40a 100644 --- a/Craftimizer/SimulatorUtils.cs +++ b/Craftimizer/SimulatorUtils.cs @@ -162,11 +162,17 @@ internal static class ClassJobUtils return CultureInfo.InvariantCulture.TextInfo.ToTitleCase(job.Name.ToDalamudString().TextValue); } + public static string GetAbbreviation(this ClassJob me) + { + var job = LuminaSheets.ClassJobSheet.GetRow(me.GetClassJobIndex())!; + return job.Abbreviation.ToDalamudString().TextValue; + } + public static Quest GetUnlockQuest(this ClassJob me) => LuminaSheets.QuestSheet.GetRow(65720 + (uint)me) ?? throw new ArgumentException($"Could not get unlock quest for {me}", nameof(me)); public static ushort GetIconId(this ClassJob me) => - (ushort)(62100 + me.GetClassJobIndex()); + (ushort)(62000 + me.GetClassJobIndex()); public static bool IsClassJob(this ClassJobCategory me, ClassJob classJob) => classJob switch diff --git a/Craftimizer/Windows/RecipeNote.cs b/Craftimizer/Windows/RecipeNote.cs index 4685ded..ee348fe 100644 --- a/Craftimizer/Windows/RecipeNote.cs +++ b/Craftimizer/Windows/RecipeNote.cs @@ -9,7 +9,6 @@ using Dalamud.Interface.Components; using Dalamud.Interface.GameFonts; using Dalamud.Interface.Raii; using Dalamud.Interface.Windowing; -using Dalamud.Logging; using Dalamud.Utility; using FFXIVClientStructs.FFXIV.Client.Game; using FFXIVClientStructs.FFXIV.Client.Game.UI; @@ -92,6 +91,7 @@ public sealed unsafe class RecipeNote : Window, IDisposable return false; } + var statsChanged = false; { var instance = CSRecipeNote.Instance(); @@ -104,7 +104,11 @@ public sealed unsafe class RecipeNote : Window, IDisposable return false; var recipeId = recipeEntry->RecipeId; - RecipeData = new(recipeId); + if (recipeId != RecipeData?.RecipeId) + { + RecipeData = new(recipeId); + statsChanged = true; + } } Gearsets.GearsetItem[] gearItems; @@ -117,10 +121,23 @@ public sealed unsafe class RecipeNote : Window, IDisposable gearItems = Gearsets.GetGearsetItems(container); - CharacterStats = Gearsets.CalculateCharacterStats(gearStats, gearItems, RecipeData.ClassJob.GetPlayerLevel(), RecipeData.ClassJob.CanPlayerUseManipulation()); + var characterStats = Gearsets.CalculateCharacterStats(gearStats, gearItems, RecipeData.ClassJob.GetPlayerLevel(), RecipeData.ClassJob.CanPlayerUseManipulation()); + if (characterStats != CharacterStats) + { + CharacterStats = characterStats; + statsChanged = true; + } } - CraftStatus = CalculateCraftStatus(gearItems); + var craftStatus = CalculateCraftStatus(gearItems); + if (craftStatus != CraftStatus) + { + CraftStatus = craftStatus; + statsChanged = true; + } + + if (statsChanged && CraftStatus == CraftableStatus.OK) + CalculateBestMacros(); return true; } @@ -145,16 +162,28 @@ public sealed unsafe class RecipeNote : Window, IDisposable public override void Draw() { - using var table = ImRaii.Table("stats", 2, ImGuiTableFlags.BordersInnerV | ImGuiTableFlags.SizingStretchSame); - if (table) { - ImGui.TableSetupColumn("col1", ImGuiTableColumnFlags.WidthStretch); - ImGui.TableSetupColumn("col2", ImGuiTableColumnFlags.WidthStretch); - ImGui.TableNextColumn(); - DrawCharacterStats(); - ImGui.TableNextColumn(); - DrawRecipeStats(); + using var table = ImRaii.Table("stats", 2, ImGuiTableFlags.BordersInnerV | ImGuiTableFlags.SizingStretchSame); + if (table) + { + ImGui.TableSetupColumn("col1", ImGuiTableColumnFlags.WidthStretch); + ImGui.TableSetupColumn("col2", ImGuiTableColumnFlags.WidthStretch); + ImGui.TableNextColumn(); + DrawCharacterStats(); + ImGui.TableNextColumn(); + DrawRecipeStats(); + } } + + if (CraftStatus != CraftableStatus.OK) + return; + + ImGui.Separator(); + + ImGuiUtils.TextCentered("Best Saved Macro"); + ImGuiUtils.ButtonCentered("View Saved Macros"); + ImGuiUtils.TextCentered("Suggested Macro"); + ImGuiUtils.ButtonCentered("Open Simulator"); } private void DrawCharacterStats() @@ -163,7 +192,12 @@ public sealed unsafe class RecipeNote : Window, IDisposable var level = RecipeData!.ClassJob.GetPlayerLevel(); { - var className = RecipeData.ClassJob.GetName(); + var textClassName = RecipeData.ClassJob.GetAbbreviation(); + Vector2 textClassSize; + { + var layout = AxisFont.LayoutBuilder(textClassName).Build(); + textClassSize = new(layout.Width, layout.Height); + } var levelText = string.Empty; if (level != 0) levelText = SqText.ToLevelString(level); @@ -178,7 +212,7 @@ public sealed unsafe class RecipeNote : Window, IDisposable ImGuiUtils.AlignCentered( imageSize + 5 + - ImGui.CalcTextSize(className).X + + textClassSize.X + (level == 0 ? 0 : (3 + ImGui.CalcTextSize(levelText).X)) + (hasSplendorous ? (3 + imageSize) : 0) + (hasSpecialist ? (3 + imageSize) : 0) + @@ -186,7 +220,12 @@ public sealed unsafe class RecipeNote : Window, IDisposable ); ImGui.AlignTextToFramePadding(); - ImGui.Image(Service.IconManager.GetIcon(RecipeData.ClassJob.GetIconId()).ImGuiHandle, new Vector2(imageSize)); + var uv0 = new Vector2(6, 3); + var uv1 = uv0 + new Vector2(44); + uv0 /= new Vector2(56); + uv1 /= new Vector2(56); + + ImGui.Image(Service.IconManager.GetIcon(RecipeData.ClassJob.GetIconId()).ImGuiHandle, new Vector2(imageSize), uv0, uv1); ImGui.SameLine(0, 5); if (level != 0) @@ -197,7 +236,8 @@ public sealed unsafe class RecipeNote : Window, IDisposable ImGui.SameLine(0, 3); } - ImGui.Text(className); + ImGui.SetCursorPosY(ImGui.GetCursorPosY() + (imageSize - textClassSize.Y) / 2); + AxisFont.Text(textClassName); if (hasSplendorous) { @@ -391,7 +431,7 @@ public sealed unsafe class RecipeNote : Window, IDisposable if (textStarsSize != Vector2.Zero) { ImGui.SameLine(0, 3); - ImGui.SetCursorPosY(ImGui.GetCursorPosY() + (textStarsSize.Y - textSize) / 2); + ImGui.SetCursorPosY(ImGui.GetCursorPosY() + (imageSize - textStarsSize.Y) / 2); AxisFont.Text(textStars); } @@ -414,6 +454,8 @@ public sealed unsafe class RecipeNote : Window, IDisposable } } + ImGui.Separator(); + using var table = ImRaii.Table("recipeStats", 2); if (table) { @@ -535,6 +577,11 @@ public sealed unsafe class RecipeNote : Window, IDisposable return null; } + private void CalculateBestMacros() + { + throw new NotImplementedException(); + } + public void Dispose() { AxisFont?.Dispose(); diff --git a/Solver/Crafty/Solver.cs b/Solver/Crafty/Solver.cs index f5192b3..0ed5d35 100644 --- a/Solver/Crafty/Solver.cs +++ b/Solver/Crafty/Solver.cs @@ -332,10 +332,7 @@ public sealed class Solver } } - public static SolverSolution SearchStepwiseFurcated(SolverConfig config, SimulationInput input, Action? actionCallback = null, CancellationToken token = default) => - SearchStepwiseFurcated(config, new SimulationState(input), actionCallback, token); - - public static SolverSolution SearchStepwiseFurcated(SolverConfig config, SimulationState state, Action? actionCallback = null, CancellationToken token = default) + public static SolverSolution SearchStepwiseFurcated(SolverConfig config, SimulationState state, Action? actionCallback, CancellationToken token) { var definiteActionCount = 0; var bestSims = new List<(float Score, SolverSolution Result)>(); @@ -445,10 +442,7 @@ public sealed class Solver return result; } - public static SolverSolution SearchStepwiseForked(SolverConfig config, SimulationInput input, Action? actionCallback = null, CancellationToken token = default) => - SearchStepwiseForked(config, new SimulationState(input), actionCallback, token); - - public static SolverSolution SearchStepwiseForked(SolverConfig config, SimulationState state, Action? actionCallback = null, CancellationToken token = default) + public static SolverSolution SearchStepwiseForked(SolverConfig config, SimulationState state, Action? actionCallback, CancellationToken token) { var actions = new List(); var sim = new Simulator(state, config.MaxStepCount); @@ -495,10 +489,7 @@ public sealed class Solver return new(actions, state); } - public static SolverSolution SearchStepwise(SolverConfig config, SimulationInput input, Action? actionCallback = null, CancellationToken token = default) => - SearchStepwise(config, new SimulationState(input), actionCallback, token); - - public static SolverSolution SearchStepwise(SolverConfig config, SimulationState state, Action? actionCallback = null, CancellationToken token = default) + public static SolverSolution SearchStepwise(SolverConfig config, SimulationState state, Action? actionCallback, CancellationToken token) { var actions = new List(); var sim = new Simulator(state, config.MaxStepCount); @@ -535,10 +526,7 @@ public sealed class Solver return new(actions, state); } - public static SolverSolution SearchOneshotForked(SolverConfig config, SimulationInput input, Action? actionCallback = null, CancellationToken token = default) => - SearchOneshotForked(config, new SimulationState(input), actionCallback, token); - - public static SolverSolution SearchOneshotForked(SolverConfig config, SimulationState state, Action? actionCallback = null, CancellationToken token = default) + public static SolverSolution SearchOneshotForked(SolverConfig config, SimulationState state, Action? actionCallback, CancellationToken token) { var tasks = new Task<(float MaxScore, SolverSolution Solution)>[config.ForkCount]; for (var i = 0; i < config.ForkCount; ++i) @@ -557,10 +545,7 @@ public sealed class Solver return solution; } - public static SolverSolution SearchOneshot(SolverConfig config, SimulationInput input, Action? actionCallback = null, CancellationToken token = default) => - SearchOneshot(config, new SimulationState(input), actionCallback, token); - - public static SolverSolution SearchOneshot(SolverConfig config, SimulationState state, Action? actionCallback = null, CancellationToken token = default) + public static SolverSolution SearchOneshot(SolverConfig config, SimulationState state, Action? actionCallback, CancellationToken token) { var solver = new Solver(config, state); solver.Search(config.Iterations, token); @@ -571,9 +556,6 @@ public sealed class Solver return solution; } - public static SolverSolution Search(SolverConfig config, SimulationInput input, Action? actionCallback = null, CancellationToken token = default) => - Search(config, new SimulationState(input), actionCallback, token); - public static SolverSolution Search(SolverConfig config, SimulationState state, Action? actionCallback = null, CancellationToken token = default) { Func?, CancellationToken, SolverSolution> func = config.Algorithm switch @@ -586,5 +568,4 @@ public sealed class Solver }; return func(config, state, actionCallback, token); } - }