84 lines
3.4 KiB
C#
Executable File
84 lines
3.4 KiB
C#
Executable File
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;
|
|
|
|
/// <summary>
|
|
/// Journal functions
|
|
/// </summary>
|
|
public class Journal {
|
|
private static class Signatures {
|
|
internal const string OpenQuest = "E8 ?? ?? ?? ?? 48 8B 74 24 ?? 48 8B 7C 24 ?? 48 83 C4 30 5B C3 48 8B CB";
|
|
internal const string IsQuestCompleted = "E8 ?? ?? ?? ?? 41 88 84 2C";
|
|
}
|
|
|
|
private delegate IntPtr OpenQuestDelegate(IntPtr agent, int questId, int a3, ushort a4, byte a5);
|
|
|
|
private delegate byte IsQuestCompletedDelegate(ushort questId);
|
|
|
|
private readonly OpenQuestDelegate? _openQuest;
|
|
private readonly IsQuestCompletedDelegate? _isQuestCompleted;
|
|
|
|
internal Journal(ISigScanner scanner) {
|
|
if (scanner.TryScanText(Signatures.OpenQuest, out var openQuestPtr, "Journal (open quest)")) {
|
|
this._openQuest = Marshal.GetDelegateForFunctionPointer<OpenQuestDelegate>(openQuestPtr);
|
|
}
|
|
|
|
if (scanner.TryScanText(Signatures.IsQuestCompleted, out var questCompletedPtr, "Journal (quest completed)")) {
|
|
this._isQuestCompleted = Marshal.GetDelegateForFunctionPointer<IsQuestCompletedDelegate>(questCompletedPtr);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Opens the quest journal to the given quest.
|
|
/// </summary>
|
|
/// <param name="quest">quest to show</param>
|
|
/// <exception cref="InvalidOperationException">if the open quest function could not be found in memory</exception>
|
|
public void OpenQuest(Quest quest) {
|
|
this.OpenQuest(quest.RowId);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Opens the quest journal to the given quest ID.
|
|
/// </summary>
|
|
/// <param name="questId">ID of quest to show</param>
|
|
/// <exception cref="InvalidOperationException">if the open quest function could not be found in memory</exception>
|
|
public unsafe void OpenQuest(uint questId) {
|
|
if (this._openQuest == null) {
|
|
throw new InvalidOperationException("Could not find signature for open quest function");
|
|
}
|
|
|
|
var agent = (IntPtr) Framework.Instance()->GetUiModule()->GetAgentModule()->GetAgentByInternalId(AgentId.Journal);
|
|
|
|
this._openQuest(agent, (int) (questId & 0xFFFF), 1, 0, 1);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Checks if the given quest is completed.
|
|
/// </summary>
|
|
/// <param name="quest">quest to check</param>
|
|
/// <returns>true if the quest is completed</returns>
|
|
/// <exception cref="InvalidOperationException">if the function for checking quest completion could not be found in memory</exception>
|
|
public bool IsQuestCompleted(Quest quest) {
|
|
return this.IsQuestCompleted(quest.RowId);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Checks if the given quest ID is completed.
|
|
/// </summary>
|
|
/// <param name="questId">ID of quest to check</param>
|
|
/// <returns>true if the quest is completed</returns>
|
|
/// <exception cref="InvalidOperationException">if the function for checking quest completion could not be found in memory</exception>
|
|
public bool IsQuestCompleted(uint questId) {
|
|
if (this._isQuestCompleted == null) {
|
|
throw new InvalidOperationException("Could not find signature for quest completed function");
|
|
}
|
|
|
|
return this._isQuestCompleted((ushort) (questId & 0xFFFF)) != 0;
|
|
}
|
|
}
|