using System; using System.Runtime.InteropServices; using Dalamud.Game; using FFXIVClientStructs.FFXIV.Client.UI.Agent; using Lumina.Excel.GeneratedSheets; using Framework = FFXIVClientStructs.FFXIV.Client.System.Framework.Framework; namespace XivCommon.Functions { /// /// Duty Finder functions /// public class DutyFinder { private static class Signatures { internal const string OpenRegularDuty = "48 89 6C 24 ?? 48 89 74 24 ?? 57 48 81 EC ?? ?? ?? ?? 48 8B F9 41 0F B6 E8"; internal const string OpenRoulette = "E9 ?? ?? ?? ?? 8B 93 ?? ?? ?? ?? 48 83 C4 20"; } private delegate IntPtr OpenDutyDelegate(IntPtr agent, uint contentFinderCondition, byte a3); private delegate IntPtr OpenRouletteDelegate(IntPtr agent, byte roulette, byte a3); private readonly OpenDutyDelegate? _openDuty; private readonly OpenRouletteDelegate? _openRoulette; internal DutyFinder(SigScanner scanner) { if (scanner.TryScanText(Signatures.OpenRegularDuty, out var openDutyPtr, "Duty Finder (open duty)")) { this._openDuty = Marshal.GetDelegateForFunctionPointer(openDutyPtr); } if (scanner.TryScanText(Signatures.OpenRoulette, out var openRoulettePtr, "Duty Finder (open roulette)")) { this._openRoulette = Marshal.GetDelegateForFunctionPointer(openRoulettePtr); } } /// /// Opens the Duty Finder to the given duty. /// /// duty to show /// if the open duty function could not be found in memory public void OpenDuty(ContentFinderCondition condition) { this.OpenDuty(condition.RowId); } /// /// Opens the Duty Finder to the given duty ID. /// /// ID of duty to show /// if the open duty function could not be found in memory public unsafe void OpenDuty(uint contentFinderCondition) { if (this._openDuty == null) { throw new InvalidOperationException("Could not find signature for open duty function"); } var agent = (IntPtr) Framework.Instance()->GetUiModule()->GetAgentModule()->GetAgentByInternalId(AgentId.ContentsFinder); this._openDuty(agent, contentFinderCondition, 0); } /// /// Opens the Duty Finder to the given roulette. /// /// roulette to show public void OpenRoulette(ContentRoulette roulette) { this.OpenRoulette((byte) roulette.RowId); } /// /// Opens the Duty Finder to the given roulette ID. /// /// ID of roulette to show public unsafe void OpenRoulette(byte roulette) { if (this._openRoulette == null) { throw new InvalidOperationException("Could not find signature for open roulette function"); } var agent = (IntPtr) Framework.Instance()->GetUiModule()->GetAgentModule()->GetAgentByInternalId(AgentId.ContentsFinder); this._openRoulette(agent, roulette, 0); } } }