Refactor ui code, add temp synth window
This commit is contained in:
@@ -1,7 +1,5 @@
|
||||
using Craftimizer.Plugin.Windows;
|
||||
using Craftimizer.Simulator;
|
||||
using Craftimizer.Simulator.Actions;
|
||||
using Dalamud.Game.Command;
|
||||
using Dalamud.Interface.Windowing;
|
||||
using Dalamud.IoC;
|
||||
using Dalamud.Plugin;
|
||||
@@ -15,9 +13,10 @@ public sealed class Plugin : IDalamudPlugin
|
||||
public string Name => "Craftimizer";
|
||||
|
||||
public WindowSystem WindowSystem { get; }
|
||||
public SettingsWindow SettingsWindow { get; }
|
||||
public Settings SettingsWindow { get; }
|
||||
public CraftingLog RecipeNoteWindow { get; }
|
||||
public SimulatorWindow? SimulatorWindow { get; set; }
|
||||
public Craft SynthesisWindow { get; }
|
||||
public Windows.Simulator? SimulatorWindow { get; set; }
|
||||
|
||||
public Plugin([RequiredVersion("1.0")] DalamudPluginInterface pluginInterface)
|
||||
{
|
||||
@@ -27,8 +26,9 @@ public sealed class Plugin : IDalamudPlugin
|
||||
|
||||
WindowSystem = new(Name);
|
||||
|
||||
RecipeNoteWindow = new();
|
||||
SettingsWindow = new();
|
||||
RecipeNoteWindow = new();
|
||||
SynthesisWindow = new();
|
||||
|
||||
Service.PluginInterface.UiBuilder.Draw += WindowSystem.Draw;
|
||||
Service.PluginInterface.UiBuilder.OpenConfigUi += OpenSettingsWindow;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Craftimizer.Simulator;
|
||||
using Dalamud.Utility;
|
||||
using FFXIVClientStructs.FFXIV.Client.Game;
|
||||
using FFXIVClientStructs.FFXIV.Client.Game.UI;
|
||||
using FFXIVClientStructs.FFXIV.Client.UI.Misc;
|
||||
using Lumina.Excel.GeneratedSheets;
|
||||
using System;
|
||||
@@ -83,21 +84,33 @@ internal static unsafe class Gearsets
|
||||
public static GearsetStats CalculateGearsetStats(GearsetItem[] gearsetItems) =>
|
||||
gearsetItems.Select(CalculateGearsetItemStats).Aggregate(BaseStats, (a, b) => new(a.CP + b.CP, a.Craftsmanship + b.Craftsmanship, a.Control + b.Control));
|
||||
|
||||
public static CharacterStats CalculateCharacterStats(GearsetItem[] gearsetItems, int characterLevel, bool canUseManipulation)
|
||||
public static GearsetStats CalculateGearsetCurrentStats()
|
||||
{
|
||||
var stats = CalculateGearsetStats(gearsetItems);
|
||||
return new CharacterStats
|
||||
var attributes = UIState.Instance()->PlayerState.Attributes;
|
||||
|
||||
return new()
|
||||
{
|
||||
CP = stats.CP,
|
||||
Craftsmanship = stats.Craftsmanship,
|
||||
Control = stats.Control,
|
||||
CP = attributes[ParamCP],
|
||||
Craftsmanship = attributes[ParamCraftsmanship],
|
||||
Control = attributes[ParamControl],
|
||||
};
|
||||
}
|
||||
|
||||
public static CharacterStats CalculateCharacterStats(GearsetItem[] gearsetItems, int characterLevel, bool canUseManipulation) =>
|
||||
CalculateCharacterStats(CalculateGearsetStats(gearsetItems), gearsetItems, characterLevel, canUseManipulation);
|
||||
|
||||
public static CharacterStats CalculateCharacterStats(GearsetStats gearsetStats, GearsetItem[] gearsetItems, int characterLevel, bool canUseManipulation) =>
|
||||
new()
|
||||
{
|
||||
CP = gearsetStats.CP,
|
||||
Craftsmanship = gearsetStats.Craftsmanship,
|
||||
Control = gearsetStats.Control,
|
||||
Level = characterLevel,
|
||||
CanUseManipulation = canUseManipulation,
|
||||
HasSplendorousBuff = gearsetItems.Any(IsSplendorousTool),
|
||||
IsSpecialist = gearsetItems.Any(IsSpecialistSoulCrystal),
|
||||
CLvl = CalculateCLvl(characterLevel),
|
||||
};
|
||||
}
|
||||
|
||||
public static bool IsItem(GearsetItem item, uint itemId) =>
|
||||
item.itemId == itemId;
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
using Craftimizer.Plugin;
|
||||
using Craftimizer.Simulator;
|
||||
using FFXIVClientStructs.FFXIV.Client.Game.UI;
|
||||
using FFXIVClientStructs.FFXIV.Client.Game;
|
||||
using FFXIVClientStructs.FFXIV.Client.UI;
|
||||
using Lumina.Excel.GeneratedSheets;
|
||||
using System.Linq;
|
||||
using System;
|
||||
using ClassJob = Craftimizer.Simulator.ClassJob;
|
||||
using CSRecipeNote = FFXIVClientStructs.FFXIV.Client.Game.UI.RecipeNote;
|
||||
using ActionType = Craftimizer.Simulator.Actions.ActionType;
|
||||
using FFXIVClientStructs.FFXIV.Client.Game.Object;
|
||||
|
||||
namespace Craftimizer.Utils;
|
||||
|
||||
public unsafe class RecipeNote
|
||||
{
|
||||
public AddonRecipeNote* AddonRecipe { get; private set; }
|
||||
public AddonSynthesis* AddonSynthesis { get; private set; }
|
||||
public CSRecipeNote* State { get; private set; }
|
||||
public ushort RecipeId { get; private set; }
|
||||
public Recipe Recipe { get; private set; } = null!;
|
||||
|
||||
public RecipeLevelTable Table { get; private set; } = null!;
|
||||
public RecipeInfo Info { get; private set; } = null!;
|
||||
public ClassJob ClassJob { get; private set; }
|
||||
public short CharacterLevel { get; private set; }
|
||||
public bool CanUseManipulation { get; private set; }
|
||||
public int HQIngredientCount { get; private set; }
|
||||
public int MaxStartingQuality { get; private set; }
|
||||
|
||||
public RecipeNote()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public bool Update(out bool isNewRecipe)
|
||||
{
|
||||
isNewRecipe = false;
|
||||
|
||||
if (Service.ClientState.LocalPlayer == null)
|
||||
return false;
|
||||
|
||||
AddonRecipe = (AddonRecipeNote*)Service.GameGui.GetAddonByName("RecipeNote");
|
||||
AddonSynthesis = (AddonSynthesis*)Service.GameGui.GetAddonByName("Synthesis");
|
||||
|
||||
if (AddonRecipe == null)
|
||||
return false;
|
||||
if (AddonSynthesis == null)
|
||||
return false;
|
||||
|
||||
State = CSRecipeNote.Instance();
|
||||
|
||||
var list = State->RecipeList;
|
||||
|
||||
if (list == null)
|
||||
return false;
|
||||
|
||||
var recipeEntry = list->SelectedRecipe;
|
||||
|
||||
if (recipeEntry == null)
|
||||
return false;
|
||||
|
||||
isNewRecipe = RecipeId != recipeEntry->RecipeId;
|
||||
|
||||
RecipeId = recipeEntry->RecipeId;
|
||||
|
||||
var recipe = LuminaSheets.RecipeSheet.GetRow(RecipeId);
|
||||
|
||||
if (recipe == null)
|
||||
return false;
|
||||
|
||||
Recipe = recipe;
|
||||
|
||||
if (isNewRecipe)
|
||||
CalculateStats();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void CalculateStats()
|
||||
{
|
||||
Table = Recipe.RecipeLevelTable.Value!;
|
||||
Info = CreateInfo();
|
||||
ClassJob = (ClassJob)Recipe.CraftType.Row;
|
||||
CharacterLevel = PlayerState.Instance()->ClassJobLevelArray[ClassJob.GetClassJobIndex()];
|
||||
CanUseManipulation = ActionManager.CanUseActionOnTarget(ActionType.Manipulation.GetId(ClassJob), (GameObject*)Service.ClientState.LocalPlayer!.Address);
|
||||
HQIngredientCount = Recipe.UnkData5
|
||||
.Where(i =>
|
||||
i != null &&
|
||||
i.ItemIngredient != 0 &&
|
||||
(LuminaSheets.ItemSheet.GetRow((uint)i.ItemIngredient)?.CanBeHq ?? false)
|
||||
).Sum(i => i.AmountIngredient);
|
||||
MaxStartingQuality = (int)Math.Floor(Recipe.MaterialQualityFactor * Info.MaxQuality / 100f);
|
||||
}
|
||||
|
||||
private RecipeInfo CreateInfo() =>
|
||||
new()
|
||||
{
|
||||
IsExpert = Recipe.IsExpert,
|
||||
ClassJobLevel = Table.ClassJobLevel,
|
||||
RLvl = (int)Table.RowId,
|
||||
ConditionsFlag = Table.ConditionsFlag,
|
||||
MaxDurability = Table.Durability * Recipe.DurabilityFactor / 100,
|
||||
MaxQuality = (int)Table.Quality * Recipe.QualityFactor / 100,
|
||||
MaxProgress = Table.Difficulty * Recipe.DifficultyFactor / 100,
|
||||
QualityModifier = Table.QualityModifier,
|
||||
QualityDivider = Table.QualityDivider,
|
||||
ProgressModifier = Table.ProgressModifier,
|
||||
ProgressDivider = Table.ProgressDivider,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
using Craftimizer.Plugin.Utils;
|
||||
using Craftimizer.Simulator;
|
||||
using Craftimizer.Utils;
|
||||
using Dalamud.Interface.Windowing;
|
||||
using FFXIVClientStructs.FFXIV.Client.Game;
|
||||
using ImGuiNET;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Craftimizer.Plugin.Windows;
|
||||
|
||||
public unsafe class Craft : Window
|
||||
{
|
||||
private const ImGuiWindowFlags WindowFlags = ImGuiWindowFlags.NoDecoration
|
||||
| ImGuiWindowFlags.AlwaysAutoResize
|
||||
| ImGuiWindowFlags.NoSavedSettings
|
||||
| ImGuiWindowFlags.NoFocusOnAppearing
|
||||
| ImGuiWindowFlags.NoNavFocus;
|
||||
|
||||
private RecipeNote RecipeUtils { get; } = new();
|
||||
|
||||
private bool WasOpen { get; set; }
|
||||
|
||||
private CharacterStats CharacterStats { get; set; } = null!;
|
||||
|
||||
public Craft() : base("Craftimizer SynthesisHelper", WindowFlags, true)
|
||||
{
|
||||
Service.WindowSystem.AddWindow(this);
|
||||
|
||||
IsOpen = true;
|
||||
}
|
||||
|
||||
public override void Draw()
|
||||
{
|
||||
ImGui.Text($"{CharacterStats.CP};{CharacterStats.Control};{CharacterStats.Craftsmanship}");
|
||||
}
|
||||
|
||||
public override void PreDraw()
|
||||
{
|
||||
var addon = RecipeUtils.AddonSynthesis;
|
||||
ref var unit = ref addon->AtkUnitBase;
|
||||
var scale = unit.Scale;
|
||||
var pos = new Vector2(unit.X, unit.Y);
|
||||
var size = new Vector2(unit.WindowNode->AtkResNode.Width, unit.WindowNode->AtkResNode.Height) * scale;
|
||||
|
||||
var node = unit.GetNodeById(5);
|
||||
|
||||
Position = pos + new Vector2(size.X, node->Y * scale);
|
||||
SizeConstraints = new WindowSizeConstraints
|
||||
{
|
||||
MinimumSize = new(-1),
|
||||
MaximumSize = new(10000, 10000)
|
||||
};
|
||||
|
||||
base.PreDraw();
|
||||
}
|
||||
|
||||
private bool DrawConditionsInner()
|
||||
{
|
||||
if (!RecipeUtils.Update(out _))
|
||||
return false;
|
||||
|
||||
// Check if Synthesis addon is visible
|
||||
if (RecipeUtils.AddonSynthesis->AtkUnitBase.WindowNode == null)
|
||||
return false;
|
||||
|
||||
return base.DrawConditions();
|
||||
}
|
||||
|
||||
public override bool DrawConditions()
|
||||
{
|
||||
var ret = DrawConditionsInner();
|
||||
if (ret && !WasOpen)
|
||||
ResetSimulation();
|
||||
|
||||
WasOpen = ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
private void ResetSimulation()
|
||||
{
|
||||
var container = InventoryManager.Instance()->GetInventoryContainer(InventoryType.EquippedItems);
|
||||
if (container == null)
|
||||
return;
|
||||
|
||||
CharacterStats = Gearsets.CalculateCharacterStats(Gearsets.CalculateGearsetCurrentStats(), Gearsets.GetGearsetItems(container), RecipeUtils.CharacterLevel, RecipeUtils.CanUseManipulation);
|
||||
}
|
||||
}
|
||||
@@ -7,22 +7,18 @@ using Dalamud.Interface.Components;
|
||||
using Dalamud.Interface.Windowing;
|
||||
using Dalamud.Utility;
|
||||
using FFXIVClientStructs.FFXIV.Client.Game;
|
||||
using FFXIVClientStructs.FFXIV.Client.Game.Object;
|
||||
using FFXIVClientStructs.FFXIV.Client.Game.UI;
|
||||
using FFXIVClientStructs.FFXIV.Client.UI;
|
||||
using FFXIVClientStructs.FFXIV.Client.UI.Misc;
|
||||
using FFXIVClientStructs.FFXIV.Component.GUI;
|
||||
using ImGuiNET;
|
||||
using Lumina.Excel.GeneratedSheets;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using ActionType = Craftimizer.Simulator.Actions.ActionType;
|
||||
using ClassJob = Craftimizer.Simulator.ClassJob;
|
||||
using RecipeNote = Craftimizer.Utils.RecipeNote;
|
||||
|
||||
namespace Craftimizer.Plugin.Windows;
|
||||
|
||||
@@ -46,20 +42,7 @@ public unsafe class CraftingLog : Window
|
||||
private static Food[] MedicineItems { get; }
|
||||
private static Random Random { get; }
|
||||
|
||||
// Set in DrawConditions
|
||||
private AddonRecipeNote* Addon { get; set; }
|
||||
private RecipeNote* State { get; set; }
|
||||
private ushort RecipeId { get; set; }
|
||||
private Recipe Recipe { get; set; } = null!;
|
||||
|
||||
// Set in CalculateRecipeStats (in DrawConditions)
|
||||
private RecipeLevelTable RecipeTable { get; set; } = null!;
|
||||
private RecipeInfo RecipeInfo { get; set; } = null!;
|
||||
private ClassJob RecipeClassJob { get; set; }
|
||||
private short RecipeCharacterLevel { get; set; }
|
||||
private bool RecipeCanUseManipulation { get; set; }
|
||||
private int RecipeHQIngredientCount { get; set; }
|
||||
private int RecipeMaxStartingQuality { get; set; }
|
||||
private RecipeNote RecipeUtils { get; } = new();
|
||||
|
||||
// Set in CalculateCharacterStats (in PreDraw)
|
||||
private Gearsets.GearsetItem[] CharacterEquipment { get; set; } = null!;
|
||||
@@ -71,7 +54,10 @@ public unsafe class CraftingLog : Window
|
||||
|
||||
// Set in UI
|
||||
private int QualityNotches { get; set; }
|
||||
private int StartingQuality => RecipeHQIngredientCount == 0 ? 0 : (int)((float)QualityNotches * RecipeMaxStartingQuality / RecipeHQIngredientCount);
|
||||
private int StartingQuality =>
|
||||
RecipeUtils.HQIngredientCount == 0 ?
|
||||
0 :
|
||||
(int)((float)QualityNotches * RecipeUtils.MaxStartingQuality / RecipeUtils.HQIngredientCount);
|
||||
|
||||
private Food? SelectedFood { get; set; }
|
||||
private bool SelectedFoodHQ { get; set; }
|
||||
@@ -139,22 +125,6 @@ public unsafe class CraftingLog : Window
|
||||
IsOpen = true;
|
||||
}
|
||||
|
||||
private void CalculateRecipeStats()
|
||||
{
|
||||
RecipeTable = Recipe.RecipeLevelTable.Value!;
|
||||
RecipeInfo = CreateRecipeInfo(Recipe);
|
||||
RecipeClassJob = (ClassJob)Recipe.CraftType.Row;
|
||||
RecipeCharacterLevel = PlayerState.Instance()->ClassJobLevelArray[RecipeClassJob.GetClassJobIndex()];
|
||||
RecipeCanUseManipulation = ActionManager.CanUseActionOnTarget(ActionType.Manipulation.GetId(RecipeClassJob), (GameObject*)Service.ClientState.LocalPlayer!.Address);
|
||||
RecipeHQIngredientCount = Recipe.UnkData5
|
||||
.Where(i =>
|
||||
i != null &&
|
||||
i.ItemIngredient != 0 &&
|
||||
(LuminaSheets.ItemSheet.GetRow((uint)i.ItemIngredient)?.CanBeHq ?? false)
|
||||
).Sum(i => i.AmountIngredient);
|
||||
RecipeMaxStartingQuality = (int)Math.Floor(Recipe.MaterialQualityFactor * RecipeInfo.MaxQuality / 100f);
|
||||
}
|
||||
|
||||
private void CalculateCharacterStats()
|
||||
{
|
||||
var container = InventoryManager.Instance()->GetInventoryContainer(InventoryType.EquippedItems);
|
||||
@@ -162,7 +132,7 @@ public unsafe class CraftingLog : Window
|
||||
return;
|
||||
|
||||
CharacterEquipment = Gearsets.GetGearsetItems(container);
|
||||
CharacterStatsNoConsumable = Gearsets.CalculateCharacterStats(CharacterEquipment, RecipeCharacterLevel, RecipeCanUseManipulation);
|
||||
CharacterStatsNoConsumable = Gearsets.CalculateCharacterStats(CharacterEquipment, RecipeUtils.CharacterLevel, RecipeUtils.CanUseManipulation);
|
||||
CharacterConsumableBonus = CalculateConsumableBonus(CharacterStatsNoConsumable);
|
||||
CharacterStatsConsumable = CharacterStatsNoConsumable with
|
||||
{
|
||||
@@ -173,7 +143,7 @@ public unsafe class CraftingLog : Window
|
||||
CharacterCannotCraftReason = Service.Configuration.OverrideUncraftability ? CannotCraftReason.OK : CanCraftRecipe(CharacterEquipment, CharacterStatsConsumable);
|
||||
|
||||
if (CharacterCannotCraftReason == CannotCraftReason.OK)
|
||||
CharacterSimulationInput = new(CharacterStatsConsumable, RecipeInfo, StartingQuality, Random);
|
||||
CharacterSimulationInput = new(CharacterStatsConsumable, RecipeUtils.Info, StartingQuality, Random);
|
||||
}
|
||||
|
||||
public override void Draw()
|
||||
@@ -210,11 +180,11 @@ public unsafe class CraftingLog : Window
|
||||
private 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($"{RecipeUtils.ClassJob.GetName()} {new string('★', RecipeUtils.Table.Stars)}");
|
||||
s.AppendLine($"Level {RecipeUtils.Table.ClassJobLevel} (RLvl {RecipeUtils.Info.RLvl})");
|
||||
s.AppendLine($"Durability: {RecipeUtils.Info.MaxDurability}");
|
||||
s.AppendLine($"Progress: {RecipeUtils.Info.MaxProgress}");
|
||||
s.AppendLine($"Quality: {RecipeUtils.Info.MaxQuality}");
|
||||
ImGui.Text(s.ToString());
|
||||
}
|
||||
|
||||
@@ -231,10 +201,10 @@ public unsafe class CraftingLog : Window
|
||||
|
||||
private void DrawCraftParameters()
|
||||
{
|
||||
ImGui.BeginDisabled(RecipeHQIngredientCount == 0);
|
||||
ImGui.BeginDisabled(RecipeUtils.HQIngredientCount == 0);
|
||||
var qualityNotches = QualityNotches;
|
||||
ImGui.SetNextItemWidth(LeftSideWidth - 115);
|
||||
if (ImGui.SliderInt("Starting Quality", ref qualityNotches, 0, RecipeHQIngredientCount, StartingQuality.ToString(), ImGuiSliderFlags.NoInput | ImGuiSliderFlags.AlwaysClamp))
|
||||
if (ImGui.SliderInt("Starting Quality", ref qualityNotches, 0, RecipeUtils.HQIngredientCount, StartingQuality.ToString(), ImGuiSliderFlags.NoInput | ImGuiSliderFlags.AlwaysClamp))
|
||||
QualityNotches = qualityNotches;
|
||||
ImGui.EndDisabled();
|
||||
|
||||
@@ -286,7 +256,7 @@ public unsafe class CraftingLog : Window
|
||||
var height = fontSize + (padding.Y * 2);
|
||||
var width = ImGui.GetContentRegionAvail().X;
|
||||
var size = new Vector2(width, height);
|
||||
var infoColWidth = SimulatorWindow.TooltipProgressBarSize.X;
|
||||
var infoColWidth = Simulator.TooltipProgressBarSize.X;
|
||||
var infoButtonCount = 3;
|
||||
var infoButtonWidth = (infoColWidth - ImGui.GetStyle().ItemSpacing.X * (infoButtonCount - 1)) / infoButtonCount;
|
||||
var infoButtonSize = new Vector2(infoButtonWidth, height);
|
||||
@@ -319,7 +289,7 @@ public unsafe class CraftingLog : Window
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.TextWrapped(macro.Name);
|
||||
if (state.HasValue)
|
||||
SimulatorWindow.DrawAllProgressTooltips(state!.Value);
|
||||
Simulator.DrawAllProgressTooltips(state!.Value);
|
||||
|
||||
if (ImGuiUtils.IconButtonSized(FontAwesomeIcon.Copy, infoButtonSize))
|
||||
CopyMacroToClipboard(macro);
|
||||
@@ -340,7 +310,7 @@ public unsafe class CraftingLog : Window
|
||||
var j = 0;
|
||||
foreach (var action in macro.Actions)
|
||||
{
|
||||
ImGui.Image(action.GetIcon(RecipeClassJob).ImGuiHandle, actionSize);
|
||||
ImGui.Image(action.GetIcon(RecipeUtils.ClassJob).ImGuiHandle, actionSize);
|
||||
if (j++ % actionCount != actionCount - 1)
|
||||
ImGui.SameLine();
|
||||
if (j == actionCount * 2)
|
||||
@@ -354,7 +324,7 @@ public unsafe class CraftingLog : Window
|
||||
|
||||
private void OpenSimulatorWindow(Macro? macro)
|
||||
{
|
||||
Service.Plugin.OpenSimulatorWindow(Recipe.ItemResult.Value!, Recipe.IsExpert, CharacterSimulationInput, RecipeClassJob, macro);
|
||||
Service.Plugin.OpenSimulatorWindow(RecipeUtils.Recipe.ItemResult.Value!, RecipeUtils.Recipe.IsExpert, CharacterSimulationInput, RecipeUtils.ClassJob, macro);
|
||||
}
|
||||
|
||||
private string GetMacroCommand(ActionType action, bool addWaitTimes)
|
||||
@@ -363,9 +333,9 @@ public unsafe class CraftingLog : Window
|
||||
if (actionBase is BaseComboAction comboActionBase)
|
||||
return $"{GetMacroCommand(comboActionBase.ActionTypeA, addWaitTimes)}\n{GetMacroCommand(comboActionBase.ActionTypeB, addWaitTimes)}";
|
||||
if (addWaitTimes)
|
||||
return $"/ac \"{action.GetName(RecipeClassJob)}\" <wait.{actionBase.MacroWaitTime}>";
|
||||
return $"/ac \"{action.GetName(RecipeUtils.ClassJob)}\" <wait.{actionBase.MacroWaitTime}>";
|
||||
else
|
||||
return $"/ac \"{action.GetName(RecipeClassJob)}\"";
|
||||
return $"/ac \"{action.GetName(RecipeUtils.ClassJob)}\"";
|
||||
}
|
||||
|
||||
private void CopyMacroToClipboard(Macro macro)
|
||||
@@ -401,11 +371,11 @@ public unsafe class CraftingLog : Window
|
||||
if (!gearset->Flags.HasFlag(RaptureGearsetModule.GearsetFlag.Exists))
|
||||
continue;
|
||||
|
||||
if (!ClassJobUtils.IsClassJob(gearset->ClassJob, RecipeClassJob))
|
||||
if (!ClassJobUtils.IsClassJob(gearset->ClassJob, RecipeUtils.ClassJob))
|
||||
continue;
|
||||
|
||||
var items = Gearsets.GetGearsetItems(gearset);
|
||||
var stats = Gearsets.CalculateCharacterStats(items, RecipeCharacterLevel, RecipeCanUseManipulation);
|
||||
var stats = Gearsets.CalculateCharacterStats(items, RecipeUtils.CharacterLevel, RecipeUtils.CanUseManipulation);
|
||||
var gearsetId = gearset->ID + 1;
|
||||
|
||||
ImGuiUtils.BeginGroupPanel($"{SafeMemory.ReadString((nint)gearset->Name, 47)} ({gearsetId})");
|
||||
@@ -421,61 +391,33 @@ public unsafe class CraftingLog : Window
|
||||
|
||||
public override bool DrawConditions()
|
||||
{
|
||||
if (Service.ClientState.LocalPlayer == null)
|
||||
if (!RecipeUtils.Update(out var isNew))
|
||||
return false;
|
||||
|
||||
Addon = (AddonRecipeNote*)Service.GameGui.GetAddonByName("RecipeNote");
|
||||
|
||||
if (Addon == null)
|
||||
// Check if RecipeNote addon is visible
|
||||
if (RecipeUtils.AddonRecipe->AtkUnitBase.WindowNode == null)
|
||||
return false;
|
||||
|
||||
if (Addon->AtkUnitBase.WindowNode == null)
|
||||
// Check if RecipeNote has a visible selected recipe
|
||||
if (!RecipeUtils.AddonRecipe->Unk258->IsVisible)
|
||||
return false;
|
||||
|
||||
State = RecipeNote.Instance();
|
||||
|
||||
var list = State->RecipeList;
|
||||
|
||||
if (list == null)
|
||||
return false;
|
||||
|
||||
var recipeEntry = list->SelectedRecipe;
|
||||
|
||||
if (recipeEntry == null)
|
||||
return false;
|
||||
|
||||
var isNewRecipe = RecipeId != recipeEntry->RecipeId;
|
||||
|
||||
RecipeId = recipeEntry->RecipeId;
|
||||
|
||||
var recipe = LuminaSheets.RecipeSheet.GetRow(RecipeId);
|
||||
|
||||
if (recipe == null)
|
||||
return false;
|
||||
|
||||
Recipe = recipe;
|
||||
|
||||
if (!Addon->Unk258->IsVisible)
|
||||
return false;
|
||||
|
||||
if (isNewRecipe)
|
||||
{
|
||||
if (isNew)
|
||||
QualityNotches = 0;
|
||||
CalculateRecipeStats();
|
||||
}
|
||||
|
||||
return base.DrawConditions();
|
||||
}
|
||||
|
||||
public override unsafe void PreDraw()
|
||||
{
|
||||
ref var unit = ref Addon->AtkUnitBase;
|
||||
var addon = RecipeUtils.AddonRecipe;
|
||||
ref var unit = ref addon->AtkUnitBase;
|
||||
var scale = unit.Scale;
|
||||
var pos = new Vector2(unit.X, unit.Y);
|
||||
var size = new Vector2(unit.WindowNode->AtkResNode.Width, unit.WindowNode->AtkResNode.Height) * scale;
|
||||
|
||||
var node = (AtkResNode*)Addon->Unk458; // unit.GetNodeById(59);
|
||||
var nodeParent = Addon->Unk258; // unit.GetNodeById(57);
|
||||
var node = (AtkResNode*)addon->Unk458; // unit.GetNodeById(59);
|
||||
var nodeParent = addon->Unk258; // unit.GetNodeById(57);
|
||||
|
||||
Position = pos + new Vector2(size.X, (nodeParent->Y + node->Y) * scale);
|
||||
SizeConstraints = new WindowSizeConstraints
|
||||
@@ -537,36 +479,38 @@ public unsafe class CraftingLog : Window
|
||||
|
||||
private CannotCraftReason CanCraftRecipe(Gearsets.GearsetItem[] items, CharacterStats stats)
|
||||
{
|
||||
if (!ClassJobUtils.IsClassJob((byte)Service.ClientState.LocalPlayer!.ClassJob.Id, RecipeClassJob))
|
||||
if (!ClassJobUtils.IsClassJob((byte)Service.ClientState.LocalPlayer!.ClassJob.Id, RecipeUtils.ClassJob))
|
||||
return CannotCraftReason.WrongClassJob;
|
||||
|
||||
if (Recipe.IsSpecializationRequired && !stats.IsSpecialist)
|
||||
var recipe = RecipeUtils.Recipe;
|
||||
|
||||
if (recipe.IsSpecializationRequired && !stats.IsSpecialist)
|
||||
return CannotCraftReason.SpecialistRequired;
|
||||
|
||||
if (Recipe.ItemRequired.Row != 0)
|
||||
if (recipe.ItemRequired.Row != 0)
|
||||
{
|
||||
if (Recipe.ItemRequired.Value != null)
|
||||
if (recipe.ItemRequired.Value != null)
|
||||
{
|
||||
if (!items.Any(i => Gearsets.IsItem(i, Recipe.ItemRequired.Row)))
|
||||
if (!items.Any(i => Gearsets.IsItem(i, recipe.ItemRequired.Row)))
|
||||
{
|
||||
return CannotCraftReason.RequiredItem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Recipe.StatusRequired.Row != 0)
|
||||
if (recipe.StatusRequired.Row != 0)
|
||||
{
|
||||
if (Recipe.StatusRequired.Value != null)
|
||||
if (recipe.StatusRequired.Value != null)
|
||||
{
|
||||
if (!Service.ClientState.LocalPlayer.StatusList.Any(s => s.StatusId == Recipe.StatusRequired.Row))
|
||||
if (!Service.ClientState.LocalPlayer.StatusList.Any(s => s.StatusId == recipe.StatusRequired.Row))
|
||||
return CannotCraftReason.RequiredStatus;
|
||||
}
|
||||
}
|
||||
|
||||
if (Recipe.RequiredCraftsmanship > stats.Craftsmanship)
|
||||
if (recipe.RequiredCraftsmanship > stats.Craftsmanship)
|
||||
return CannotCraftReason.CraftsmanshipTooLow;
|
||||
|
||||
if (Recipe.RequiredControl > stats.Control)
|
||||
if (recipe.RequiredControl > stats.Control)
|
||||
return CannotCraftReason.ControlTooLow;
|
||||
|
||||
return CannotCraftReason.OK;
|
||||
|
||||
@@ -6,11 +6,11 @@ using System;
|
||||
|
||||
namespace Craftimizer.Plugin.Windows;
|
||||
|
||||
public class SettingsWindow : Window
|
||||
public class Settings : Window
|
||||
{
|
||||
private static Configuration Config => Service.Configuration;
|
||||
|
||||
public SettingsWindow() : base("Craftimizer Settings")
|
||||
public Settings() : base("Craftimizer Settings")
|
||||
{
|
||||
Service.WindowSystem.AddWindow(this);
|
||||
|
||||
@@ -9,7 +9,7 @@ using ClassJob = Craftimizer.Simulator.ClassJob;
|
||||
|
||||
namespace Craftimizer.Plugin.Windows;
|
||||
|
||||
public sealed partial class SimulatorWindow : Window, IDisposable
|
||||
public sealed partial class Simulator : Window, IDisposable
|
||||
{
|
||||
private const ImGuiWindowFlags WindowFlags = ImGuiWindowFlags.AlwaysAutoResize;
|
||||
|
||||
@@ -23,13 +23,13 @@ public sealed partial class SimulatorWindow : Window, IDisposable
|
||||
private string MacroName { get; set; }
|
||||
// State is the state of the simulation *after* its corresponding action is executed.
|
||||
private List<(ActionType Action, string Tooltip, ActionResponse Response, SimulationState State)> Actions { get; }
|
||||
private Simulator.Simulator Simulator { get; set; }
|
||||
private Craftimizer.Simulator.Simulator Sim { get; set; }
|
||||
|
||||
private SimulationState LatestState => Actions.Count == 0 ? new(Input) : Actions[^1].State;
|
||||
|
||||
// Simulator is set by ResetSimulator()
|
||||
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
||||
public SimulatorWindow(Item item, bool isExpert, SimulationInput input, ClassJob classJob, Macro? macro) : base("Craftimizer Simulator", WindowFlags)
|
||||
public Simulator(Item item, bool isExpert, SimulationInput input, ClassJob classJob, Macro? macro) : base("Craftimizer Simulator", WindowFlags)
|
||||
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
||||
{
|
||||
Service.WindowSystem.AddWindow(this);
|
||||
@@ -58,7 +58,7 @@ public sealed partial class SimulatorWindow : Window, IDisposable
|
||||
|
||||
private void ResetSimulator()
|
||||
{
|
||||
Simulator = Configuration.CreateSimulator(LatestState);
|
||||
Sim = Configuration.CreateSimulator(LatestState);
|
||||
ReexecuteAllActions();
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -5,7 +5,7 @@ using System;
|
||||
|
||||
namespace Craftimizer.Plugin.Windows;
|
||||
|
||||
public sealed partial class SimulatorWindow : Window, IDisposable
|
||||
public sealed partial class Simulator : Window, IDisposable
|
||||
{
|
||||
private void AppendAction(ActionType action)
|
||||
{
|
||||
@@ -24,8 +24,8 @@ public sealed partial class SimulatorWindow : Window, IDisposable
|
||||
}
|
||||
else
|
||||
{
|
||||
var tooltip = actionBase.GetTooltip(Simulator, false);
|
||||
var (response, state) = Simulator.Execute(LatestState, action);
|
||||
var tooltip = actionBase.GetTooltip(Sim, false);
|
||||
var (response, state) = Sim.Execute(LatestState, action);
|
||||
Actions.Add((action, tooltip, response, state));
|
||||
}
|
||||
}
|
||||
+7
-7
@@ -13,7 +13,7 @@ using Dalamud.Game.Text;
|
||||
|
||||
namespace Craftimizer.Plugin.Windows;
|
||||
|
||||
public sealed partial class SimulatorWindow : Window, IDisposable
|
||||
public sealed partial class Simulator : Window, IDisposable
|
||||
{
|
||||
private const int ActionColumnSize = 260;
|
||||
|
||||
@@ -36,7 +36,7 @@ public sealed partial class SimulatorWindow : Window, IDisposable
|
||||
|
||||
private static readonly (ActionCategory Category, ActionType[] Actions)[] SortedActions;
|
||||
|
||||
static SimulatorWindow()
|
||||
static Simulator()
|
||||
{
|
||||
SortedActions = Enum.GetValues<ActionType>()
|
||||
.Where(a => a.Category() != ActionCategory.Combo)
|
||||
@@ -69,7 +69,7 @@ public sealed partial class SimulatorWindow : Window, IDisposable
|
||||
Configuration.Save();
|
||||
}
|
||||
|
||||
Simulator.SetState(LatestState);
|
||||
Sim.SetState(LatestState);
|
||||
|
||||
var actionSize = new Vector2((ActionColumnSize / 5) - ImGui.GetStyle().ItemSpacing.X * (6f / 5));
|
||||
ImGui.PushStyleColor(ImGuiCol.Button, Vector4.Zero);
|
||||
@@ -89,7 +89,7 @@ public sealed partial class SimulatorWindow : Window, IDisposable
|
||||
if (cannotUse && Configuration.HideUnlearnedActions)
|
||||
continue;
|
||||
|
||||
var shouldNotUse = !baseAction.CanUse(Simulator) || Simulator.IsComplete;
|
||||
var shouldNotUse = !baseAction.CanUse(Sim) || Sim.IsComplete;
|
||||
|
||||
ImGui.BeginDisabled(cannotUse);
|
||||
|
||||
@@ -97,7 +97,7 @@ public sealed partial class SimulatorWindow : Window, IDisposable
|
||||
AppendAction(action);
|
||||
|
||||
if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled))
|
||||
ImGui.SetTooltip($"{action.GetName(ClassJob)}\n{baseAction.GetTooltip(Simulator, true)}");
|
||||
ImGui.SetTooltip($"{action.GetName(ClassJob)}\n{baseAction.GetTooltip(Sim, true)}");
|
||||
|
||||
ImGui.EndDisabled();
|
||||
|
||||
@@ -210,11 +210,11 @@ public sealed partial class SimulatorWindow : Window, IDisposable
|
||||
ImGui.SameLine(0, 0);
|
||||
foreach (var effect in Enum.GetValues<EffectType>())
|
||||
{
|
||||
var duration = Simulator.GetEffectDuration(effect);
|
||||
var duration = Sim.GetEffectDuration(effect);
|
||||
if (duration == 0)
|
||||
continue;
|
||||
|
||||
var strength = Simulator.GetEffectStrength(effect);
|
||||
var strength = Sim.GetEffectStrength(effect);
|
||||
var icon = effect.GetIcon(strength);
|
||||
var iconSize = GetEffectSize(icon);
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@ using System.Numerics;
|
||||
|
||||
namespace Craftimizer.Plugin.Windows;
|
||||
|
||||
public sealed partial class SimulatorWindow : Window, IDisposable
|
||||
public sealed partial class Simulator : Window, IDisposable
|
||||
{
|
||||
private readonly record struct SynthDrawParams
|
||||
{
|
||||
+2
-2
@@ -10,7 +10,7 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace Craftimizer.Plugin.Windows;
|
||||
|
||||
public sealed partial class SimulatorWindow : Window, IDisposable
|
||||
public sealed partial class Simulator : Window, IDisposable
|
||||
{
|
||||
private Task SolverTask { get; set; } = Task.CompletedTask;
|
||||
private CancellationTokenSource SolverTaskToken { get; set; } = new();
|
||||
@@ -27,7 +27,7 @@ public sealed partial class SimulatorWindow : Window, IDisposable
|
||||
|
||||
private SimulationState? GenerateSolverState()
|
||||
{
|
||||
if (Simulator is SimulatorNoRandom)
|
||||
if (Sim is SimulatorNoRandom)
|
||||
{
|
||||
if (!Actions.Exists(a => a.Response != ActionResponse.UsedAction))
|
||||
return LatestState;
|
||||
Reference in New Issue
Block a user