forked from liza/Questionable
Remove 'Automatically complete snipe tasks'
This commit is contained in:
parent
73e030b620
commit
0265fcc0ae
@ -7,7 +7,7 @@ namespace Questionable;
|
|||||||
|
|
||||||
internal sealed class Configuration : IPluginConfiguration
|
internal sealed class Configuration : IPluginConfiguration
|
||||||
{
|
{
|
||||||
public const int PluginSetupVersion = 1;
|
public const int PluginSetupVersion = 2;
|
||||||
|
|
||||||
public int Version { get; set; } =1 ;
|
public int Version { get; set; } =1 ;
|
||||||
public int PluginSetupCompleteVersion { get; set; }
|
public int PluginSetupCompleteVersion { get; set; }
|
||||||
@ -28,7 +28,6 @@ internal sealed class Configuration : IPluginConfiguration
|
|||||||
public bool HideInAllInstances { get; set; } = true;
|
public bool HideInAllInstances { get; set; } = true;
|
||||||
public bool UseEscToCancelQuesting { get; set; } = true;
|
public bool UseEscToCancelQuesting { get; set; } = true;
|
||||||
public bool ShowIncompleteSeasonalEvents { get; set; } = true;
|
public bool ShowIncompleteSeasonalEvents { get; set; } = true;
|
||||||
public bool AutomaticallyCompleteSnipeTasks { get; set; }
|
|
||||||
public bool ConfigureTextAdvance { get; set; } = true;
|
public bool ConfigureTextAdvance { get; set; } = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,14 +12,14 @@ namespace Questionable.Controller.Steps.Common;
|
|||||||
internal static class SendNotification
|
internal static class SendNotification
|
||||||
{
|
{
|
||||||
internal sealed class Factory(
|
internal sealed class Factory(
|
||||||
Configuration configuration,
|
AutomatonIpc automatonIpc,
|
||||||
TerritoryData territoryData) : SimpleTaskFactory
|
TerritoryData territoryData) : SimpleTaskFactory
|
||||||
{
|
{
|
||||||
public override ITask? CreateTask(Quest quest, QuestSequence sequence, QuestStep step)
|
public override ITask? CreateTask(Quest quest, QuestSequence sequence, QuestStep step)
|
||||||
{
|
{
|
||||||
return step.InteractionType switch
|
return step.InteractionType switch
|
||||||
{
|
{
|
||||||
EInteractionType.Snipe when !configuration.General.AutomaticallyCompleteSnipeTasks =>
|
EInteractionType.Snipe when !automatonIpc.IsAutoSnipeEnabled =>
|
||||||
new Task(step.InteractionType, step.Comment),
|
new Task(step.InteractionType, step.Comment),
|
||||||
EInteractionType.Duty =>
|
EInteractionType.Duty =>
|
||||||
new Task(step.InteractionType, step.ContentFinderConditionId.HasValue
|
new Task(step.InteractionType, step.ContentFinderConditionId.HasValue
|
||||||
|
@ -8,6 +8,7 @@ using FFXIVClientStructs.FFXIV.Client.Game;
|
|||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Questionable.Controller.Steps.Shared;
|
using Questionable.Controller.Steps.Shared;
|
||||||
using Questionable.Controller.Utils;
|
using Questionable.Controller.Utils;
|
||||||
|
using Questionable.External;
|
||||||
using Questionable.Functions;
|
using Questionable.Functions;
|
||||||
using Questionable.Model;
|
using Questionable.Model;
|
||||||
using Questionable.Model.Questing;
|
using Questionable.Model.Questing;
|
||||||
@ -16,7 +17,7 @@ namespace Questionable.Controller.Steps.Interactions;
|
|||||||
|
|
||||||
internal static class Interact
|
internal static class Interact
|
||||||
{
|
{
|
||||||
internal sealed class Factory(Configuration configuration) : ITaskFactory
|
internal sealed class Factory(AutomatonIpc automatonIpc) : ITaskFactory
|
||||||
{
|
{
|
||||||
public IEnumerable<ITask> CreateAllTasks(Quest quest, QuestSequence sequence, QuestStep step)
|
public IEnumerable<ITask> CreateAllTasks(Quest quest, QuestSequence sequence, QuestStep step)
|
||||||
{
|
{
|
||||||
@ -43,7 +44,7 @@ internal static class Interact
|
|||||||
}
|
}
|
||||||
else if (step.InteractionType == EInteractionType.Snipe)
|
else if (step.InteractionType == EInteractionType.Snipe)
|
||||||
{
|
{
|
||||||
if (!configuration.General.AutomaticallyCompleteSnipeTasks)
|
if (!automatonIpc.IsAutoSnipeEnabled)
|
||||||
yield break;
|
yield break;
|
||||||
}
|
}
|
||||||
else if (step.InteractionType != EInteractionType.Interact)
|
else if (step.InteractionType != EInteractionType.Interact)
|
||||||
|
@ -1,48 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Dalamud.Hooking;
|
|
||||||
using Dalamud.Plugin.Services;
|
|
||||||
using FFXIVClientStructs.FFXIV.Client.Game.Event;
|
|
||||||
using FFXIVClientStructs.FFXIV.Common.Lua;
|
|
||||||
|
|
||||||
namespace Questionable.Controller.Utils;
|
|
||||||
|
|
||||||
internal sealed unsafe class AutoSnipeHandler : IDisposable
|
|
||||||
{
|
|
||||||
private readonly QuestController _questController;
|
|
||||||
private readonly Configuration _configuration;
|
|
||||||
private readonly Hook<EnqueueSnipeTaskDelegate> _enqueueSnipeTaskHook;
|
|
||||||
|
|
||||||
private delegate ulong EnqueueSnipeTaskDelegate(EventSceneModuleImplBase* scene, lua_State* state);
|
|
||||||
|
|
||||||
public AutoSnipeHandler(QuestController questController, Configuration configuration, IGameInteropProvider gameInteropProvider)
|
|
||||||
{
|
|
||||||
_questController = questController;
|
|
||||||
_configuration = configuration;
|
|
||||||
|
|
||||||
_enqueueSnipeTaskHook =
|
|
||||||
gameInteropProvider.HookFromSignature<EnqueueSnipeTaskDelegate>(
|
|
||||||
"48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 48 83 EC 50 48 8B F1 48 8D 4C 24 ?? E8 ?? ?? ?? ?? 48 8B 4C 24 ??",
|
|
||||||
EnqueueSnipeTask);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Enable() => _enqueueSnipeTaskHook.Enable();
|
|
||||||
|
|
||||||
private ulong EnqueueSnipeTask(EventSceneModuleImplBase* scene, lua_State* state)
|
|
||||||
{
|
|
||||||
if (_configuration.General.AutomaticallyCompleteSnipeTasks && _questController.IsRunning)
|
|
||||||
{
|
|
||||||
var val = state->top;
|
|
||||||
val->tt = 3;
|
|
||||||
val->value.n = 1;
|
|
||||||
state->top += 1;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return _enqueueSnipeTaskHook.Original.Invoke(scene, state);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
_enqueueSnipeTaskHook.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
40
Questionable/External/AutomatonIpc.cs
vendored
Normal file
40
Questionable/External/AutomatonIpc.cs
vendored
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
using Dalamud.Plugin;
|
||||||
|
using Dalamud.Plugin.Ipc;
|
||||||
|
using Dalamud.Plugin.Ipc.Exceptions;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace Questionable.External;
|
||||||
|
|
||||||
|
internal sealed class AutomatonIpc
|
||||||
|
{
|
||||||
|
private readonly ILogger<AutomatonIpc> _logger;
|
||||||
|
private readonly ICallGateSubscriber<string,bool> _isTweakEnabled;
|
||||||
|
private bool _loggedIpcError;
|
||||||
|
|
||||||
|
public AutomatonIpc(IDalamudPluginInterface pluginInterface, ILogger<AutomatonIpc> logger)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_isTweakEnabled = pluginInterface.GetIpcSubscriber<string, bool>("Automaton.IsTweakEnabled");
|
||||||
|
logger.LogWarning("Automaton x {IsTweakEnabled}", IsAutoSnipeEnabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsAutoSnipeEnabled
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return _isTweakEnabled.InvokeFunc("AutoSnipeQuests");
|
||||||
|
}
|
||||||
|
catch (IpcError e)
|
||||||
|
{
|
||||||
|
if (!_loggedIpcError)
|
||||||
|
{
|
||||||
|
_loggedIpcError = true;
|
||||||
|
_logger.LogWarning(e, "Could not query automaton for tweak status, probably not installed");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -112,7 +112,6 @@ public sealed class QuestionablePlugin : IDalamudPlugin
|
|||||||
serviceCollection.AddSingleton<ChatFunctions>();
|
serviceCollection.AddSingleton<ChatFunctions>();
|
||||||
serviceCollection.AddSingleton<QuestFunctions>();
|
serviceCollection.AddSingleton<QuestFunctions>();
|
||||||
serviceCollection.AddSingleton<DalamudReflector>();
|
serviceCollection.AddSingleton<DalamudReflector>();
|
||||||
serviceCollection.AddSingleton<AutoSnipeHandler>();
|
|
||||||
|
|
||||||
serviceCollection.AddSingleton<AetherCurrentData>();
|
serviceCollection.AddSingleton<AetherCurrentData>();
|
||||||
serviceCollection.AddSingleton<AetheryteData>();
|
serviceCollection.AddSingleton<AetheryteData>();
|
||||||
@ -128,6 +127,7 @@ public sealed class QuestionablePlugin : IDalamudPlugin
|
|||||||
serviceCollection.AddSingleton<QuestionableIpc>();
|
serviceCollection.AddSingleton<QuestionableIpc>();
|
||||||
serviceCollection.AddSingleton<TextAdvanceIpc>();
|
serviceCollection.AddSingleton<TextAdvanceIpc>();
|
||||||
serviceCollection.AddSingleton<NotificationMasterIpc>();
|
serviceCollection.AddSingleton<NotificationMasterIpc>();
|
||||||
|
serviceCollection.AddSingleton<AutomatonIpc>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void AddTaskFactories(ServiceCollection serviceCollection)
|
private static void AddTaskFactories(ServiceCollection serviceCollection)
|
||||||
@ -300,8 +300,8 @@ public sealed class QuestionablePlugin : IDalamudPlugin
|
|||||||
serviceProvider.GetRequiredService<ShopController>();
|
serviceProvider.GetRequiredService<ShopController>();
|
||||||
serviceProvider.GetRequiredService<QuestionableIpc>();
|
serviceProvider.GetRequiredService<QuestionableIpc>();
|
||||||
serviceProvider.GetRequiredService<DalamudInitializer>();
|
serviceProvider.GetRequiredService<DalamudInitializer>();
|
||||||
serviceProvider.GetRequiredService<AutoSnipeHandler>().Enable();
|
|
||||||
serviceProvider.GetRequiredService<TextAdvanceIpc>();
|
serviceProvider.GetRequiredService<TextAdvanceIpc>();
|
||||||
|
serviceProvider.GetRequiredService<AutomatonIpc>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
|
@ -115,18 +115,6 @@ internal sealed class ConfigWindow : LWindow, IPersistableWindowConfig
|
|||||||
_configuration.General.ConfigureTextAdvance = configureTextAdvance;
|
_configuration.General.ConfigureTextAdvance = configureTextAdvance;
|
||||||
Save();
|
Save();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui.CollapsingHeader("Cheats"))
|
|
||||||
{
|
|
||||||
ImGui.TextColored(ImGuiColors.DalamudRed,
|
|
||||||
"This setting will be removed in a future version, and will be\navailable through TextAdvance instead.");
|
|
||||||
bool automaticallyCompleteSnipeTasks = _configuration.General.AutomaticallyCompleteSnipeTasks;
|
|
||||||
if (ImGui.Checkbox("Automatically complete snipe tasks", ref automaticallyCompleteSnipeTasks))
|
|
||||||
{
|
|
||||||
_configuration.General.AutomaticallyCompleteSnipeTasks = automaticallyCompleteSnipeTasks;
|
|
||||||
Save();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawNotificationsTab()
|
private void DrawNotificationsTab()
|
||||||
|
@ -10,10 +10,11 @@ using ImGuiNET;
|
|||||||
using LLib;
|
using LLib;
|
||||||
using LLib.ImGui;
|
using LLib.ImGui;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Questionable.External;
|
||||||
|
|
||||||
namespace Questionable.Windows;
|
namespace Questionable.Windows;
|
||||||
|
|
||||||
internal sealed class OneTimeSetupWindow : LWindow, IDisposable
|
internal sealed class OneTimeSetupWindow : LWindow
|
||||||
{
|
{
|
||||||
private static readonly IReadOnlyList<PluginInfo> RequiredPlugins =
|
private static readonly IReadOnlyList<PluginInfo> RequiredPlugins =
|
||||||
[
|
[
|
||||||
@ -22,35 +23,24 @@ internal sealed class OneTimeSetupWindow : LWindow, IDisposable
|
|||||||
vnavmesh handles the navigation within a zone, moving
|
vnavmesh handles the navigation within a zone, moving
|
||||||
your character to the next quest-related objective.
|
your character to the next quest-related objective.
|
||||||
""",
|
""",
|
||||||
new Uri("https://github.com/awgil/ffxiv_navmesh/")),
|
new Uri("https://github.com/awgil/ffxiv_navmesh/"),
|
||||||
|
new Uri("https://puni.sh/api/repository/veyn")),
|
||||||
new("Lifestream",
|
new("Lifestream",
|
||||||
"""
|
"""
|
||||||
Used to travel to aethernet shards in cities.
|
Used to travel to aethernet shards in cities.
|
||||||
""",
|
""",
|
||||||
new Uri("https://github.com/NightmareXIV/Lifestream")),
|
new Uri("https://github.com/NightmareXIV/Lifestream"),
|
||||||
|
new Uri("https://github.com/NightmareXIV/MyDalamudPlugins/raw/main/pluginmaster.json")),
|
||||||
new("TextAdvance",
|
new("TextAdvance",
|
||||||
"""
|
"""
|
||||||
Automatically accepts and turns in quests, skips cutscenes
|
Automatically accepts and turns in quests, skips cutscenes
|
||||||
and dialogue.
|
and dialogue.
|
||||||
""",
|
""",
|
||||||
new Uri("https://github.com/NightmareXIV/TextAdvance")),
|
new Uri("https://github.com/NightmareXIV/TextAdvance"),
|
||||||
|
new Uri("https://github.com/NightmareXIV/MyDalamudPlugins/raw/main/pluginmaster.json")),
|
||||||
];
|
];
|
||||||
|
|
||||||
private static readonly IReadOnlyList<PluginInfo> RecommendedPlugins =
|
private readonly IReadOnlyList<PluginInfo> _recommendedPlugins;
|
||||||
[
|
|
||||||
new("Rotation Solver Reborn",
|
|
||||||
"""
|
|
||||||
Automatically handles most combat interactions you encounter
|
|
||||||
during quests, including being interrupted by mobs.
|
|
||||||
""",
|
|
||||||
new Uri("https://github.com/FFXIV-CombatReborn/RotationSolverReborn")),
|
|
||||||
new("NotificationMaster",
|
|
||||||
"""
|
|
||||||
Sends a configurable out-of-game notification if a quest
|
|
||||||
requires manual actions.
|
|
||||||
""",
|
|
||||||
new Uri("https://github.com/NightmareXIV/NotificationMaster")),
|
|
||||||
];
|
|
||||||
|
|
||||||
private readonly Configuration _configuration;
|
private readonly Configuration _configuration;
|
||||||
private readonly IDalamudPluginInterface _pluginInterface;
|
private readonly IDalamudPluginInterface _pluginInterface;
|
||||||
@ -59,7 +49,7 @@ internal sealed class OneTimeSetupWindow : LWindow, IDisposable
|
|||||||
private readonly ILogger<OneTimeSetupWindow> _logger;
|
private readonly ILogger<OneTimeSetupWindow> _logger;
|
||||||
|
|
||||||
public OneTimeSetupWindow(Configuration configuration, IDalamudPluginInterface pluginInterface, UiUtils uiUtils,
|
public OneTimeSetupWindow(Configuration configuration, IDalamudPluginInterface pluginInterface, UiUtils uiUtils,
|
||||||
DalamudReflector dalamudReflector, ILogger<OneTimeSetupWindow> logger)
|
DalamudReflector dalamudReflector, ILogger<OneTimeSetupWindow> logger, AutomatonIpc automatonIpc)
|
||||||
: base("Questionable Setup###QuestionableOneTimeSetup",
|
: base("Questionable Setup###QuestionableOneTimeSetup",
|
||||||
ImGuiWindowFlags.NoCollapse | ImGuiWindowFlags.AlwaysAutoResize | ImGuiWindowFlags.NoSavedSettings, true)
|
ImGuiWindowFlags.NoCollapse | ImGuiWindowFlags.AlwaysAutoResize | ImGuiWindowFlags.NoSavedSettings, true)
|
||||||
{
|
{
|
||||||
@ -69,6 +59,33 @@ internal sealed class OneTimeSetupWindow : LWindow, IDisposable
|
|||||||
_dalamudReflector = dalamudReflector;
|
_dalamudReflector = dalamudReflector;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
|
||||||
|
_recommendedPlugins =
|
||||||
|
[
|
||||||
|
new("Rotation Solver Reborn",
|
||||||
|
"""
|
||||||
|
Automatically handles most combat interactions you encounter
|
||||||
|
during quests, including being interrupted by mobs.
|
||||||
|
""",
|
||||||
|
new Uri("https://github.com/FFXIV-CombatReborn/RotationSolverReborn"),
|
||||||
|
new Uri(
|
||||||
|
"https://raw.githubusercontent.com/FFXIV-CombatReborn/CombatRebornRepo/main/pluginmaster.json")),
|
||||||
|
new PluginInfo("Automaton",
|
||||||
|
"""
|
||||||
|
Automaton is a collection of automation-related tweaks.
|
||||||
|
The 'Sniper no sniping' tweak can complete snipe tasks automatically.
|
||||||
|
""",
|
||||||
|
new Uri("https://github.com/Jaksuhn/Automaton"),
|
||||||
|
new Uri("https://puni.sh/api/repository/croizat"),
|
||||||
|
[new PluginDetailInfo("'Sniper no sniping' enabled", () => automatonIpc.IsAutoSnipeEnabled)]),
|
||||||
|
new("NotificationMaster",
|
||||||
|
"""
|
||||||
|
Sends a configurable out-of-game notification if a quest
|
||||||
|
requires manual actions.
|
||||||
|
""",
|
||||||
|
new Uri("https://github.com/NightmareXIV/NotificationMaster"),
|
||||||
|
null),
|
||||||
|
];
|
||||||
|
|
||||||
RespectCloseHotkey = false;
|
RespectCloseHotkey = false;
|
||||||
ShowCloseButton = false;
|
ShowCloseButton = false;
|
||||||
AllowPinning = false;
|
AllowPinning = false;
|
||||||
@ -101,7 +118,7 @@ internal sealed class OneTimeSetupWindow : LWindow, IDisposable
|
|||||||
ImGui.Text("The following plugins are recommended, but not required:");
|
ImGui.Text("The following plugins are recommended, but not required:");
|
||||||
using (ImRaii.PushIndent())
|
using (ImRaii.PushIndent())
|
||||||
{
|
{
|
||||||
foreach (var plugin in RecommendedPlugins)
|
foreach (var plugin in _recommendedPlugins)
|
||||||
DrawPlugin(plugin, checklistPadding);
|
DrawPlugin(plugin, checklistPadding);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,8 +166,28 @@ internal sealed class OneTimeSetupWindow : LWindow, IDisposable
|
|||||||
using (ImRaii.PushIndent(checklistPadding))
|
using (ImRaii.PushIndent(checklistPadding))
|
||||||
{
|
{
|
||||||
ImGui.TextUnformatted(plugin.Details);
|
ImGui.TextUnformatted(plugin.Details);
|
||||||
if (!isInstalled && ImGui.Button("Open Repository"))
|
if (plugin.DetailsToCheck != null)
|
||||||
Util.OpenLink(plugin.Uri.ToString());
|
{
|
||||||
|
foreach (var detail in plugin.DetailsToCheck)
|
||||||
|
_uiUtils.ChecklistItem(detail.DisplayName, isInstalled && detail.Predicate());
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.Spacing();
|
||||||
|
|
||||||
|
if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Globe, "Open Website"))
|
||||||
|
Util.OpenLink(plugin.WebsiteUri.ToString());
|
||||||
|
|
||||||
|
ImGui.SameLine();
|
||||||
|
if (plugin.DalamudRepositoryUri != null)
|
||||||
|
{
|
||||||
|
if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Code, "Open Repository"))
|
||||||
|
Util.OpenLink(plugin.DalamudRepositoryUri.ToString());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ImGui.AlignTextToFramePadding();
|
||||||
|
ImGuiComponents.HelpMarker("Available on official Dalamud Repository");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,12 +199,12 @@ internal sealed class OneTimeSetupWindow : LWindow, IDisposable
|
|||||||
return _dalamudReflector.TryGetDalamudPlugin(internalName, out _, suppressErrors: true, ignoreCache: true);
|
return _dalamudReflector.TryGetDalamudPlugin(internalName, out _, suppressErrors: true, ignoreCache: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
private sealed record PluginInfo(
|
private sealed record PluginInfo(
|
||||||
string DisplayName,
|
string DisplayName,
|
||||||
string Details,
|
string Details,
|
||||||
Uri Uri);
|
Uri WebsiteUri,
|
||||||
|
Uri? DalamudRepositoryUri,
|
||||||
|
List<PluginDetailInfo>? DetailsToCheck = null);
|
||||||
|
|
||||||
|
private sealed record PluginDetailInfo(string DisplayName, Func<bool> Predicate);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user