diff --git a/Craftimizer/SimulatorUtils.cs b/Craftimizer/SimulatorUtils.cs index 82cf307..df4ecec 100644 --- a/Craftimizer/SimulatorUtils.cs +++ b/Craftimizer/SimulatorUtils.cs @@ -11,6 +11,7 @@ using Condition = Craftimizer.Simulator.Condition; using Craftimizer.Simulator; using System.Text; using System.Numerics; +using System.Globalization; namespace Craftimizer.Plugin; @@ -95,6 +96,12 @@ internal static class ClassJobUtils _ => 0 }; + public static string GetName(this ClassJob classJob) + { + var job = LuminaSheets.ClassJobSheet.GetRow(classJob.GetClassJobIndex())!; + return CultureInfo.InvariantCulture.TextInfo.ToTitleCase(job.Name.ToDalamudString().TextValue); + } + // Index in the actual ClassJob sheet public static bool IsClassJob(byte classJobIdx, ClassJob classJob) { diff --git a/Craftimizer/Windows/CraftingLog.cs b/Craftimizer/Windows/CraftingLog.cs index 66ce4c6..30ea05c 100644 --- a/Craftimizer/Windows/CraftingLog.cs +++ b/Craftimizer/Windows/CraftingLog.cs @@ -1,6 +1,7 @@ using Craftimizer.Plugin.Utils; using Craftimizer.Simulator; using Craftimizer.Simulator.Actions; +using Dalamud; using Dalamud.Interface; using Dalamud.Interface.Components; using Dalamud.Interface.Windowing; @@ -30,9 +31,16 @@ public unsafe class CraftingLog : Window private AddonRecipeNote* Addon { get; set; } private RecipeNote* State { get; set; } - private ushort SelectedRecipeId { get; set; } - private Recipe SelectedRecipe { get; set; } = null!; - private RecipeInfo SelectedRecipeInfo { get; set; } = null!; + private ushort RecipeId { get; set; } + private Recipe Recipe { get; set; } = null!; + private RecipeInfo RecipeInfo { get; set; } = null!; + + private ClassJob RecipeClassJob => (ClassJob)Recipe.CraftType.Row; + private short RecipeCharacterLevel => PlayerState.Instance()->ClassJobLevelArray[RecipeClassJob.GetClassJobIndex()]; + private bool RecipeCanUseManipulation => ActionManager.CanUseActionOnTarget(ActionType.Manipulation.GetId(RecipeClassJob), (GameObject*)Service.ClientState.LocalPlayer!.Address); + private RecipeLevelTable RecipeTable => Recipe.RecipeLevelTable.Value!; + + private int startingQuality; public CraftingLog() : base("RecipeNoteHelper", WindowFlags, true) { @@ -41,15 +49,74 @@ public unsafe class CraftingLog : Window public override void Draw() { - var inst = RaptureGearsetModule.Instance(); - if (Service.ClientState.LocalPlayer == null) return; - var recipeClassJob = (ClassJob)SelectedRecipe.CraftType.Row; + DrawCraftInfo(); - var characterLevel = PlayerState.Instance()->ClassJobLevelArray[recipeClassJob.GetClassJobIndex()]; - var canUseManipulation = ActionManager.CanUseActionOnTarget(ActionType.Manipulation.GetId(recipeClassJob), (GameObject*)Service.ClientState.LocalPlayer.Address); + DrawGearsets(); + } + + void DrawCraftInfo() + { + DrawRecipeInfo(); + DrawCharacterInfo(); + + DrawCraftActions(); + } + + void DrawRecipeInfo() + { + var s = new StringBuilder(); + s.AppendLine($"{RecipeClassJob.GetName()} {new string('★', RecipeTable.Stars)}"); + s.AppendLine($"Level {RecipeTable.ClassJobLevel} (RLvl {RecipeInfo.RLvl})"); + s.AppendLine($"Durability: {RecipeInfo.MaxDurability}"); + s.AppendLine($"Progress: {RecipeInfo.MaxProgress}"); + s.AppendLine($"Quality: {RecipeInfo.MaxQuality}"); + s.AppendLine($"Starting Quality: {startingQuality}"); + ImGui.Text(s.ToString()); + } + + void DrawCharacterInfo() + { + var classJob = (byte)Service.ClientState.LocalPlayer!.ClassJob.Id; + + if (!ClassJobUtils.IsClassJob(classJob, RecipeClassJob)) + { + ImGui.Text("Your current class cannot craft this recipe."); + return; + } + + var container = InventoryManager.Instance()->GetInventoryContainer(InventoryType.EquippedItems); + if (container == null) + return; + + var stats = Gearsets.CalculateCharacterStats(container, RecipeCharacterLevel, RecipeCanUseManipulation); + + var s = new StringBuilder(); + s.AppendLine($"{RecipeClassJob.GetName()}"); + s.AppendLine($"Level {stats.Level} (CLvl {stats.CLvl})"); + s.AppendLine($"Craftsmanship {stats.Craftsmanship}"); + s.AppendLine($"Control {stats.Control}"); + s.AppendLine($"CP {stats.CP}"); + if (stats.IsSpecialist) + s.AppendLine($" + Specialist"); + if (stats.HasSplendorousBuff) + s.AppendLine($" + Splendorous"); + ImGui.Text(s.ToString()); + } + + void DrawCraftActions() + { + ImGui.Button("Open Simulator"); + ImGui.Button("Generate a new macro"); + } + + void DrawGearsets() + { + ImGui.Text("Available Gearsets"); + + var inst = RaptureGearsetModule.Instance(); for (var i = 0; i < 100; i++) { @@ -61,33 +128,34 @@ public unsafe class CraftingLog : Window if (!gearset->Flags.HasFlag(RaptureGearsetModule.GearsetFlag.Exists)) continue; - if (!ClassJobUtils.IsClassJob(gearset->ClassJob, recipeClassJob)) + if (!ClassJobUtils.IsClassJob(gearset->ClassJob, RecipeClassJob)) continue; - var stats = Gearsets.CalculateCharacterStats(gearset, characterLevel, canUseManipulation); - ImGui.Text($"Gearset: {gearset->ID + 1} {Marshal.PtrToStringUTF8((nint)gearset->Name)}"); + var stats = Gearsets.CalculateCharacterStats(gearset, RecipeCharacterLevel, RecipeCanUseManipulation); + var gearsetId = gearset->ID + 1; + + var s = new StringBuilder(); + s.AppendLine($"{SafeMemory.ReadString((nint)gearset->Name, 47)} ({gearsetId})"); + s.AppendLine($"Level {stats.Level} (CLvl {stats.CLvl})"); + s.AppendLine($"Craftsmanship {stats.Craftsmanship}"); + s.AppendLine($"Control {stats.Control}"); + s.AppendLine($"CP {stats.CP}"); + if (stats.IsSpecialist) + s.AppendLine($" + Specialist"); + if (stats.HasSplendorousBuff) + s.AppendLine($" + Splendorous"); + ImGui.Text(s.ToString()); ImGui.SameLine(); - if (ImGuiComponents.IconButton($"SwapGearset{gearset->ID}", FontAwesomeIcon.SyncAlt)) - Chat.SendMessage($"/gearset change {gearset->ID + 1}"); + if (ImGuiComponents.IconButton($"SwapGearset{gearsetId}", FontAwesomeIcon.SyncAlt)) + Chat.SendMessage($"/gearset change {gearsetId}"); if (ImGui.IsItemHovered()) - ImGui.SetTooltip($"Swap to gearset {gearset->ID + 1}"); - ImGui.Text($"{stats}"); + ImGui.SetTooltip($"Swap to gearset {gearsetId}"); } + } - { - var classJob = (byte)Service.ClientState.LocalPlayer.ClassJob.Id; - - if (!ClassJobUtils.IsClassJob(classJob, recipeClassJob)) - return; - - var container = InventoryManager.Instance()->GetInventoryContainer(InventoryType.EquippedItems); - if (container == null) - return; - - var stats = Gearsets.CalculateCharacterStats(container, characterLevel, canUseManipulation); - ImGui.Text($"Currently Equipped"); - ImGui.Text($"{stats}"); - } + void OnNewRecipe() + { + startingQuality = 0; } public override bool DrawConditions() @@ -112,16 +180,19 @@ public unsafe class CraftingLog : Window if (recipeEntry == null) return false; - SelectedRecipeId = recipeEntry->RecipeId; + if (RecipeId != recipeEntry->RecipeId) + OnNewRecipe(); - var recipe = LuminaSheets.RecipeSheet.GetRow(SelectedRecipeId); + RecipeId = recipeEntry->RecipeId; + + var recipe = LuminaSheets.RecipeSheet.GetRow(RecipeId); if (recipe == null) return false; - SelectedRecipe = recipe; + Recipe = recipe; - SelectedRecipeInfo = SimulatorWindow.CreateRecipeInfo(SelectedRecipe); + RecipeInfo = SimulatorWindow.CreateRecipeInfo(Recipe); if (!Addon->Unk258->IsVisible) return false;