feat: add option to open examine window

This commit is contained in:
Anna 2020-08-26 08:20:01 -04:00
parent 2569318827
commit 23140a3377
5 changed files with 115 additions and 10 deletions

View File

@ -34,6 +34,8 @@ namespace PeepingTom {
public bool LogSelf { get; set; } = false;
public bool FocusTargetOnHover { get; set; } = true;
public bool OpenExamine { get; set; } = false;
public bool PlaySoundOnTarget { get; set; } = false;
public string SoundPath { get; set; } = null;
public float SoundVolume { get; set; } = 1f;

View File

@ -0,0 +1,59 @@
using Dalamud.Game.ClientState.Actors.Types;
using Dalamud.Plugin;
using System;
using System.Linq;
using System.Runtime.InteropServices;
namespace PeepingTom {
public class GameFunctions {
private delegate IntPtr GetListDelegate(IntPtr basePtr);
private delegate long RequestCharInfoDelegate(IntPtr ptr);
private readonly PeepingTomPlugin plugin;
private readonly RequestCharInfoDelegate _requestCharInfo = null;
public GameFunctions(PeepingTomPlugin plugin) {
this.plugin = plugin ?? throw new ArgumentNullException(nameof(plugin), "PeepingTomPlugin cannot be null");
IntPtr rciPtr = this.plugin.Interface.TargetModuleScanner.ScanText("48 89 5C 24 ?? 57 48 83 EC 40 BA 1B 01 00 00");
if (rciPtr == IntPtr.Zero) {
PluginLog.Log("Could not find the signature for the examine window function - will not be able to open examine window.");
return;
}
this._requestCharInfo = Marshal.GetDelegateForFunctionPointer<RequestCharInfoDelegate>(rciPtr);
}
private static IntPtr FollowPtrChain(IntPtr start, int[] offsets) {
foreach (int offset in offsets) {
start = Marshal.ReadIntPtr(start, offset);
if (start == IntPtr.Zero) {
break;
}
}
return start;
}
public void OpenExamineWindow(Actor actor) {
if (this._requestCharInfo == null) {
return;
}
IntPtr framework = this.plugin.Interface.Framework.Address.BaseAddress;
IntPtr getListPtr = FollowPtrChain(framework, new int[] { 0x29f8, 0, 0x110 });
var getList = Marshal.GetDelegateForFunctionPointer<GetListDelegate>(getListPtr);
IntPtr list = getList(Marshal.ReadIntPtr(framework + 0x29f8));
IntPtr rciData = Marshal.ReadIntPtr(list + 0x188);
Marshal.WriteInt32(rciData + 0x28, actor.ActorId);
Marshal.WriteInt32(rciData + 0x2c, actor.ActorId);
Marshal.WriteInt32(rciData + 0x30, actor.ActorId);
this._requestCharInfo(rciData);
}
}
}

View File

@ -64,6 +64,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Configuration.cs" />
<Compile Include="GameFunctions.cs" />
<Compile Include="GlobalSuppressions.cs" />
<Compile Include="Plugin.cs" />
<Compile Include="PluginUI.cs" />

View File

@ -10,12 +10,14 @@ namespace PeepingTom {
internal Configuration Config { get; private set; }
internal PluginUI Ui { get; private set; }
internal TargetWatcher Watcher { get; private set; }
internal GameFunctions GameFunctions { get; private set; }
public void Initialize(DalamudPluginInterface pluginInterface) {
this.Interface = pluginInterface ?? throw new ArgumentNullException(nameof(pluginInterface), "DalamudPluginInterface argument was null");
this.Config = this.Interface.GetPluginConfig() as Configuration ?? new Configuration();
this.Config.Initialize(this.Interface);
this.Watcher = new TargetWatcher(this);
this.GameFunctions = new GameFunctions(this);
this.Ui = new PluginUI(this);
this.Interface.CommandManager.AddHandler("/ppeepingtom", new CommandInfo(this.OnCommand) {

View File

@ -3,6 +3,7 @@ using Dalamud.Game.Chat.SeStringHandling;
using Dalamud.Game.Chat.SeStringHandling.Payloads;
using Dalamud.Game.ClientState;
using Dalamud.Game.ClientState.Actors.Types;
using Dalamud.Plugin;
using ImGuiNET;
using NAudio.Wave;
using System;
@ -89,8 +90,7 @@ namespace PeepingTom {
}
private void ShowSettings() {
// 700x250 if setting a size
ImGui.SetNextWindowSize(new Vector2(700, 275));
ImGui.SetNextWindowSize(new Vector2(700, 250));
if (ImGui.Begin($"{this.plugin.Name} settings", ref this._settingsOpen, ImGuiWindowFlags.NoResize)) {
if (ImGui.BeginTabBar("##settings-tabs")) {
if (ImGui.BeginTabItem("Markers")) {
@ -172,6 +172,16 @@ namespace PeepingTom {
this.plugin.Config.Save();
}
bool openExamine = this.plugin.Config.OpenExamine;
if (ImGui.Checkbox("Open examine window on Alt-click", ref openExamine)) {
this.plugin.Config.OpenExamine = openExamine;
this.plugin.Config.Save();
}
ImGui.EndTabItem();
}
if (ImGui.BeginTabItem("Sound")) {
bool playSound = this.plugin.Config.PlaySoundOnTarget;
if (ImGui.Checkbox("Play sound when targeted", ref playSound)) {
this.plugin.Config.PlaySoundOnTarget = playSound;
@ -211,7 +221,7 @@ namespace PeepingTom {
ImGui.Separator();
for (int deviceNum = -1; deviceNum < WaveOut.DeviceCount; deviceNum++) {
for (int deviceNum = 0; deviceNum < WaveOut.DeviceCount; deviceNum++) {
var caps = WaveOut.GetCapabilities(deviceNum);
if (ImGui.Selectable(caps.ProductName)) {
this.plugin.Config.SoundDevice = deviceNum;
@ -404,10 +414,16 @@ namespace PeepingTom {
ImGui.SetNextWindowSize(new Vector2(290, 195), ImGuiCond.FirstUseEver);
if (ImGui.Begin(this.plugin.Name, ref this._wantsOpen, flags)) {
ImGui.Text("Targeting you");
ImGui.SameLine();
if (this.plugin.Config.OpenExamine) {
HelpMarker("Click to link, Alt-click to examine, or right click to target.");
} else {
HelpMarker("Click to link or right click to target.");
}
float height = ImGui.GetContentRegionAvail().Y;
height -= ImGui.GetStyle().ItemSpacing.Y;
height -= ImGui.CalcTextSize(string.Empty).Y + ImGui.GetStyle().ItemSpacing.Y;
bool anyHovered = false;
if (ImGui.ListBoxHeader("##targeting", new Vector2(-1, height))) {
// add the two first players for testing
@ -447,11 +463,21 @@ namespace PeepingTom {
}
this.previousFocus = new Optional<Actor>();
}
ImGui.Text("Click to link or right click to target.");
ImGui.End();
}
}
private static void HelpMarker(string text) {
ImGui.TextDisabled("(?)");
if (ImGui.IsItemHovered()) {
ImGui.BeginTooltip();
ImGui.PushTextWrapPos(ImGui.GetFontSize() * 20f);
ImGui.TextUnformatted(text);
ImGui.PopTextWrapPos();
ImGui.EndTooltip();
}
}
private void AddEntry(Targeter targeter, Actor actor, ref bool anyHovered, ImGuiSelectableFlags flags = ImGuiSelectableFlags.None) {
ImGui.Selectable(targeter.Name, false, flags);
bool hover = ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled);
@ -477,11 +503,26 @@ namespace PeepingTom {
}
if (left) {
PlayerPayload payload = new PlayerPayload(this.plugin.Interface.Data, targeter.Name, targeter.HomeWorld.Id);
Payload[] payloads = { payload };
this.plugin.Interface.Framework.Gui.Chat.PrintChat(new XivChatEntry {
MessageBytes = new SeString(payloads).Encode()
});
if (this.plugin.Config.OpenExamine && ImGui.GetIO().KeyAlt) {
if (actor != null) {
this.plugin.GameFunctions.OpenExamineWindow(actor);
} else {
Payload[] payloads = {
new TextPayload($"[{this.plugin.Name}] "),
new PlayerPayload(this.plugin.Interface.Data, targeter.Name, targeter.HomeWorld.Id),
new TextPayload(" is not close enough to examine."),
};
this.plugin.Interface.Framework.Gui.Chat.PrintChat(new XivChatEntry {
MessageBytes = new SeString(payloads).Encode(),
});
}
} else {
PlayerPayload payload = new PlayerPayload(this.plugin.Interface.Data, targeter.Name, targeter.HomeWorld.Id);
Payload[] payloads = { payload };
this.plugin.Interface.Framework.Gui.Chat.PrintChat(new XivChatEntry {
MessageBytes = new SeString(payloads).Encode(),
});
}
} else if (right && actor != null) {
this.plugin.Interface.ClientState.Targets.SetCurrentTarget(actor);
}