Read ingredient HQ counts from RecipeNote

This commit is contained in:
Asriel Camora
2024-07-31 13:06:16 -07:00
parent 7c32ff74b1
commit d0f0d79116
5 changed files with 57 additions and 16 deletions
+3 -3
View File
@@ -104,13 +104,13 @@ public sealed class Plugin : IDalamudPlugin
public void OpenEmptyMacroEditor() public void OpenEmptyMacroEditor()
{ {
var stats = GetDefaultStats(); var stats = GetDefaultStats();
OpenMacroEditor(stats.Character, stats.Recipe, stats.Buffs, [], null); OpenMacroEditor(stats.Character, stats.Recipe, stats.Buffs, null, [], null);
} }
public void OpenMacroEditor(CharacterStats characterStats, RecipeData recipeData, MacroEditor.CrafterBuffs buffs, IEnumerable<ActionType> actions, Action<IEnumerable<ActionType>>? setter) public void OpenMacroEditor(CharacterStats characterStats, RecipeData recipeData, MacroEditor.CrafterBuffs buffs, IEnumerable<int>? ingredientHqCounts, IEnumerable<ActionType> actions, Action<IEnumerable<ActionType>>? setter)
{ {
EditorWindow?.Dispose(); EditorWindow?.Dispose();
EditorWindow = new(characterStats, recipeData, buffs, actions, setter); EditorWindow = new(characterStats, recipeData, buffs, ingredientHqCounts, actions, setter);
} }
[Command(name: "/craftaction", description: "Execute the suggested action in the synthesis helper. Can also be run inside a macro. This command is useful for controller players.")] [Command(name: "/craftaction", description: "Execute the suggested action in the synthesis helper. Can also be run inside a macro. This command is useful for controller players.")]
+2 -2
View File
@@ -108,7 +108,7 @@ public sealed class MacroEditor : Window, IDisposable
private CancellationTokenSource? popupImportUrlTokenSource; private CancellationTokenSource? popupImportUrlTokenSource;
private CommunityMacros.CommunityMacro? popupImportUrlMacro; private CommunityMacros.CommunityMacro? popupImportUrlMacro;
public MacroEditor(CharacterStats characterStats, RecipeData recipeData, CrafterBuffs buffs, IEnumerable<ActionType> actions, Action<IEnumerable<ActionType>>? setter) : base("Craftimizer Macro Editor", WindowFlags) public MacroEditor(CharacterStats characterStats, RecipeData recipeData, CrafterBuffs buffs, IEnumerable<int>? ingredientHqCounts, IEnumerable<ActionType> actions, Action<IEnumerable<ActionType>>? setter) : base("Craftimizer Macro Editor", WindowFlags)
{ {
CharacterStats = characterStats; CharacterStats = characterStats;
RecipeData = recipeData; RecipeData = recipeData;
@@ -116,7 +116,7 @@ public sealed class MacroEditor : Window, IDisposable
MacroSetter = setter; MacroSetter = setter;
DefaultActions = actions.ToArray(); DefaultActions = actions.ToArray();
HQIngredientCounts = [.. Enumerable.Repeat(0, RecipeData.Ingredients.Count)]; HQIngredientCounts = [.. ingredientHqCounts ?? Enumerable.Repeat(0, RecipeData.Ingredients.Count)];
RecalculateState(); RecalculateState();
foreach (var action in DefaultActions) foreach (var action in DefaultActions)
+1 -1
View File
@@ -352,7 +352,7 @@ public sealed class MacroList : Window, IDisposable
private void OpenEditor(Macro? macro) private void OpenEditor(Macro? macro)
{ {
var stats = Service.Plugin.GetDefaultStats(); var stats = Service.Plugin.GetDefaultStats();
Service.Plugin.OpenMacroEditor(stats.Character, stats.Recipe, stats.Buffs, macro?.Actions ?? Enumerable.Empty<ActionType>(), macro != null ? (actions => { macro.ActionEnumerable = actions; Service.Configuration.Save(); }) : null); Service.Plugin.OpenMacroEditor(stats.Character, stats.Recipe, stats.Buffs, null, macro?.Actions ?? Enumerable.Empty<ActionType>(), macro != null ? (actions => { macro.ActionEnumerable = actions; Service.Configuration.Save(); }) : null);
} }
private void OnMacroChanged(Macro macro) private void OnMacroChanged(Macro macro)
+50 -9
View File
@@ -16,6 +16,7 @@ using Dalamud.Interface.Windowing;
using Dalamud.Utility; using Dalamud.Utility;
using FFXIVClientStructs.FFXIV.Client.Game; using FFXIVClientStructs.FFXIV.Client.Game;
using FFXIVClientStructs.FFXIV.Client.Game.UI; using FFXIVClientStructs.FFXIV.Client.Game.UI;
using FFXIVClientStructs.FFXIV.Client.System.String;
using FFXIVClientStructs.FFXIV.Client.UI; using FFXIVClientStructs.FFXIV.Client.UI;
using FFXIVClientStructs.FFXIV.Client.UI.Misc; using FFXIVClientStructs.FFXIV.Client.UI.Misc;
using ImGuiNET; using ImGuiNET;
@@ -23,8 +24,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Numerics; using System.Numerics;
using System.Threading; using System.Runtime.InteropServices;
using System.Threading.Tasks;
using ActionType = Craftimizer.Simulator.Actions.ActionType; using ActionType = Craftimizer.Simulator.Actions.ActionType;
using ClassJob = Craftimizer.Simulator.ClassJob; using ClassJob = Craftimizer.Simulator.ClassJob;
using CSRecipeNote = FFXIVClientStructs.FFXIV.Client.Game.UI.RecipeNote; using CSRecipeNote = FFXIVClientStructs.FFXIV.Client.Game.UI.RecipeNote;
@@ -58,6 +58,7 @@ public sealed unsafe class RecipeNote : Window, IDisposable
public AddonRecipeNote* Addon { get; private set; } public AddonRecipeNote* Addon { get; private set; }
public RecipeData? RecipeData { get; private set; } public RecipeData? RecipeData { get; private set; }
public CharacterStats? CharacterStats { get; private set; } public CharacterStats? CharacterStats { get; private set; }
private int StartingQuality { get; set; }
public CraftableStatus CraftStatus { get; private set; } public CraftableStatus CraftStatus { get; private set; }
private BackgroundTask<(Macro?, SimulationState?)>? SavedMacroTask { get; set; } private BackgroundTask<(Macro?, SimulationState?)>? SavedMacroTask { get; set; }
@@ -238,7 +239,12 @@ public sealed unsafe class RecipeNote : Window, IDisposable
StatsChanged = true; StatsChanged = true;
} }
if (StatsChanged && CraftStatus == CraftableStatus.OK) var startingQuality = RecipeData.CalculateStartingQuality(CalculateIngredientHqCounts());
var qualityChanged = startingQuality != StartingQuality;
if (qualityChanged)
StartingQuality = startingQuality;
if ((StatsChanged || qualityChanged) && CraftStatus == CraftableStatus.OK)
{ {
// Stats changed and we are still craftable, so we need to recalculate // Stats changed and we are still craftable, so we need to recalculate
CalculateSavedMacro(); CalculateSavedMacro();
@@ -267,6 +273,41 @@ public sealed unsafe class RecipeNote : Window, IDisposable
return true; return true;
} }
[StructLayout(LayoutKind.Explicit, Size = 136)]
public struct RecipeIngredient2
{
[FieldOffset(8)]
public byte NQCount;
[FieldOffset(9)]
public byte HQCount;
[FieldOffset(16)]
public Utf8String Name;
[FieldOffset(120)]
public uint ItemId;
[FieldOffset(124)]
public uint IconId;
[FieldOffset(130)]
public byte Amount;
[FieldOffset(131)]
public byte Flags;
}
private IEnumerable<int> CalculateIngredientHqCounts()
{
if (RecipeData == null)
throw new InvalidOperationException("RecipeData must not be null");
var ingredientCount = RecipeData.Ingredients.Count;
var ingredientSpan = MemoryMarshal.Cast<CSRecipeNote.RecipeIngredient, RecipeIngredient2>(CSRecipeNote.Instance()->RecipeList->SelectedRecipe->Ingredients);
return ingredientSpan.ToArray().Take(ingredientCount).Select(i => (int)i.HQCount);
}
private Vector2? LastPosition { get; set; } private Vector2? LastPosition { get; set; }
private byte? StyleAlpha { get; set; } private byte? StyleAlpha { get; set; }
private byte? LastAlpha { get; set; } private byte? LastAlpha { get; set; }
@@ -403,7 +444,7 @@ public sealed unsafe class RecipeNote : Window, IDisposable
Service.Plugin.OpenMacroListWindow(); Service.Plugin.OpenMacroListWindow();
if (ImGui.Button("Open in Macro Editor", new(availWidth, 0))) if (ImGui.Button("Open in Macro Editor", new(availWidth, 0)))
Service.Plugin.OpenMacroEditor(CharacterStats!, RecipeData!, new(Service.ClientState.LocalPlayer!.StatusList), [], null); Service.Plugin.OpenMacroEditor(CharacterStats!, RecipeData!, new(Service.ClientState.LocalPlayer!.StatusList), CalculateIngredientHqCounts(), [], null);
} }
private void DrawCharacterStats() private void DrawCharacterStats()
@@ -947,7 +988,7 @@ public sealed unsafe class RecipeNote : Window, IDisposable
ImGui.TableNextColumn(); ImGui.TableNextColumn();
{ {
if (ImGuiUtils.IconButtonSquare(FontAwesomeIcon.Edit, miniRowHeight)) if (ImGuiUtils.IconButtonSquare(FontAwesomeIcon.Edit, miniRowHeight))
Service.Plugin.OpenMacroEditor(CharacterStats!, RecipeData!, new(Service.ClientState.LocalPlayer!.StatusList), actions, state.MacroEditorSetter); Service.Plugin.OpenMacroEditor(CharacterStats!, RecipeData!, new(Service.ClientState.LocalPlayer!.StatusList), CalculateIngredientHqCounts(), actions, state.MacroEditorSetter);
if (ImGui.IsItemHovered()) if (ImGui.IsItemHovered())
ImGuiUtils.Tooltip("Open in Macro Editor"); ImGuiUtils.Tooltip("Open in Macro Editor");
if (ImGuiUtils.IconButtonSquare(FontAwesomeIcon.Paste, miniRowHeight)) if (ImGuiUtils.IconButtonSquare(FontAwesomeIcon.Paste, miniRowHeight))
@@ -1028,7 +1069,7 @@ public sealed unsafe class RecipeNote : Window, IDisposable
if (PlayerState.Instance()->CurrentClassJobId != RecipeData.ClassJob.GetClassJobIndex()) if (PlayerState.Instance()->CurrentClassJobId != RecipeData.ClassJob.GetClassJobIndex())
return CraftableStatus.WrongClassJob; return CraftableStatus.WrongClassJob;
if (RecipeData.Recipe.IsSpecializationRequired && !(CharacterStats!.IsSpecialist)) if (RecipeData.Recipe.IsSpecializationRequired && !CharacterStats!.IsSpecialist)
return CraftableStatus.SpecialistRequired; return CraftableStatus.SpecialistRequired;
var itemRequired = RecipeData.Recipe.ItemRequired; var itemRequired = RecipeData.Recipe.ItemRequired;
@@ -1101,7 +1142,7 @@ public sealed unsafe class RecipeNote : Window, IDisposable
SavedMacroTask?.Cancel(); SavedMacroTask?.Cancel();
SavedMacroTask = new(token => SavedMacroTask = new(token =>
{ {
var input = new SimulationInput(CharacterStats!, RecipeData!.RecipeInfo); var input = new SimulationInput(CharacterStats!, RecipeData!.RecipeInfo, StartingQuality);
var state = new SimulationState(input); var state = new SimulationState(input);
var config = Service.Configuration.RecipeNoteSolverConfig; var config = Service.Configuration.RecipeNoteSolverConfig;
var mctsConfig = new MCTSConfig(config); var mctsConfig = new MCTSConfig(config);
@@ -1132,7 +1173,7 @@ public sealed unsafe class RecipeNote : Window, IDisposable
SuggestedMacroTask?.Cancel(); SuggestedMacroTask?.Cancel();
SuggestedMacroTask = new(token => SuggestedMacroTask = new(token =>
{ {
var input = new SimulationInput(CharacterStats!, RecipeData!.RecipeInfo); var input = new SimulationInput(CharacterStats!, RecipeData!.RecipeInfo, StartingQuality);
var state = new SimulationState(input); var state = new SimulationState(input);
var config = Service.Configuration.RecipeNoteSolverConfig; var config = Service.Configuration.RecipeNoteSolverConfig;
@@ -1156,7 +1197,7 @@ public sealed unsafe class RecipeNote : Window, IDisposable
CommunityMacroTask?.Cancel(); CommunityMacroTask?.Cancel();
CommunityMacroTask = new(token => CommunityMacroTask = new(token =>
{ {
var input = new SimulationInput(CharacterStats!, RecipeData!.RecipeInfo); var input = new SimulationInput(CharacterStats!, RecipeData!.RecipeInfo, StartingQuality);
var state = new SimulationState(input); var state = new SimulationState(input);
var config = Service.Configuration.RecipeNoteSolverConfig; var config = Service.Configuration.RecipeNoteSolverConfig;
var mctsConfig = new MCTSConfig(config); var mctsConfig = new MCTSConfig(config);
+1 -1
View File
@@ -459,7 +459,7 @@ public sealed unsafe class SynthHelper : Window, IDisposable
} }
if (ImGui.Button("Open in Macro Editor", new(-1, 0))) if (ImGui.Button("Open in Macro Editor", new(-1, 0)))
Service.Plugin.OpenMacroEditor(CharacterStats!, RecipeData!, new(Service.ClientState.LocalPlayer!.StatusList), [], null); Service.Plugin.OpenMacroEditor(CharacterStats!, RecipeData!, new(Service.ClientState.LocalPlayer!.StatusList), null, [], null);
} }
public bool ExecuteNextAction() public bool ExecuteNextAction()