"Z": -210.22363
},
"TerritoryId": 622,
- "InteractionType": "Instruction",
+ "InteractionType": "Snipe",
"Comment": "Snipe sheep"
}
]
"Z": 208.484
},
"TerritoryId": 787,
- "InteractionType": "Instruction",
+ "InteractionType": "Snipe",
"Comment": "Far on the left"
}
]
"Z": 147.23425
},
"TerritoryId": 614,
- "InteractionType": "Instruction",
+ "InteractionType": "Snipe",
"Comment": "Snipe soldiers"
}
]
"Z": 237.04883
},
"TerritoryId": 614,
- "InteractionType": "Instruction",
+ "InteractionType": "Snipe",
"Comment": "Snipe soldiers"
}
]
"Z": 603.2959
},
"TerritoryId": 614,
- "InteractionType": "Instruction",
+ "InteractionType": "Snipe",
"Comment": "Snipe soldiers"
}
]
"Z": 196.55139\r
},\r
"TerritoryId": 621,\r
- "InteractionType": "Instruction",\r
+ "InteractionType": "Snipe",\r
"Comment": "Aim at jaw",\r
"Fly": true\r
}\r
"Z": 282.7954\r
},\r
"TerritoryId": 621,\r
- "InteractionType": "Instruction",\r
+ "InteractionType": "Snipe",\r
"Fly": true,\r
"Comment": "Aim at nearest eye"\r
}\r
"Z": 755.58093
},
"TerritoryId": 816,
- "InteractionType": "Instruction",
+ "InteractionType": "Snipe",
"Fly": true,
"Comment": "Throw Porxies at Beavers"
}
"Z": 656.9772
},
"TerritoryId": 814,
- "InteractionType": "Instruction",
+ "InteractionType": "Snipe",
"Comment": "Click the guy in front of (or near) the light house stairs"
}
]
"Z": -186.14484
},
"TerritoryId": 815,
- "InteractionType": "Instruction",
+ "InteractionType": "Snipe",
"Comment": "Click all four foods"
}
]
"Z": -92.97333
},
"TerritoryId": 813,
- "InteractionType": "WaitForManualProgress",
+ "InteractionType": "Snipe",
"Comment": "Tablet is on the right middle shelf of the table"
}
]
"Z": -359.4873
},
"TerritoryId": 817,
- "InteractionType": "WaitForManualProgress",
+ "InteractionType": "Snipe",
"Comment": "Click murals"
}
]
"Z": 22.47644
},
"TerritoryId": 814,
- "InteractionType": "WaitForManualProgress",
+ "InteractionType": "Snipe",
"Comment": "Click on the guy left of the the rock"
}
]
"Z": -616.47974
},
"TerritoryId": 814,
- "InteractionType": "WaitForManualProgress",
+ "InteractionType": "Snipe",
"Comment": "Click red hat dwarf (always shows up in the same location)"
}
]
"Z": -616.47974
},
"TerritoryId": 814,
- "InteractionType": "WaitForManualProgress",
+ "InteractionType": "Snipe",
"Comment": "Click red hat dwarf"
}
]
"Z": -414.38928
},
"TerritoryId": 818,
- "InteractionType": "WaitForManualProgress",
+ "InteractionType": "Snipe",
"Comment": "Click top left (broken) window",
"CompletionQuestVariablesFlags": [
null,
"Z": -161.45575
},
"TerritoryId": 814,
- "InteractionType": "WaitForManualProgress",
+ "InteractionType": "Snipe",
"Comment": "Help Master Chai dodge enemies"
}
]
"Z": -519.18823
},
"TerritoryId": 956,
- "InteractionType": "WaitForManualProgress",
+ "InteractionType": "Snipe",
"Comment": "Shoot Large Green Bird"
}
]
"Z": -654.13904
},
"TerritoryId": 959,
- "InteractionType": "WaitForManualProgress",
+ "InteractionType": "Snipe",
"Comment": "Find \"Runninway?\""
}
]
},
"StopDistance": 5,
"TerritoryId": 956,
- "InteractionType": "WaitForManualProgress",
+ "InteractionType": "Snipe",
"Comment": "Find Points of Interest"
}
]
"Z": 375.50916
},
"TerritoryId": 960,
- "InteractionType": "WaitForManualProgress",
+ "InteractionType": "Snipe",
"Comment": "Find Errant Omicron"
}
]
"Z": 398.42822
},
"TerritoryId": 960,
- "InteractionType": "WaitForManualProgress",
+ "InteractionType": "Snipe",
"Comment": "Identify Anomaly (Head, Elbow or Knee)"
}
]
"Z": 276.81384
},
"TerritoryId": 962,
- "InteractionType": "Instruction",
+ "InteractionType": "Snipe",
"Comment": "Click ewer, head and feet",
"AethernetShortcut": [
"[Old Sharlayan] Aetheryte Plaza",
"Z": -532.15845
},
"TerritoryId": 1188,
- "InteractionType": "WaitForManualProgress",
+ "InteractionType": "Snipe",
"Comment": "Inspect Eye, Carrying Pole and Tail",
"AetheryteShortcut": "Kozama'uka - Ok'hanu"
}
"Z": 343.7704
},
"TerritoryId": 1188,
- "InteractionType": "WaitForManualProgress",
+ "InteractionType": "Snipe",
"Comment": "Click (from left to right) worn tools, Kaahe, crafting materials, untouched meal"
}
]
"Z": 25.680908
},
"TerritoryId": 1185,
- "InteractionType": "WaitForManualProgress",
+ "InteractionType": "Snipe",
"Comment": "Inspect Helm, Corpse, Weapon"
}
]
"Z": -141.92426
},
"TerritoryId": 1190,
- "InteractionType": "Instruction",
+ "InteractionType": "Snipe",
"Comment": "Click (from left to right) pump, middle of the connecting pipes, barrels"
}
]
"Z": 557.7018
},
"TerritoryId": 1189,
- "InteractionType": "Instruction",
+ "InteractionType": "Snipe",
"Comment": "Inspect Flag, Red Head, Blue Head"
}
]
"Jump",
"Dive",
"Craft",
+ "Snipe",
"Instruction",
"AcceptQuest",
"CompleteQuest",
{ EInteractionType.Jump, "Jump" },
{ EInteractionType.Dive, "Dive" },
{ EInteractionType.Craft, "Craft" },
+ { EInteractionType.Snipe, "Snipe" },
{ EInteractionType.Instruction, "Instruction" },
{ EInteractionType.AcceptQuest, "AcceptQuest" },
{ EInteractionType.CompleteQuest, "CompleteQuest" },
Jump,
Dive,
Craft,
+ Snipe,
/// <summary>
/// Needs to be manually continued.
public bool HideInAllInstances { get; set; } = true;
public bool UseEscToCancelQuesting { get; set; } = true;
public bool ShowIncompleteSeasonalEvents { get; set; } = true;
+ public bool AutomaticallyCompleteSnipeTasks { get; set; }
}
internal sealed class AdvancedConfiguration
internal static class Interact
{
- internal sealed class Factory(GameFunctions gameFunctions, ICondition condition, ILoggerFactory loggerFactory)
+ internal sealed class Factory(GameFunctions gameFunctions, Configuration configuration, ICondition condition,
+ ILoggerFactory loggerFactory)
: ITaskFactory
{
public IEnumerable<ITask> CreateAllTasks(Quest quest, QuestSequence sequence, QuestStep step)
if (step.DataId == null)
yield break;
}
+ else if (step.InteractionType == EInteractionType.Snipe)
+ {
+ if (!configuration.General.AutomaticallyCompleteSnipeTasks)
+ yield break;
+ }
else if (step.InteractionType != EInteractionType.Interact)
yield break;
case EInteractionType.WaitForManualProgress:
case EInteractionType.Instruction:
+ case EInteractionType.Snipe:
return [new WaitNextStepOrSequence()];
case EInteractionType.Duty:
--- /dev/null
+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();
+ }
+}
using Questionable.Controller.Steps.Gathering;
using Questionable.Controller.Steps.Interactions;
using Questionable.Controller.Steps.Leves;
+using Questionable.Controller.Utils;
using Questionable.Data;
using Questionable.External;
using Questionable.Functions;
serviceCollection.AddSingleton<GameFunctions>();
serviceCollection.AddSingleton<ChatFunctions>();
serviceCollection.AddSingleton<QuestFunctions>();
+ serviceCollection.AddSingleton<AutoSnipeHandler>();
serviceCollection.AddSingleton<AetherCurrentData>();
serviceCollection.AddSingleton<AetheryteData>();
serviceProvider.GetRequiredService<LeveUiController>();
serviceProvider.GetRequiredService<QuestionableIpc>();
serviceProvider.GetRequiredService<DalamudInitializer>();
+ serviceProvider.GetRequiredService<AutoSnipeHandler>().Enable();
}
public void Dispose()
Save();
}
+ if (ImGui.CollapsingHeader("Cheats"))
+ {
+ bool automaticallyCompleteSnipeTasks = _configuration.General.AutomaticallyCompleteSnipeTasks;
+ if (ImGui.Checkbox("Automatically complete snipe tasks", ref automaticallyCompleteSnipeTasks))
+ {
+ _configuration.General.AutomaticallyCompleteSnipeTasks = automaticallyCompleteSnipeTasks;
+ Save();
+ }
+ }
+
ImGui.EndTabItem();
}
if (!isMinimized)
{
bool colored = currentStep is
- { InteractionType: EInteractionType.Instruction or EInteractionType.WaitForManualProgress };
+ { InteractionType: EInteractionType.Instruction or EInteractionType.WaitForManualProgress or EInteractionType.Snipe };
if (colored)
ImGui.PushStyleColor(ImGuiCol.Text, ImGuiColors.DalamudOrange);
ImGui.TextUnformatted(currentStep?.Comment ??