diff --git a/XivCommon/Functions/Examine.cs b/XivCommon/Functions/Examine.cs
new file mode 100755
index 0000000..d7f25a3
--- /dev/null
+++ b/XivCommon/Functions/Examine.cs
@@ -0,0 +1,69 @@
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using Dalamud.Game;
+using Dalamud.Game.ClientState.Actors.Types;
+
+namespace XivCommon.Functions {
+ ///
+ /// Class containing examine functions
+ ///
+ public class Examine {
+ private GameFunctions Functions { get; }
+
+ private delegate IntPtr GetListDelegate(IntPtr basePtr);
+
+ private delegate long RequestCharInfoDelegate(IntPtr ptr);
+
+ private RequestCharInfoDelegate RequestCharacterInfo { get; }
+
+ internal Examine(GameFunctions functions, SigScanner scanner) {
+ this.Functions = functions;
+
+ // got this by checking what accesses rciData below
+ var rciPtr = scanner.ScanText("48 89 5C 24 ?? 57 48 83 EC 40 BA ?? ?? ?? ?? 48 8B D9 E8 ?? ?? ?? ?? 48 8B F8 48 85 C0 74 16");
+ this.RequestCharacterInfo = Marshal.GetDelegateForFunctionPointer(rciPtr);
+ }
+
+ private static IntPtr FollowPtrChain(IntPtr start, IEnumerable offsets) {
+ foreach (var offset in offsets) {
+ start = Marshal.ReadIntPtr(start, offset);
+ if (start == IntPtr.Zero) {
+ break;
+ }
+ }
+
+ return start;
+ }
+
+ ///
+ /// Opens the Examine window for the specified actor.
+ ///
+ /// Actor to open window for
+ public void OpenExamineWindow(Actor actor) {
+ // NOTES LAST UPDATED: 5.45
+
+ // offsets and stuff come from the beginning of case 0x2c (around line 621 in IDA)
+ // if 29f8 ever changes, I'd just scan for it in old binary and find what it is in the new binary at the same spot
+ // 40 55 53 57 41 54 41 55 41 56 48 8D 6C 24 ??
+ var uiModule = this.Functions.GetUiModule();
+ var getListPtr = FollowPtrChain(uiModule, new[] {0, 0x110});
+ var getList = Marshal.GetDelegateForFunctionPointer(getListPtr);
+ var list = getList(uiModule);
+ var rciData = Marshal.ReadIntPtr(list + 0x1A0);
+
+ unsafe {
+ // offsets at sig E8 ?? ?? ?? ?? 33 C0 EB 4C
+ // this is called at the end of the 2c case
+ var raw = (int*) rciData;
+ *(raw + 10) = actor.ActorId;
+ *(raw + 11) = actor.ActorId;
+ *(raw + 12) = actor.ActorId;
+ *(raw + 13) = -536870912;
+ *(raw + 311) = 0;
+ }
+
+ this.RequestCharacterInfo(rciData);
+ }
+ }
+}
diff --git a/XivCommon/GameFunctions.cs b/XivCommon/GameFunctions.cs
index f412790..b0d39ed 100755
--- a/XivCommon/GameFunctions.cs
+++ b/XivCommon/GameFunctions.cs
@@ -23,12 +23,18 @@ namespace XivCommon {
/// BattleTalk functions and events
///
public BattleTalk BattleTalk { get; }
+ ///
+ /// Examine functions
+ ///
+ public Examine Examine { get; }
internal GameFunctions(Hooks hooks, DalamudPluginInterface @interface) {
this.Interface = @interface;
+
this.Chat = new Chat(this, @interface.TargetModuleScanner);
this.PartyFinder = new PartyFinder(@interface.TargetModuleScanner, hooks.HasFlag(Hooks.PartyFinder));
this.BattleTalk = new BattleTalk(this, @interface.TargetModuleScanner, @interface.SeStringManager, hooks.HasFlag(Hooks.BattleTalk));
+ this.Examine = new Examine(this, @interface.TargetModuleScanner);
}
///