feat: add option to open examine window
This commit is contained in:
parent
2569318827
commit
23140a3377
|
@ -34,6 +34,8 @@ namespace PeepingTom {
|
||||||
public bool LogSelf { get; set; } = false;
|
public bool LogSelf { get; set; } = false;
|
||||||
|
|
||||||
public bool FocusTargetOnHover { get; set; } = true;
|
public bool FocusTargetOnHover { get; set; } = true;
|
||||||
|
public bool OpenExamine { get; set; } = false;
|
||||||
|
|
||||||
public bool PlaySoundOnTarget { get; set; } = false;
|
public bool PlaySoundOnTarget { get; set; } = false;
|
||||||
public string SoundPath { get; set; } = null;
|
public string SoundPath { get; set; } = null;
|
||||||
public float SoundVolume { get; set; } = 1f;
|
public float SoundVolume { get; set; } = 1f;
|
||||||
|
|
59
Peeping Tom/GameFunctions.cs
Normal file
59
Peeping Tom/GameFunctions.cs
Normal 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -64,6 +64,7 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Configuration.cs" />
|
<Compile Include="Configuration.cs" />
|
||||||
|
<Compile Include="GameFunctions.cs" />
|
||||||
<Compile Include="GlobalSuppressions.cs" />
|
<Compile Include="GlobalSuppressions.cs" />
|
||||||
<Compile Include="Plugin.cs" />
|
<Compile Include="Plugin.cs" />
|
||||||
<Compile Include="PluginUI.cs" />
|
<Compile Include="PluginUI.cs" />
|
||||||
|
|
|
@ -10,12 +10,14 @@ namespace PeepingTom {
|
||||||
internal Configuration Config { get; private set; }
|
internal Configuration Config { get; private set; }
|
||||||
internal PluginUI Ui { get; private set; }
|
internal PluginUI Ui { get; private set; }
|
||||||
internal TargetWatcher Watcher { get; private set; }
|
internal TargetWatcher Watcher { get; private set; }
|
||||||
|
internal GameFunctions GameFunctions { get; private set; }
|
||||||
|
|
||||||
public void Initialize(DalamudPluginInterface pluginInterface) {
|
public void Initialize(DalamudPluginInterface pluginInterface) {
|
||||||
this.Interface = pluginInterface ?? throw new ArgumentNullException(nameof(pluginInterface), "DalamudPluginInterface argument was null");
|
this.Interface = pluginInterface ?? throw new ArgumentNullException(nameof(pluginInterface), "DalamudPluginInterface argument was null");
|
||||||
this.Config = this.Interface.GetPluginConfig() as Configuration ?? new Configuration();
|
this.Config = this.Interface.GetPluginConfig() as Configuration ?? new Configuration();
|
||||||
this.Config.Initialize(this.Interface);
|
this.Config.Initialize(this.Interface);
|
||||||
this.Watcher = new TargetWatcher(this);
|
this.Watcher = new TargetWatcher(this);
|
||||||
|
this.GameFunctions = new GameFunctions(this);
|
||||||
this.Ui = new PluginUI(this);
|
this.Ui = new PluginUI(this);
|
||||||
|
|
||||||
this.Interface.CommandManager.AddHandler("/ppeepingtom", new CommandInfo(this.OnCommand) {
|
this.Interface.CommandManager.AddHandler("/ppeepingtom", new CommandInfo(this.OnCommand) {
|
||||||
|
|
|
@ -3,6 +3,7 @@ using Dalamud.Game.Chat.SeStringHandling;
|
||||||
using Dalamud.Game.Chat.SeStringHandling.Payloads;
|
using Dalamud.Game.Chat.SeStringHandling.Payloads;
|
||||||
using Dalamud.Game.ClientState;
|
using Dalamud.Game.ClientState;
|
||||||
using Dalamud.Game.ClientState.Actors.Types;
|
using Dalamud.Game.ClientState.Actors.Types;
|
||||||
|
using Dalamud.Plugin;
|
||||||
using ImGuiNET;
|
using ImGuiNET;
|
||||||
using NAudio.Wave;
|
using NAudio.Wave;
|
||||||
using System;
|
using System;
|
||||||
|
@ -89,8 +90,7 @@ namespace PeepingTom {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ShowSettings() {
|
private void ShowSettings() {
|
||||||
// 700x250 if setting a size
|
ImGui.SetNextWindowSize(new Vector2(700, 250));
|
||||||
ImGui.SetNextWindowSize(new Vector2(700, 275));
|
|
||||||
if (ImGui.Begin($"{this.plugin.Name} settings", ref this._settingsOpen, ImGuiWindowFlags.NoResize)) {
|
if (ImGui.Begin($"{this.plugin.Name} settings", ref this._settingsOpen, ImGuiWindowFlags.NoResize)) {
|
||||||
if (ImGui.BeginTabBar("##settings-tabs")) {
|
if (ImGui.BeginTabBar("##settings-tabs")) {
|
||||||
if (ImGui.BeginTabItem("Markers")) {
|
if (ImGui.BeginTabItem("Markers")) {
|
||||||
|
@ -172,6 +172,16 @@ namespace PeepingTom {
|
||||||
this.plugin.Config.Save();
|
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;
|
bool playSound = this.plugin.Config.PlaySoundOnTarget;
|
||||||
if (ImGui.Checkbox("Play sound when targeted", ref playSound)) {
|
if (ImGui.Checkbox("Play sound when targeted", ref playSound)) {
|
||||||
this.plugin.Config.PlaySoundOnTarget = playSound;
|
this.plugin.Config.PlaySoundOnTarget = playSound;
|
||||||
|
@ -211,7 +221,7 @@ namespace PeepingTom {
|
||||||
|
|
||||||
ImGui.Separator();
|
ImGui.Separator();
|
||||||
|
|
||||||
for (int deviceNum = -1; deviceNum < WaveOut.DeviceCount; deviceNum++) {
|
for (int deviceNum = 0; deviceNum < WaveOut.DeviceCount; deviceNum++) {
|
||||||
var caps = WaveOut.GetCapabilities(deviceNum);
|
var caps = WaveOut.GetCapabilities(deviceNum);
|
||||||
if (ImGui.Selectable(caps.ProductName)) {
|
if (ImGui.Selectable(caps.ProductName)) {
|
||||||
this.plugin.Config.SoundDevice = deviceNum;
|
this.plugin.Config.SoundDevice = deviceNum;
|
||||||
|
@ -404,10 +414,16 @@ namespace PeepingTom {
|
||||||
ImGui.SetNextWindowSize(new Vector2(290, 195), ImGuiCond.FirstUseEver);
|
ImGui.SetNextWindowSize(new Vector2(290, 195), ImGuiCond.FirstUseEver);
|
||||||
if (ImGui.Begin(this.plugin.Name, ref this._wantsOpen, flags)) {
|
if (ImGui.Begin(this.plugin.Name, ref this._wantsOpen, flags)) {
|
||||||
ImGui.Text("Targeting you");
|
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;
|
float height = ImGui.GetContentRegionAvail().Y;
|
||||||
|
height -= ImGui.GetStyle().ItemSpacing.Y;
|
||||||
|
|
||||||
height -= ImGui.CalcTextSize(string.Empty).Y + ImGui.GetStyle().ItemSpacing.Y;
|
|
||||||
bool anyHovered = false;
|
bool anyHovered = false;
|
||||||
if (ImGui.ListBoxHeader("##targeting", new Vector2(-1, height))) {
|
if (ImGui.ListBoxHeader("##targeting", new Vector2(-1, height))) {
|
||||||
// add the two first players for testing
|
// add the two first players for testing
|
||||||
|
@ -447,11 +463,21 @@ namespace PeepingTom {
|
||||||
}
|
}
|
||||||
this.previousFocus = new Optional<Actor>();
|
this.previousFocus = new Optional<Actor>();
|
||||||
}
|
}
|
||||||
ImGui.Text("Click to link or right click to target.");
|
|
||||||
ImGui.End();
|
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) {
|
private void AddEntry(Targeter targeter, Actor actor, ref bool anyHovered, ImGuiSelectableFlags flags = ImGuiSelectableFlags.None) {
|
||||||
ImGui.Selectable(targeter.Name, false, flags);
|
ImGui.Selectable(targeter.Name, false, flags);
|
||||||
bool hover = ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled);
|
bool hover = ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled);
|
||||||
|
@ -477,11 +503,26 @@ namespace PeepingTom {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (left) {
|
if (left) {
|
||||||
PlayerPayload payload = new PlayerPayload(this.plugin.Interface.Data, targeter.Name, targeter.HomeWorld.Id);
|
if (this.plugin.Config.OpenExamine && ImGui.GetIO().KeyAlt) {
|
||||||
Payload[] payloads = { payload };
|
if (actor != null) {
|
||||||
this.plugin.Interface.Framework.Gui.Chat.PrintChat(new XivChatEntry {
|
this.plugin.GameFunctions.OpenExamineWindow(actor);
|
||||||
MessageBytes = new SeString(payloads).Encode()
|
} 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) {
|
} else if (right && actor != null) {
|
||||||
this.plugin.Interface.ClientState.Targets.SetCurrentTarget(actor);
|
this.plugin.Interface.ClientState.Targets.SetCurrentTarget(actor);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user