diff --git a/Globetrotter/Configuration.cs b/Globetrotter/Configuration.cs
index bf7ad04..58298bb 100644
--- a/Globetrotter/Configuration.cs
+++ b/Globetrotter/Configuration.cs
@@ -5,19 +5,20 @@ using System;
namespace Globetrotter {
[Serializable]
internal class Configuration : IPluginConfiguration {
- private DalamudPluginInterface _pi;
+ private DalamudPluginInterface Plugin { get; set; } = null!;
public int Version { get; set; } = 1;
public bool ShowOnHover { get; set; } = true;
+ public bool ShowOnDecipher { get; set; } = true;
public bool ShowOnOpen { get; set; } = true;
public void Initialize(DalamudPluginInterface pi) {
- this._pi = pi ?? throw new ArgumentNullException(nameof(pi), "DalamudPluginInterface cannot be null");
+ this.Plugin = pi ?? throw new ArgumentNullException(nameof(pi), "DalamudPluginInterface cannot be null");
}
public void Save() {
- this._pi.SavePluginConfig(this);
+ this.Plugin.SavePluginConfig(this);
}
}
}
diff --git a/Globetrotter/Globetrotter.csproj b/Globetrotter/Globetrotter.csproj
index f8f2753..d7e54b0 100755
--- a/Globetrotter/Globetrotter.csproj
+++ b/Globetrotter/Globetrotter.csproj
@@ -4,6 +4,7 @@
1.1.4
net48
latest
+ enable
@@ -28,6 +29,6 @@
-
+
diff --git a/Globetrotter/PluginUi.cs b/Globetrotter/PluginUi.cs
index ef60727..32278c6 100644
--- a/Globetrotter/PluginUi.cs
+++ b/Globetrotter/PluginUi.cs
@@ -1,5 +1,6 @@
using ImGuiNET;
using System;
+using System.Numerics;
namespace Globetrotter {
internal class PluginUi {
@@ -25,28 +26,52 @@ namespace Globetrotter {
return;
}
+ ImGui.SetNextWindowSize(new Vector2(350, 250), ImGuiCond.FirstUseEver);
+
if (!ImGui.Begin("Globetrotter settings", ref this._displaySettings)) {
+ ImGui.End();
return;
}
ImGui.TextUnformatted("Use /tmap to open your current treasure map.");
- ImGui.TextUnformatted("If you have a map and this plugin isn't working, change zone.");
+
+ ImGui.Separator();
+
+ var showOnDecipher = this.Config.ShowOnDecipher;
+ if (HelpCheckbox("Show on decipher", "Open the map with a flag set after deciphering a map.", ref showOnDecipher)) {
+ this.Config.ShowOnDecipher = showOnDecipher;
+ this.Config.Save();
+ }
+
+ ImGui.Separator();
+
+ var showOnOpen = this.Config.ShowOnOpen;
+ if (HelpCheckbox("Show on open", "Open the map with a flag set instead of the normal treasure map window.", ref showOnOpen)) {
+ this.Config.ShowOnOpen = showOnOpen;
+ this.Config.Save();
+ }
ImGui.Separator();
var showOnHover = this.Config.ShowOnHover;
- if (ImGui.Checkbox("Show on hover", ref showOnHover)) {
+ if (HelpCheckbox("Show on hover", "Open the map with a flag set when hovering over a deciphered map.", ref showOnHover)) {
this.Config.ShowOnHover = showOnHover;
this.Config.Save();
}
- var showOnOpen = this.Config.ShowOnOpen;
- if (ImGui.Checkbox("Show on open", ref showOnOpen)) {
- this.Config.ShowOnOpen = showOnOpen;
- this.Config.Save();
- }
-
ImGui.End();
}
+
+ private static bool HelpCheckbox(string label, string help, ref bool isChecked) {
+ var ret = ImGui.Checkbox(label, ref isChecked);
+
+ ImGui.TreePush();
+ ImGui.PushTextWrapPos();
+ ImGui.TextUnformatted(help);
+ ImGui.PopTextWrapPos();
+ ImGui.TreePop();
+
+ return ret;
+ }
}
}
diff --git a/Globetrotter/TreasureMaps.cs b/Globetrotter/TreasureMaps.cs
index c6cdcea..18df6f6 100644
--- a/Globetrotter/TreasureMaps.cs
+++ b/Globetrotter/TreasureMaps.cs
@@ -3,6 +3,7 @@ using Dalamud.Plugin;
using Lumina.Excel.GeneratedSheets;
using System;
using System.Collections.Generic;
+using System.Linq;
using System.Runtime.InteropServices;
using Dalamud.Game.Text.SeStringHandling.Payloads;
@@ -10,7 +11,7 @@ namespace Globetrotter {
internal sealed class TreasureMaps : IDisposable {
private const uint TreasureMapsCode = 0x54;
- private static Dictionary _mapToRow;
+ private static Dictionary? _mapToRow;
private Dictionary MapToRow {
get {
@@ -26,7 +27,7 @@ namespace Globetrotter {
continue;
}
- EventItem opened;
+ EventItem? opened;
// FIXME: remove this try/catch when lumina is fixed
try {
opened = rank.KeyItemName.Value;
@@ -49,24 +50,31 @@ namespace Globetrotter {
private DalamudPluginInterface Interface { get; }
private Configuration Config { get; }
- private TreasureMapPacket _lastMap;
+ private TreasureMapPacket? _lastMap;
private delegate char HandleActorControlSelfDelegate(long a1, long a2, IntPtr dataPtr);
+ private delegate IntPtr ShowTreasureMapDelegate(IntPtr manager, ushort rowId, ushort subRowId, byte a4);
+
private readonly Hook _acsHook;
+ private readonly Hook _showMapHook;
public TreasureMaps(DalamudPluginInterface pi, Configuration config) {
this.Interface = pi ?? throw new ArgumentNullException(nameof(pi), "DalamudPluginInterface cannot be null");
this.Config = config ?? throw new ArgumentNullException(nameof(config), "Configuration cannot be null");
- var delegatePtr = this.Interface.TargetModuleScanner.ScanText("48 89 5C 24 ?? 48 89 74 24 ?? 57 48 83 EC 30 48 8B D9 49 8B F8 41 0F B7 08");
- if (delegatePtr == IntPtr.Zero) {
- PluginLog.Log("Unable to detect treasure maps because could not find ACS handler delegate");
- return;
- }
-
- this._acsHook = new Hook(delegatePtr, new HandleActorControlSelfDelegate(this.OnACS));
+ var acsPtr = this.Interface.TargetModuleScanner.ScanText("48 89 5C 24 ?? 48 89 74 24 ?? 57 48 83 EC 30 48 8B D9 49 8B F8 41 0F B7 08");
+ this._acsHook = new Hook(acsPtr, new HandleActorControlSelfDelegate(this.OnACS));
this._acsHook.Enable();
+
+ var showMapPtr = this.Interface.TargetModuleScanner.ScanText("E8 ?? ?? ?? ?? 40 84 FF 0F 85 ?? ?? ?? ?? 48 8B 0D ?? ?? ?? ??");
+ this._showMapHook = new Hook(showMapPtr, new ShowTreasureMapDelegate(this.OnShowMap));
+ this._showMapHook.Enable();
+ }
+
+ public void Dispose() {
+ this._acsHook.Dispose();
+ this._showMapHook.Dispose();
}
public void OnHover(object sender, ulong id) {
@@ -77,6 +85,36 @@ namespace Globetrotter {
this.OpenMapLocation();
}
+ private IntPtr OnShowMap(IntPtr manager, ushort rowId, ushort subRowId, byte a4) {
+ try {
+ if (!this.OnShowMapInner(rowId, subRowId)) {
+ return IntPtr.Zero;
+ }
+ } catch (Exception ex) {
+ PluginLog.LogError(ex, "Exception on show map");
+ }
+
+ return this._showMapHook.Original(manager, rowId, subRowId, a4);
+ }
+
+ private bool OnShowMapInner(ushort rowId, ushort subRowId) {
+ if (this._lastMap == null) {
+ try {
+ var eventItemId = this.MapToRow.First(entry => entry.Value == rowId);
+ this._lastMap = new TreasureMapPacket(eventItemId.Key, subRowId, false);
+ } catch (InvalidOperationException) {
+ // no-op
+ }
+ }
+
+ if (!this.Config.ShowOnOpen && (!this.Config.ShowOnDecipher || this._lastMap?.JustOpened != true)) {
+ return true;
+ }
+
+ this.OpenMapLocation();
+ return false;
+ }
+
private char OnACS(long a1, long a2, IntPtr dataPtr) {
try {
this.OnACSInner(dataPtr);
@@ -94,10 +132,6 @@ namespace Globetrotter {
}
this._lastMap = packet;
-
- if (this.Config.ShowOnOpen && packet.JustOpened) {
- this.OpenMapLocation();
- }
}
public void OpenMapLocation() {
@@ -132,9 +166,13 @@ namespace Globetrotter {
);
this.Interface.Framework.Gui.OpenMapWithMapLink(mapLink);
+
+ if (this._lastMap != null) {
+ this._lastMap.JustOpened = false;
+ }
}
- private static TreasureMapPacket ParsePacket(IntPtr dataPtr) {
+ private static TreasureMapPacket? ParsePacket(IntPtr dataPtr) {
uint category = Marshal.ReadByte(dataPtr);
if (category != TreasureMapsCode) {
return null;
@@ -169,16 +207,12 @@ namespace Globetrotter {
val *= c;
return (41f / c * ((val + 1024f) / 2048f)) + 1;
}
-
- public void Dispose() {
- this._acsHook?.Dispose();
- }
}
internal class TreasureMapPacket {
public uint EventItemId { get; }
public uint SubRowId { get; }
- public bool JustOpened { get; }
+ public bool JustOpened { get; set; }
public TreasureMapPacket(uint eventItemId, uint subRowId, bool justOpened) {
this.EventItemId = eventItemId;