Read ingredient HQ counts from RecipeNote
This commit is contained in:
@@ -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.")]
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
Reference in New Issue
Block a user