Ability ants :p

This commit is contained in:
Asriel Camora
2024-07-04 00:36:58 -07:00
parent 5093867971
commit ec60bcfdcf
5 changed files with 88 additions and 25 deletions
+2 -1
View File
@@ -181,8 +181,9 @@ public partial class Configuration
public bool SuggestMacroAutomatically { get; set; }
public bool ShowCommunityMacros { get; set; } = true;
public bool SearchCommunityMacroAutomatically { get; set; }
public int SynthHelperStepCount { get; set; } = 5;
public int SynthHelperStepCount { get; set; } = 3;
public bool SynthHelperDisplayOnlyFirstStep { get; set; }
public bool SynthHelperAbilityAnts { get; set; }
public bool PinSynthHelperToWindow { get; set; } = true;
public bool PinRecipeNoteToWindow { get; set; } = true;
+1 -1
View File
@@ -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.")]
public void ExecuteSuggestedSynthHelperAction() =>
SynthHelperWindow.QueueSuggestedActionExecution();
SynthHelperWindow.ExecuteNextAction();
[Command(name: "/craftimizer", description: "Open the settings window.")]
private void OpenSettingsWindowForced() =>
+40 -1
View File
@@ -18,17 +18,24 @@ public sealed unsafe class Hooks : IDisposable
public readonly Hook<UseActionDelegate> UseActionHook = null!;
public delegate byte IsActionHighlightedDelegate(ActionManager* manager, CSActionType actionType, uint actionId);
public readonly Hook<IsActionHighlightedDelegate> IsActionHighlightedHook = null!;
public Hooks()
{
UseActionHook = Service.GameInteropProvider.HookFromAddress<UseActionDelegate>((nint)ActionManager.MemberFunctionPointers.UseAction, UseActionDetour);
IsActionHighlightedHook = Service.GameInteropProvider.HookFromAddress<IsActionHighlightedDelegate>((nint)ActionManager.MemberFunctionPointers.IsActionHighlighted, IsActionHighlightedDetour);
UseActionHook.Enable();
IsActionHighlightedHook.Enable();
}
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 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));
if (classJob != null)
@@ -41,8 +48,40 @@ public sealed unsafe class Hooks : IDisposable
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()
{
UseActionHook.Dispose();
IsActionHighlightedHook.Dispose();
}
}
+10
View File
@@ -885,6 +885,16 @@ public sealed class Settings : Window, IDisposable
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(
"Step Count",
"The minimum number of future steps to solve for during an in-game craft.",
+35 -22
View File
@@ -46,6 +46,8 @@ public sealed unsafe class SynthHelper : Window, IDisposable
public RecipeData? RecipeData { get; private set; }
public CharacterStats? CharacterStats { 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; }
private int CurrentActionCount { get; set; }
@@ -65,8 +67,6 @@ public sealed unsafe class SynthHelper : Window, IDisposable
private SimulationState currentState;
private SimulatedMacro Macro { get; } = new();
private bool IsSuggestedActionExecutionQueued { get; set; }
private CancellationTokenSource? HelperTaskTokenSource { get; set; }
private Exception? HelperTaskException { 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)
{
StyleAlpha = LastAlpha = null;
@@ -159,10 +156,24 @@ public sealed unsafe class SynthHelper : Window, IDisposable
if (!Service.Configuration.EnableSynthHelper)
return false;
if (Service.Configuration.DisableSynthHelperOnMacro &&
RaptureShellModule.Instance()->MacroCurrentLine >= 0 &&
!IsSuggestedActionExecutionQueued)
return false;
if (Service.Configuration.DisableSynthHelperOnMacro)
{
var module = RaptureShellModule.Instance();
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");
@@ -239,8 +250,6 @@ public sealed unsafe class SynthHelper : Window, IDisposable
ImGui.PopStyleVar();
base.PostDraw();
IsSuggestedActionExecutionQueued = false;
}
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);
}
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)
{
Service.Chat.SendMessage($"/ac \"{action.GetName(RecipeData.ClassJob)}\"");
if (ExecuteNextAction())
break;
}
}
if (isHovered)
{
ImGuiUtils.Tooltip($"{action.GetName(RecipeData!.ClassJob)}\n" +
$"{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;
}
lastState = state;
@@ -475,6 +481,18 @@ public sealed unsafe class SynthHelper : Window, IDisposable
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)
{
var shouldUpdateInput = false;
@@ -652,11 +670,6 @@ public sealed unsafe class SynthHelper : Window, IDisposable
HelperTaskTokenSource?.Cancel();
}
public void QueueSuggestedActionExecution()
{
IsSuggestedActionExecutionQueued = true;
}
private static Sim CreateSim(in SimulationState state) =>
Service.Configuration.ConditionRandomness ? new Sim() { State = state } : new SimNoRandom() { State = state };