Add action pool selector to settings

This commit is contained in:
Asriel Camora
2024-03-03 19:04:06 -08:00
parent 84d7d5737f
commit 0eae63f7bc
2 changed files with 146 additions and 0 deletions
+133
View File
@@ -1,3 +1,5 @@
using Craftimizer.Simulator;
using Craftimizer.Simulator.Actions;
using Craftimizer.Solver; using Craftimizer.Solver;
using Dalamud.Interface; using Dalamud.Interface;
using Dalamud.Interface.Colors; using Dalamud.Interface.Colors;
@@ -8,8 +10,10 @@ using Dalamud.Interface.Windowing;
using FFXIVClientStructs.FFXIV.Client.UI; using FFXIVClientStructs.FFXIV.Client.UI;
using ImGuiNET; using ImGuiNET;
using System; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Numerics; using System.Numerics;
using System.Text;
namespace Craftimizer.Plugin.Windows; namespace Craftimizer.Plugin.Windows;
@@ -558,6 +562,21 @@ public sealed class Settings : Window, IDisposable
); );
} }
using (var panel = ImRaii2.GroupPanel("Action Pool", -1, out var poolWidth))
{
poolWidth -= ImGui.GetStyle().ItemSpacing.X * 2;
ImGui.Text("Select the actions you want the solver to choose from.");
var pool = config.ActionPool;
DrawActionPool(ref pool, poolWidth, out var isPoolDirty);
if (isPoolDirty)
{
config = config with { ActionPool = pool };
isDirty = true;
}
}
using (var panel = ImRaii2.GroupPanel("Advanced", -1, out _)) using (var panel = ImRaii2.GroupPanel("Advanced", -1, out _))
{ {
DrawOption( DrawOption(
@@ -676,6 +695,120 @@ public sealed class Settings : Window, IDisposable
configRef = config; configRef = config;
} }
private static void DrawActionPool(ref ActionType[] actionPool, float poolWidth, out bool isDirty)
{
isDirty = false;
var recipeData = Service.Plugin.GetDefaultStats().Recipe;
HashSet<ActionType> pool = new(actionPool);
var imageSize = ImGui.GetFrameHeight() * 2;
var spacing = ImGui.GetStyle().ItemSpacing.Y;
using var _color = ImRaii.PushColor(ImGuiCol.Button, Vector4.Zero);
using var _color3 = ImRaii.PushColor(ImGuiCol.ButtonHovered, Vector4.Zero);
using var _color2 = ImRaii.PushColor(ImGuiCol.ButtonActive, Vector4.Zero);
using var _alpha = ImRaii.PushStyle(ImGuiStyleVar.DisabledAlpha, ImGui.GetStyle().DisabledAlpha * .5f);
foreach (var category in Enum.GetValues<ActionCategory>())
{
if (category == ActionCategory.Combo)
continue;
var actions = category.GetActions();
using var panel = ImRaii2.GroupPanel(category.GetDisplayName(), poolWidth, out var availSpace);
var itemsPerRow = (int)MathF.Floor((availSpace + spacing) / (imageSize + spacing));
var itemCount = actions.Count;
var iterCount = (int)(Math.Ceiling((float)itemCount / itemsPerRow) * itemsPerRow);
for (var i = 0; i < iterCount; i++)
{
if (i % itemsPerRow != 0)
ImGui.SameLine(0, spacing);
if (i < itemCount)
{
var actionBase = actions[i].Base();
var isEnabled = pool.Contains(actions[i]);
var isInefficient = SolverConfig.InefficientActions.Contains(actions[i]);
var isRisky = SolverConfig.RiskyActions.Contains(actions[i]);
var iconTint = Vector4.One;
if (!isEnabled)
iconTint = new(1, 1, 1, ImGui.GetStyle().DisabledAlpha);
else if (isInefficient)
iconTint = new(1, 1f, .5f, 1);
else if (isRisky)
iconTint = new(1, .5f, .5f, 1);
if (ImGui.ImageButton(actions[i].GetIcon(recipeData.ClassJob).ImGuiHandle, new(imageSize), default, Vector2.One, 0, default, iconTint))
{
isDirty = true;
if (isEnabled)
pool.Remove(actions[i]);
else
pool.Add(actions[i]);
}
if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled))
{
var s = new StringBuilder();
s.AppendLine(actions[i].GetName(recipeData.ClassJob));
if (isInefficient)
s.AppendLine(
"Not recommended. This action may be randomly used in a " +
"detrimental way to the rest of the craft. Always use " +
"your best judgement if enabling this action.");
if (isRisky)
s.AppendLine(
"Useless; the solver currently doesn't take any risks in " +
"its crafts. It only takes steps that have a 100% chance of " +
"succeeding. If you want have a moment where you want to take " +
"risks in your craft (like in expert recipes), don't rely " +
"on the solver during that time.");
ImGuiUtils.TooltipWrapped(s.ToString());
}
}
else
ImGui.Dummy(new(imageSize));
}
}
if (isDirty)
{
bool InPool(BaseComboAction action)
{
if (action.ActionTypeA.Base() is BaseComboAction { } aCombo)
{
if (!InPool(aCombo))
return false;
}
else
{
if (!pool.Contains(action.ActionTypeA))
return false;
}
if (action.ActionTypeB.Base() is BaseComboAction { } bCombo)
{
if (!InPool(bCombo))
return false;
}
else
{
if (!pool.Contains(action.ActionTypeB))
return false;
}
return true;
}
foreach(var combo in ActionCategory.Combo.GetActions())
{
if (combo.Base() is BaseComboAction { } comboAction)
{
if (!InPool(comboAction))
pool.Remove(combo);
else
pool.Add(combo);
}
}
actionPool = pool.ToArray();
}
}
private void DrawTabSimulator() private void DrawTabSimulator()
{ {
using var tab = TabItem("Simulator"); using var tab = TabItem("Simulator");
+13
View File
@@ -93,6 +93,19 @@ public readonly record struct SolverConfig
ActionType.BasicTouch, ActionType.BasicTouch,
}); });
public static readonly IReadOnlySet<ActionType> InefficientActions = new HashSet<ActionType>(new[]
{
ActionType.CarefulObservation,
ActionType.HeartAndSoul,
ActionType.FinalAppraisal
});
public static readonly IReadOnlySet<ActionType> RiskyActions = new HashSet<ActionType>(new[]
{
ActionType.RapidSynthesis,
ActionType.HastyTouch,
});
public static readonly SolverConfig SimulatorDefault = new SolverConfig() with public static readonly SolverConfig SimulatorDefault = new SolverConfig() with
{ {