Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1744943e75 | |||
| 448d3ca933 | |||
| 611e61967b |
@@ -2,6 +2,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
using Dalamud.Game.ClientState.Conditions;
|
using Dalamud.Game.ClientState.Conditions;
|
||||||
using Dalamud.Hooking;
|
using Dalamud.Hooking;
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
@@ -27,8 +28,12 @@ public unsafe class IntegrationsController : IDisposable
|
|||||||
private bool _wasBetweenAreas;
|
private bool _wasBetweenAreas;
|
||||||
private int _lastQuestCount = -1;
|
private int _lastQuestCount = -1;
|
||||||
private int _lastTempMarkerCount = -1;
|
private int _lastTempMarkerCount = -1;
|
||||||
/// <summary>Snapshot of (QuestId, Sequence) for each active quest; when this changes we refresh so markers update (e.g. multi-step objective).</summary>
|
/// <summary>Snapshot of (QuestId, Sequence, variables) for each active quest; when this changes we refresh so markers update (e.g. multi-step objective).</summary>
|
||||||
private string _lastQuestSequenceSnapshot = string.Empty;
|
private string _lastQuestSequenceSnapshot = string.Empty;
|
||||||
|
/// <summary>Snapshot of temp marker positions; when this changes we refresh so quest area circles update (e.g. marker moved from 1/3 to 2/3 location).</summary>
|
||||||
|
private string _lastTempMarkerSnapshot = string.Empty;
|
||||||
|
/// <summary>True on the previous frame if player was in NPC or quest dialogue (Occupied / OccupiedInQuestEvent). Used to refresh minimap when dialogue ends (e.g. after speaking to quest NPC with no step counter).</summary>
|
||||||
|
private bool _wasInQuestOrNpcDialogue;
|
||||||
private bool _refreshedDuringLoad;
|
private bool _refreshedDuringLoad;
|
||||||
/// <summary>When true, request a silent refresh on the next framework update (e.g. after plugin load).</summary>
|
/// <summary>When true, request a silent refresh on the next framework update (e.g. after plugin load).</summary>
|
||||||
private bool _requestRefreshOnLoad = true;
|
private bool _requestRefreshOnLoad = true;
|
||||||
@@ -110,9 +115,9 @@ public unsafe class IntegrationsController : IDisposable
|
|||||||
try { AgentMap.Instance()->Hide(); } catch { }
|
try { AgentMap.Instance()->Hide(); } catch { }
|
||||||
SilentRefreshInProgress = false;
|
SilentRefreshInProgress = false;
|
||||||
}
|
}
|
||||||
|
// Do NOT update quest/temp baselines here: if the user accepts a quest or advances a step during
|
||||||
|
// these frames, we would overwrite the baseline and never trigger a refresh for that change.
|
||||||
_wasBetweenAreas = Service.Condition.IsBetweenAreas();
|
_wasBetweenAreas = Service.Condition.IsBetweenAreas();
|
||||||
_lastQuestCount = GetActiveQuestCount();
|
|
||||||
try { _lastTempMarkerCount = (int)AgentMap.Instance()->TempMapMarkerCount; } catch { }
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,6 +144,12 @@ public unsafe class IntegrationsController : IDisposable
|
|||||||
RequestSilentRefresh();
|
RequestSilentRefresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// When player exits NPC or quest dialogue, refresh so minimap updates (e.g. "go to destination and speak to NPC" with no 1/3, 2/3 step counter).
|
||||||
|
var inDialogue = Service.Condition[ConditionFlag.Occupied] || Service.Condition[ConditionFlag.OccupiedInQuestEvent];
|
||||||
|
if (_wasInQuestOrNpcDialogue && !inDialogue)
|
||||||
|
RequestSilentRefresh();
|
||||||
|
_wasInQuestOrNpcDialogue = inDialogue;
|
||||||
|
|
||||||
// Quest turned in, quest accepted, or objectives updated: refresh so markers stay in sync
|
// Quest turned in, quest accepted, or objectives updated: refresh so markers stay in sync
|
||||||
// Skip these triggers when user just opened map via Duty List (quest/gathering/flag/teleport)
|
// Skip these triggers when user just opened map via Duty List (quest/gathering/flag/teleport)
|
||||||
// so we don't close the map they intentionally opened.
|
// so we don't close the map they intentionally opened.
|
||||||
@@ -154,6 +165,7 @@ public unsafe class IntegrationsController : IDisposable
|
|||||||
var tempCount = -1;
|
var tempCount = -1;
|
||||||
try { tempCount = (int)AgentMap.Instance()->TempMapMarkerCount; } catch { }
|
try { tempCount = (int)AgentMap.Instance()->TempMapMarkerCount; } catch { }
|
||||||
var sequenceSnapshot = GetQuestSequenceSnapshot();
|
var sequenceSnapshot = GetQuestSequenceSnapshot();
|
||||||
|
var tempMarkerSnapshot = GetTempMarkerSnapshot();
|
||||||
if (!skipQuestTempRefresh) {
|
if (!skipQuestTempRefresh) {
|
||||||
if (_lastQuestCount >= 0 && questCount < _lastQuestCount)
|
if (_lastQuestCount >= 0 && questCount < _lastQuestCount)
|
||||||
RequestSilentRefresh(); // quest turned in
|
RequestSilentRefresh(); // quest turned in
|
||||||
@@ -165,9 +177,12 @@ public unsafe class IntegrationsController : IDisposable
|
|||||||
RequestSilentRefresh(); // objectives added (e.g. new quest)
|
RequestSilentRefresh(); // objectives added (e.g. new quest)
|
||||||
if (_lastQuestSequenceSnapshot.Length > 0 && sequenceSnapshot != _lastQuestSequenceSnapshot)
|
if (_lastQuestSequenceSnapshot.Length > 0 && sequenceSnapshot != _lastQuestSequenceSnapshot)
|
||||||
RequestSilentRefresh(); // quest step advanced (multi-step objective)
|
RequestSilentRefresh(); // quest step advanced (multi-step objective)
|
||||||
|
if (_lastTempMarkerSnapshot.Length > 0 && tempMarkerSnapshot.Length > 0 && tempMarkerSnapshot != _lastTempMarkerSnapshot)
|
||||||
|
RequestSilentRefresh(); // marker positions changed (e.g. 1/3 -> 2/3, circle moved)
|
||||||
_lastQuestCount = questCount;
|
_lastQuestCount = questCount;
|
||||||
_lastTempMarkerCount = tempCount;
|
_lastTempMarkerCount = tempCount;
|
||||||
_lastQuestSequenceSnapshot = sequenceSnapshot;
|
_lastQuestSequenceSnapshot = sequenceSnapshot;
|
||||||
|
_lastTempMarkerSnapshot = tempMarkerSnapshot;
|
||||||
} else {
|
} else {
|
||||||
// During suppression: only update temp baseline so we don't false-trigger when suppression
|
// During suppression: only update temp baseline so we don't false-trigger when suppression
|
||||||
// ends (e.g. Duty List click repopulates markers). Keep _lastQuestCount and _lastQuestSequenceSnapshot
|
// ends (e.g. Duty List click repopulates markers). Keep _lastQuestCount and _lastQuestSequenceSnapshot
|
||||||
@@ -188,16 +203,22 @@ public unsafe class IntegrationsController : IDisposable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Build a string of (QuestId, Sequence) for each active quest so we can detect step advances.</summary>
|
/// <summary>Build a string of (QuestId, Sequence, variables) for each active quest so we can detect step advances and multi-step objective progress (1/3, 2/3, etc.).</summary>
|
||||||
private static unsafe string GetQuestSequenceSnapshot()
|
private static unsafe string GetQuestSequenceSnapshot()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var parts = new List<string>();
|
var parts = new List<string>();
|
||||||
foreach (var q in QuestManager.Instance()->NormalQuests)
|
var span = QuestManager.Instance()->NormalQuests;
|
||||||
|
for (var i = 0; i < span.Length; i++)
|
||||||
{
|
{
|
||||||
|
ref var q = ref span[i];
|
||||||
if (q.QuestId is 0) continue;
|
if (q.QuestId is 0) continue;
|
||||||
parts.Add($"{q.QuestId}:{q.Sequence}");
|
// Include variables (objective progress) - changes when 1/3 -> 2/3 even if Sequence does not
|
||||||
|
var ptr = (byte*)Unsafe.AsPointer(ref q);
|
||||||
|
var varStr = string.Empty;
|
||||||
|
for (var j = 0; j < 6; j++) varStr += $"{ptr[0x0C + j]:X2}";
|
||||||
|
parts.Add($"{q.QuestId}:{q.Sequence}:{varStr}");
|
||||||
}
|
}
|
||||||
return string.Join("|", parts);
|
return string.Join("|", parts);
|
||||||
}
|
}
|
||||||
@@ -207,6 +228,31 @@ public unsafe class IntegrationsController : IDisposable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Build a string of temp marker positions; when marker moves (e.g. 1/3 to 2/3 location) we detect and refresh.</summary>
|
||||||
|
private static unsafe string GetTempMarkerSnapshot()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var agent = AgentMap.Instance();
|
||||||
|
var count = agent->TempMapMarkerCount;
|
||||||
|
if (count == 0) return string.Empty;
|
||||||
|
var parts = new List<string>();
|
||||||
|
var seen = new HashSet<(int, int)>();
|
||||||
|
for (var i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
ref var m = ref agent->TempMapMarkers[i];
|
||||||
|
var key = (m.MapMarker.X, m.MapMarker.Y);
|
||||||
|
if (seen.Add(key))
|
||||||
|
parts.Add($"{m.MapMarker.X},{m.MapMarker.Y}");
|
||||||
|
}
|
||||||
|
return string.Join("|", parts.OrderBy(x => x));
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>Call when user opens map via Duty List (quest/gathering/flag/teleport). Cancels any in-progress silent refresh so we never Hide() the map. Suppresses new quest/temp-marker-triggered refresh for ~1s. Must be called BEFORE openMapHook.Original so OnFrameworkUpdate cannot call Hide() first.</summary>
|
/// <summary>Call when user opens map via Duty List (quest/gathering/flag/teleport). Cancels any in-progress silent refresh so we never Hide() the map. Suppresses new quest/temp-marker-triggered refresh for ~1s. Must be called BEFORE openMapHook.Original so OnFrameworkUpdate cannot call Hide() first.</summary>
|
||||||
private void SuppressSilentRefreshForUserMapOpen()
|
private void SuppressSilentRefreshForUserMapOpen()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -175,6 +175,7 @@ public unsafe partial class MapRenderer : IDisposable
|
|||||||
if (string.IsNullOrEmpty(idStr)) return false;
|
if (string.IsNullOrEmpty(idStr)) return false;
|
||||||
|
|
||||||
// Try several path conventions so the minimap can show without ever requiring the user to open the Area Map.
|
// Try several path conventions so the minimap can show without ever requiring the user to open the Area Map.
|
||||||
|
// Prefer TextureProvider.GetFromGame (same as Area Map) so path resolution and mods match; fall back to Lumina GetTexFile.
|
||||||
var fileName = idStr.Replace("/", "");
|
var fileName = idStr.Replace("/", "");
|
||||||
var pathsToTry = new[]
|
var pathsToTry = new[]
|
||||||
{
|
{
|
||||||
@@ -185,17 +186,24 @@ public unsafe partial class MapRenderer : IDisposable
|
|||||||
$"ui/uld/areamap/{fileName}.tex",
|
$"ui/uld/areamap/{fileName}.tex",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
string? gamePath = null;
|
||||||
IDalamudTextureWrap? texture = null;
|
IDalamudTextureWrap? texture = null;
|
||||||
foreach (var path in pathsToTry) {
|
foreach (var path in pathsToTry) {
|
||||||
|
var wrap = Service.TextureProvider.GetFromGame(path).GetWrapOrDefault();
|
||||||
|
if (wrap is not null && wrap.Handle != IntPtr.Zero && wrap.Size.X > 0 && wrap.Size.Y > 0) {
|
||||||
|
gamePath = path;
|
||||||
|
break;
|
||||||
|
}
|
||||||
texture = LoadSingleTexture(path);
|
texture = LoadSingleTexture(path);
|
||||||
if (texture is not null) break;
|
if (texture is not null) break;
|
||||||
}
|
}
|
||||||
if (texture is null) return false;
|
|
||||||
|
if (gamePath is null && texture is null) return false;
|
||||||
|
|
||||||
TrimMinimapCacheToLimit();
|
TrimMinimapCacheToLimit();
|
||||||
var entry = _minimapCache[mapId] = new MinimapCacheEntry();
|
var entry = _minimapCache[mapId] = new MinimapCacheEntry();
|
||||||
entry.PathKey = $"lumina:{mapId}";
|
entry.PathKey = gamePath is not null ? $"game:{gamePath}" : $"lumina:{mapId}";
|
||||||
entry.Texture = texture;
|
entry.Texture = texture; // null when using game path (looked up each frame)
|
||||||
entry.ScaleFactor = map.SizeFactor / 100f;
|
entry.ScaleFactor = map.SizeFactor / 100f;
|
||||||
entry.OffsetX = map.OffsetX;
|
entry.OffsetX = map.OffsetX;
|
||||||
entry.OffsetY = map.OffsetY;
|
entry.OffsetY = map.OffsetY;
|
||||||
@@ -251,14 +259,23 @@ public unsafe partial class MapRenderer : IDisposable
|
|||||||
TryEnsureLuminaCacheFor(currentMapId);
|
TryEnsureLuminaCacheFor(currentMapId);
|
||||||
|
|
||||||
// Draw from cache if we have it for the current map.
|
// Draw from cache if we have it for the current map.
|
||||||
if (!_minimapCache.TryGetValue(currentMapId, out var cached) || cached.Texture is null)
|
if (!_minimapCache.TryGetValue(currentMapId, out var cached))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Resolve texture: use cached texture, or for "game:" path look up via TextureProvider each frame (same as Area Map).
|
||||||
|
IDalamudTextureWrap? textureToDraw = cached.Texture;
|
||||||
|
if (textureToDraw is null && cached.PathKey.StartsWith("game:", StringComparison.Ordinal)) {
|
||||||
|
var path = cached.PathKey.Substring(5);
|
||||||
|
textureToDraw = Service.TextureProvider.GetFromGame(path).GetWrapOrDefault();
|
||||||
|
}
|
||||||
|
if (textureToDraw is null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Use the size passed by the minimap window (window size) so zoom/center is stable.
|
// Use the size passed by the minimap window (window size) so zoom/center is stable.
|
||||||
if (size.X <= 0 || size.Y <= 0) return;
|
if (size.X <= 0 || size.Y <= 0) return;
|
||||||
|
|
||||||
var zoom = Math.Clamp(System.SystemConfig.MinimapZoom, 0.03f, 0.112f);
|
var zoom = Math.Clamp(System.SystemConfig.MinimapZoom, 0.03f, 0.112f);
|
||||||
var mapSize = cached.Texture.Size.X;
|
var mapSize = textureToDraw.Size.X;
|
||||||
// Scale so the map COVERS the view at zoom=1 (use max so no black bands at max zoom out).
|
// Scale so the map COVERS the view at zoom=1 (use max so no black bands at max zoom out).
|
||||||
var fitScale = Math.Max(size.X, size.Y) / mapSize;
|
var fitScale = Math.Max(size.X, size.Y) / mapSize;
|
||||||
var scale = fitScale / zoom;
|
var scale = fitScale / zoom;
|
||||||
@@ -270,11 +287,11 @@ public unsafe partial class MapRenderer : IDisposable
|
|||||||
var drawOffset = (-playerCoord + new Vector2(cached.OffsetX, cached.OffsetY)) * cached.ScaleFactor;
|
var drawOffset = (-playerCoord + new Vector2(cached.OffsetX, cached.OffsetY)) * cached.ScaleFactor;
|
||||||
|
|
||||||
var centerOffset = size / 2.0f;
|
var centerOffset = size / 2.0f;
|
||||||
var mapCenterOffset = (cached.Texture.Size / 2f) * scale;
|
var mapCenterOffset = (textureToDraw.Size / 2f) * scale;
|
||||||
var drawPosition = centerOffset - mapCenterOffset + drawOffset * scale;
|
var drawPosition = centerOffset - mapCenterOffset + drawOffset * scale;
|
||||||
|
|
||||||
// Clamp so the map always fills the view (no black), but when zoomed in allow full pan so the player tracks.
|
// Clamp so the map always fills the view (no black), but when zoomed in allow full pan so the player tracks.
|
||||||
var texSize = cached.Texture.Size * scale;
|
var texSize = textureToDraw.Size * scale;
|
||||||
if (texSize.X > size.X && texSize.Y > size.Y) {
|
if (texSize.X > size.X && texSize.Y > size.Y) {
|
||||||
// Zoomed in: allow full pan range so the map can shift in any direction and the player stays at center.
|
// Zoomed in: allow full pan range so the map can shift in any direction and the player stays at center.
|
||||||
drawPosition.X = Math.Clamp(drawPosition.X, size.X - texSize.X, texSize.X - size.X);
|
drawPosition.X = Math.Clamp(drawPosition.X, size.X - texSize.X, texSize.X - size.X);
|
||||||
@@ -287,7 +304,7 @@ public unsafe partial class MapRenderer : IDisposable
|
|||||||
|
|
||||||
// Content top-left in screen space so player is drawn at the true center of the minimap (not offset by title bar).
|
// Content top-left in screen space so player is drawn at the true center of the minimap (not offset by title bar).
|
||||||
var contentTopLeft = ImGui.GetCursorScreenPos();
|
var contentTopLeft = ImGui.GetCursorScreenPos();
|
||||||
DrawMinimapCachedTextureAt(drawPosition, scale, cached.Texture);
|
DrawMinimapCachedTextureAt(drawPosition, scale, textureToDraw);
|
||||||
var centerScreen = contentTopLeft + centerOffset;
|
var centerScreen = contentTopLeft + centerOffset;
|
||||||
// Draw cone under markers so quest/FATE/POI markers stay visible on top of the cone.
|
// Draw cone under markers so quest/FATE/POI markers stay visible on top of the cone.
|
||||||
DrawMinimapConeAtCenter(centerScreen, scale);
|
DrawMinimapConeAtCenter(centerScreen, scale);
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@
|
|||||||
<Name>HSMappy</Name>
|
<Name>HSMappy</Name>
|
||||||
<InternalName>HSMappy</InternalName>
|
<InternalName>HSMappy</InternalName>
|
||||||
<Author>Knack117</Author>
|
<Author>Knack117</Author>
|
||||||
<Version>1.0.0.18</Version>
|
<Version>1.0.0.21</Version>
|
||||||
<Punchline>A more versatile in-game map.</Punchline>
|
<Punchline>A more versatile in-game map.</Punchline>
|
||||||
<Description>Replaces the in-game map with an ImGui implementation with several additional features. Fork with minimap improvements, quest radius on minimap, and more.</Description>
|
<Description>Replaces the in-game map with an ImGui implementation with several additional features. Fork with minimap improvements, quest radius on minimap, and more.</Description>
|
||||||
<RepoUrl>http://brassnet.ddns.net:33983/KnackAtNite/HSMappy</RepoUrl>
|
<RepoUrl>http://brassnet.ddns.net:33983/KnackAtNite/HSMappy</RepoUrl>
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
[{"Author":"Knack117","Name":"HSMappy","Punchline":"A more versatile in-game map.","Description":"Replaces the in-game map with an ImGui implementation with several additional features. Fork with minimap improvements, quest radius on minimap, white gradient player cone, and more.","Changelog":"1.0.0.18: Minimap automations (Desynth, Extract, Repair, Equip, Coffers); player movement cancels automation; >> button with tooltip. 1.0.0.17: Minimap stays visible during dialogue (NPC/quest); rest of hide behavior unchanged. 1.0.0.16: Draw minimap underneath other UI (HSUI etc); Draw Under Other UI config option. 1.0.0.15: Top/Bottom Info Bars: renamed from Map Info/Coordinate; configurable order for both; Repair % (most damaged item); font, size, color, background for both bars; right-align last bottom bar element. 1.0.0.14: Movement Trail (Carbonite-style) - red dots show where you've been on map and minimap; configurable distance, fade time, max points; Clear Trail in context menu. 1.0.0.13: User-placed map notes with Title/Description; custom white-page icon; notes on minimap; Remove Note via context menu; Note List layout fix. 1.0.0.12: Other players on minimap use distinct icon (60403) from party markers. 1.0.0.11: Player/NPC tracking on minimap with Show Players and NPCs toggle. 1.0.0.10: Release build. Suppress silent refresh at start of OnOpenMapHook; remove debug logging. 1.0.0.9: Duty List quest click: don't Hide() when viewing quest map (SelectedMapId != CurrentMapId). 1.0.0.8: Cancel silent refresh when opening map from Duty List so it doesn't immediately close. 1.0.0.7: Duty List quest click opens Area Map even when Hide With Game GUI would block it. 1.0.0.6: Minimap stays open after client restart (restore on login). 1.0.0.5: Fix crash when map texture path is invalid (ArgumentOutOfRangeException in Lumina GetFileHash). 1.0.0.4: Temp marker circle refreshes when quest objective is progressed. 1.0.0.3: Fix marker cache refresh after quest turn-in; invalidate temp cache so old markers don't persist. 1.0.0.2: Red direction arrow on minimap pointing to player flag. 1.0.0.1: Duty List quest click keeps Area Map open; player flags show on minimap. 1.0.0.0: Initial HSMappy release. Minimap: quest radius circle (orange, transparent), tooltip; cone drawn under markers; white gradient cone; /hsmappy commands.","InternalName":"HSMappy","AssemblyVersion":"1.0.0.18","RepoUrl":"http://brassnet.ddns.net:33983/KnackAtNite/HSMappy","ApplicableVersion":"any","Tags":["map","mapping","overlay","utility"],"CategoryTags":["jobs"],"DalamudApiLevel":14,"DownloadLinkInstall":"http://brassnet.ddns.net:33983/KnackAtNite/HSMappy/releases/download/v1.0.0.18/latest.zip","IsHide":false,"IsTestingExclusive":false,"DownloadLinkTesting":"http://brassnet.ddns.net:33983/KnackAtNite/HSMappy/releases/download/v1.0.0.18/latest.zip","DownloadLinkUpdate":"http://brassnet.ddns.net:33983/KnackAtNite/HSMappy/releases/download/v1.0.0.18/latest.zip","LastUpdate":"1772372275"}]
|
[{"Author":"Knack117","Name":"HSMappy","Punchline":"A more versatile in-game map.","Description":"Replaces the in-game map with an ImGui implementation with several additional features. Fork with minimap improvements, quest radius on minimap, white gradient player cone, and more.","Changelog":"1.0.0.21: Refresh minimap markers when exiting NPC/quest dialogue (fixes 'speak to NPC' objectives with no step counter). 1.0.0.20: Fix marker refresh sometimes not running when accepting a quest or advancing a quest step. 1.0.0.19: Minimap quest area circles refresh when multi-step objective progresses (1/3 -> 2/3, etc.). 1.0.0.18: Minimap automations (Desynth, Extract, Repair, Equip, Coffers); player movement cancels automation; >> button with tooltip. 1.0.0.17: Minimap stays visible during dialogue (NPC/quest); rest of hide behavior unchanged. 1.0.0.16: Draw minimap underneath other UI (HSUI etc); Draw Under Other UI config option. 1.0.0.15: Top/Bottom Info Bars: renamed from Map Info/Coordinate; configurable order for both; Repair % (most damaged item); font, size, color, background for both bars; right-align last bottom bar element. 1.0.0.14: Movement Trail (Carbonite-style) - red dots show where you've been on map and minimap; configurable distance, fade time, max points; Clear Trail in context menu. 1.0.0.13: User-placed map notes with Title/Description; custom white-page icon; notes on minimap; Remove Note via context menu; Note List layout fix. 1.0.0.12: Other players on minimap use distinct icon (60403) from party markers. 1.0.0.11: Player/NPC tracking on minimap with Show Players and NPCs toggle. 1.0.0.10: Release build. Suppress silent refresh at start of OnOpenMapHook; remove debug logging. 1.0.0.9: Duty List quest click: don't Hide() when viewing quest map (SelectedMapId != CurrentMapId). 1.0.0.8: Cancel silent refresh when opening map from Duty List so it doesn't immediately close. 1.0.0.7: Duty List quest click opens Area Map even when Hide With Game GUI would block it. 1.0.0.6: Minimap stays open after client restart (restore on login). 1.0.0.5: Fix crash when map texture path is invalid (ArgumentOutOfRangeException in Lumina GetFileHash). 1.0.0.4: Temp marker circle refreshes when quest objective is progressed. 1.0.0.3: Fix marker cache refresh after quest turn-in; invalidate temp cache so old markers don't persist. 1.0.0.2: Red direction arrow on minimap pointing to player flag. 1.0.0.1: Duty List quest click keeps Area Map open; player flags show on minimap. 1.0.0.0: Initial HSMappy release. Minimap: quest radius circle (orange, transparent), tooltip; cone drawn under markers; white gradient cone; /hsmappy commands.","InternalName":"HSMappy","AssemblyVersion":"1.0.0.21","RepoUrl":"http://brassnet.ddns.net:33983/KnackAtNite/HSMappy","ApplicableVersion":"any","Tags":["map","mapping","overlay","utility"],"CategoryTags":["jobs"],"DalamudApiLevel":14,"DownloadLinkInstall":"http://brassnet.ddns.net:33983/KnackAtNite/HSMappy/releases/download/v1.0.0.21/latest.zip","IsHide":false,"IsTestingExclusive":false,"DownloadLinkTesting":"http://brassnet.ddns.net:33983/KnackAtNite/HSMappy/releases/download/v1.0.0.21/latest.zip","DownloadLinkUpdate":"http://brassnet.ddns.net:33983/KnackAtNite/HSMappy/releases/download/v1.0.0.21/latest.zip","LastUpdate":"1772669732"}]
|
||||||
|
|||||||
Reference in New Issue
Block a user