Ability ants :p
This commit is contained in:
@@ -181,8 +181,9 @@ public partial class Configuration
|
|||||||
public bool SuggestMacroAutomatically { get; set; }
|
public bool SuggestMacroAutomatically { get; set; }
|
||||||
public bool ShowCommunityMacros { get; set; } = true;
|
public bool ShowCommunityMacros { get; set; } = true;
|
||||||
public bool SearchCommunityMacroAutomatically { get; set; }
|
public bool SearchCommunityMacroAutomatically { get; set; }
|
||||||
public int SynthHelperStepCount { get; set; } = 5;
|
public int SynthHelperStepCount { get; set; } = 3;
|
||||||
public bool SynthHelperDisplayOnlyFirstStep { get; set; }
|
public bool SynthHelperDisplayOnlyFirstStep { get; set; }
|
||||||
|
public bool SynthHelperAbilityAnts { get; set; }
|
||||||
|
|
||||||
public bool PinSynthHelperToWindow { get; set; } = true;
|
public bool PinSynthHelperToWindow { get; set; } = true;
|
||||||
public bool PinRecipeNoteToWindow { get; set; } = true;
|
public bool PinRecipeNoteToWindow { get; set; } = true;
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ public sealed class Plugin : IDalamudPlugin
|
|||||||
|
|
||||||
[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.")]
|
||||||
public void ExecuteSuggestedSynthHelperAction() =>
|
public void ExecuteSuggestedSynthHelperAction() =>
|
||||||
SynthHelperWindow.QueueSuggestedActionExecution();
|
SynthHelperWindow.ExecuteNextAction();
|
||||||
|
|
||||||
[Command(name: "/craftimizer", description: "Open the settings window.")]
|
[Command(name: "/craftimizer", description: "Open the settings window.")]
|
||||||
private void OpenSettingsWindowForced() =>
|
private void OpenSettingsWindowForced() =>
|
||||||
|
|||||||
@@ -18,17 +18,24 @@ public sealed unsafe class Hooks : IDisposable
|
|||||||
|
|
||||||
public readonly Hook<UseActionDelegate> UseActionHook = null!;
|
public readonly Hook<UseActionDelegate> UseActionHook = null!;
|
||||||
|
|
||||||
|
public delegate byte IsActionHighlightedDelegate(ActionManager* manager, CSActionType actionType, uint actionId);
|
||||||
|
|
||||||
|
public readonly Hook<IsActionHighlightedDelegate> IsActionHighlightedHook = null!;
|
||||||
|
|
||||||
public Hooks()
|
public Hooks()
|
||||||
{
|
{
|
||||||
UseActionHook = Service.GameInteropProvider.HookFromAddress<UseActionDelegate>((nint)ActionManager.MemberFunctionPointers.UseAction, UseActionDetour);
|
UseActionHook = Service.GameInteropProvider.HookFromAddress<UseActionDelegate>((nint)ActionManager.MemberFunctionPointers.UseAction, UseActionDetour);
|
||||||
|
IsActionHighlightedHook = Service.GameInteropProvider.HookFromAddress<IsActionHighlightedDelegate>((nint)ActionManager.MemberFunctionPointers.IsActionHighlighted, IsActionHighlightedDetour);
|
||||||
|
|
||||||
UseActionHook.Enable();
|
UseActionHook.Enable();
|
||||||
|
IsActionHighlightedHook.Enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool UseActionDetour(ActionManager* manager, CSActionType actionType, uint actionId, ulong targetId, uint param, uint useType, int pvp, nint a8)
|
private bool UseActionDetour(ActionManager* manager, CSActionType actionType, uint actionId, ulong targetId, uint param, uint useType, int pvp, nint a8)
|
||||||
{
|
{
|
||||||
var canCast = manager->GetActionStatus(actionType, actionId) == 0;
|
var canCast = manager->GetActionStatus(actionType, actionId) == 0;
|
||||||
var ret = UseActionHook.Original(manager, actionType, actionId, targetId, param, useType, pvp, a8);
|
var ret = UseActionHook.Original(manager, actionType, actionId, targetId, param, useType, pvp, a8);
|
||||||
if (canCast && ret && (actionType == CSActionType.CraftAction || actionType == CSActionType.Action))
|
if (canCast && ret && actionType is CSActionType.CraftAction or CSActionType.Action)
|
||||||
{
|
{
|
||||||
var classJob = ClassJobUtils.GetClassJobFromIdx((byte)(Service.ClientState.LocalPlayer?.ClassJob.Id ?? 0));
|
var classJob = ClassJobUtils.GetClassJobFromIdx((byte)(Service.ClientState.LocalPlayer?.ClassJob.Id ?? 0));
|
||||||
if (classJob != null)
|
if (classJob != null)
|
||||||
@@ -41,8 +48,40 @@ public sealed unsafe class Hooks : IDisposable
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private byte IsActionHighlightedDetour(ActionManager* manager, CSActionType actionType, uint actionId)
|
||||||
|
{
|
||||||
|
var ret = IsActionHighlightedHook.Original(manager, actionType, actionId);
|
||||||
|
|
||||||
|
if (!Service.Configuration.SynthHelperAbilityAnts)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (!Service.Plugin.SynthHelperWindow.ShouldDrawAnts)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (actionType is not (CSActionType.CraftAction or CSActionType.Action))
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
var jobId = Service.ClientState.LocalPlayer?.ClassJob.Id;
|
||||||
|
if (jobId == null)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
var classJob = ClassJobUtils.GetClassJobFromIdx((byte)jobId.Value);
|
||||||
|
if (classJob == null)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
var simActionType = ActionUtils.GetActionTypeFromId(actionId, classJob.Value, actionType == CSActionType.CraftAction);
|
||||||
|
if (simActionType == null)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (Service.Plugin.SynthHelperWindow.NextAction != simActionType)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
UseActionHook.Dispose();
|
UseActionHook.Dispose();
|
||||||
|
IsActionHighlightedHook.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -885,6 +885,16 @@ public sealed class Settings : Window, IDisposable
|
|||||||
ref isDirty
|
ref isDirty
|
||||||
);
|
);
|
||||||
|
|
||||||
|
DrawOption(
|
||||||
|
"Draw Ability Ants",
|
||||||
|
"Turns your hotbar into a whack-a-mole game! Draws ants for " +
|
||||||
|
"the next action that should be executed. Also disables ants " +
|
||||||
|
"for things like combo actions and condition procs.",
|
||||||
|
Config.SynthHelperAbilityAnts,
|
||||||
|
v => Config.SynthHelperAbilityAnts = v,
|
||||||
|
ref isDirty
|
||||||
|
);
|
||||||
|
|
||||||
DrawOption(
|
DrawOption(
|
||||||
"Step Count",
|
"Step Count",
|
||||||
"The minimum number of future steps to solve for during an in-game craft.",
|
"The minimum number of future steps to solve for during an in-game craft.",
|
||||||
|
|||||||
@@ -46,6 +46,8 @@ public sealed unsafe class SynthHelper : Window, IDisposable
|
|||||||
public RecipeData? RecipeData { get; private set; }
|
public RecipeData? RecipeData { get; private set; }
|
||||||
public CharacterStats? CharacterStats { get; private set; }
|
public CharacterStats? CharacterStats { get; private set; }
|
||||||
public SimulationInput? SimulationInput { get; private set; }
|
public SimulationInput? SimulationInput { get; private set; }
|
||||||
|
public ActionType? NextAction => (ShouldOpen && Macro.Count > 0) ? Macro[0].Action : null;
|
||||||
|
public bool ShouldDrawAnts => ShouldOpen;
|
||||||
|
|
||||||
public bool IsCrafting { get; private set; }
|
public bool IsCrafting { get; private set; }
|
||||||
private int CurrentActionCount { get; set; }
|
private int CurrentActionCount { get; set; }
|
||||||
@@ -65,8 +67,6 @@ public sealed unsafe class SynthHelper : Window, IDisposable
|
|||||||
private SimulationState currentState;
|
private SimulationState currentState;
|
||||||
private SimulatedMacro Macro { get; } = new();
|
private SimulatedMacro Macro { get; } = new();
|
||||||
|
|
||||||
private bool IsSuggestedActionExecutionQueued { get; set; }
|
|
||||||
|
|
||||||
private CancellationTokenSource? HelperTaskTokenSource { get; set; }
|
private CancellationTokenSource? HelperTaskTokenSource { get; set; }
|
||||||
private Exception? HelperTaskException { get; set; }
|
private Exception? HelperTaskException { get; set; }
|
||||||
private Solver.Solver? HelperTaskObject { get; set; }
|
private Solver.Solver? HelperTaskObject { get; set; }
|
||||||
@@ -133,9 +133,6 @@ public sealed unsafe class SynthHelper : Window, IDisposable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ShouldCalculate)
|
|
||||||
IsSuggestedActionExecutionQueued = false;
|
|
||||||
|
|
||||||
if (!ShouldOpen)
|
if (!ShouldOpen)
|
||||||
{
|
{
|
||||||
StyleAlpha = LastAlpha = null;
|
StyleAlpha = LastAlpha = null;
|
||||||
@@ -159,10 +156,24 @@ public sealed unsafe class SynthHelper : Window, IDisposable
|
|||||||
if (!Service.Configuration.EnableSynthHelper)
|
if (!Service.Configuration.EnableSynthHelper)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (Service.Configuration.DisableSynthHelperOnMacro &&
|
if (Service.Configuration.DisableSynthHelperOnMacro)
|
||||||
RaptureShellModule.Instance()->MacroCurrentLine >= 0 &&
|
{
|
||||||
!IsSuggestedActionExecutionQueued)
|
var module = RaptureShellModule.Instance();
|
||||||
return false;
|
if (module->MacroCurrentLine >= 0)
|
||||||
|
{
|
||||||
|
var hasCraftAction = false;
|
||||||
|
foreach (ref var line in module->MacroLines)
|
||||||
|
{
|
||||||
|
if (line.EqualToString("/craftaction"))
|
||||||
|
{
|
||||||
|
hasCraftAction = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!hasCraftAction)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Addon = (AddonSynthesis*)Service.GameGui.GetAddonByName("Synthesis");
|
Addon = (AddonSynthesis*)Service.GameGui.GetAddonByName("Synthesis");
|
||||||
|
|
||||||
@@ -239,8 +250,6 @@ public sealed unsafe class SynthHelper : Window, IDisposable
|
|||||||
ImGui.PopStyleVar();
|
ImGui.PopStyleVar();
|
||||||
|
|
||||||
base.PostDraw();
|
base.PostDraw();
|
||||||
|
|
||||||
IsSuggestedActionExecutionQueued = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Draw()
|
public override void Draw()
|
||||||
@@ -311,19 +320,16 @@ public sealed unsafe class SynthHelper : Window, IDisposable
|
|||||||
isPressed = ImGuiExtras.ButtonBehavior(bb, id, out isHovered, out isHeld, ImGuiButtonFlags.None);
|
isPressed = ImGuiExtras.ButtonBehavior(bb, id, out isHovered, out isHeld, ImGuiButtonFlags.None);
|
||||||
}
|
}
|
||||||
ImGui.ImageButton(action.GetIcon(RecipeData!.ClassJob).ImGuiHandle, new(imageSize), default, Vector2.One, 0, default, failedAction ? new(1, 1, 1, ImGui.GetStyle().DisabledAlpha) : Vector4.One);
|
ImGui.ImageButton(action.GetIcon(RecipeData!.ClassJob).ImGuiHandle, new(imageSize), default, Vector2.One, 0, default, failedAction ? new(1, 1, 1, ImGui.GetStyle().DisabledAlpha) : Vector4.One);
|
||||||
if (isPressed || IsSuggestedActionExecutionQueued)
|
if (isPressed && i == 0)
|
||||||
{
|
{
|
||||||
if (canExecute && i == 0)
|
if (ExecuteNextAction())
|
||||||
{
|
|
||||||
Service.Chat.SendMessage($"/ac \"{action.GetName(RecipeData.ClassJob)}\"");
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (isHovered)
|
if (isHovered)
|
||||||
{
|
{
|
||||||
ImGuiUtils.Tooltip($"{action.GetName(RecipeData!.ClassJob)}\n" +
|
ImGuiUtils.Tooltip($"{action.GetName(RecipeData!.ClassJob)}\n" +
|
||||||
$"{actionBase.GetTooltip(CreateSim(lastState), true)}" +
|
$"{actionBase.GetTooltip(CreateSim(lastState), true)}" +
|
||||||
$"{(canExecute && i == 0 ? "Click or run /craftaction to Execute" : string.Empty)}");
|
$"{(canExecute && i == 0 ? "Click or run /craftaction to execute" : string.Empty)}");
|
||||||
hoveredState = state;
|
hoveredState = state;
|
||||||
}
|
}
|
||||||
lastState = state;
|
lastState = state;
|
||||||
@@ -475,6 +481,18 @@ public sealed unsafe class SynthHelper : Window, IDisposable
|
|||||||
Service.Plugin.OpenMacroEditor(CharacterStats!, RecipeData!, new(Service.ClientState.LocalPlayer!.StatusList), [], null);
|
Service.Plugin.OpenMacroEditor(CharacterStats!, RecipeData!, new(Service.ClientState.LocalPlayer!.StatusList), [], null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool ExecuteNextAction()
|
||||||
|
{
|
||||||
|
var canExecute = !Service.Condition[ConditionFlag.Crafting40];
|
||||||
|
var action = NextAction;
|
||||||
|
if (canExecute && action != null)
|
||||||
|
{
|
||||||
|
Service.Chat.SendMessage($"/ac \"{action.Value.GetName(RecipeData!.ClassJob)}\"");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private void OnStartCrafting(ushort recipeId)
|
private void OnStartCrafting(ushort recipeId)
|
||||||
{
|
{
|
||||||
var shouldUpdateInput = false;
|
var shouldUpdateInput = false;
|
||||||
@@ -652,11 +670,6 @@ public sealed unsafe class SynthHelper : Window, IDisposable
|
|||||||
HelperTaskTokenSource?.Cancel();
|
HelperTaskTokenSource?.Cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void QueueSuggestedActionExecution()
|
|
||||||
{
|
|
||||||
IsSuggestedActionExecutionQueued = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Sim CreateSim(in SimulationState state) =>
|
private static Sim CreateSim(in SimulationState state) =>
|
||||||
Service.Configuration.ConditionRandomness ? new Sim() { State = state } : new SimNoRandom() { State = state };
|
Service.Configuration.ConditionRandomness ? new Sim() { State = state } : new SimNoRandom() { State = state };
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user