v1.0.0.19: Minimap quest area circles refresh when multi-step objective progresses (1/3 -> 2/3, etc.)
Made-with: Cursor
This commit is contained in:
@@ -2,6 +2,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Dalamud.Game.ClientState.Conditions;
|
||||
using Dalamud.Hooking;
|
||||
using Dalamud.Plugin.Services;
|
||||
@@ -27,8 +28,10 @@ public unsafe class IntegrationsController : IDisposable
|
||||
private bool _wasBetweenAreas;
|
||||
private int _lastQuestCount = -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;
|
||||
/// <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;
|
||||
private bool _refreshedDuringLoad;
|
||||
/// <summary>When true, request a silent refresh on the next framework update (e.g. after plugin load).</summary>
|
||||
private bool _requestRefreshOnLoad = true;
|
||||
@@ -113,6 +116,8 @@ public unsafe class IntegrationsController : IDisposable
|
||||
_wasBetweenAreas = Service.Condition.IsBetweenAreas();
|
||||
_lastQuestCount = GetActiveQuestCount();
|
||||
try { _lastTempMarkerCount = (int)AgentMap.Instance()->TempMapMarkerCount; } catch { }
|
||||
_lastQuestSequenceSnapshot = GetQuestSequenceSnapshot();
|
||||
_lastTempMarkerSnapshot = GetTempMarkerSnapshot();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -154,6 +159,7 @@ public unsafe class IntegrationsController : IDisposable
|
||||
var tempCount = -1;
|
||||
try { tempCount = (int)AgentMap.Instance()->TempMapMarkerCount; } catch { }
|
||||
var sequenceSnapshot = GetQuestSequenceSnapshot();
|
||||
var tempMarkerSnapshot = GetTempMarkerSnapshot();
|
||||
if (!skipQuestTempRefresh) {
|
||||
if (_lastQuestCount >= 0 && questCount < _lastQuestCount)
|
||||
RequestSilentRefresh(); // quest turned in
|
||||
@@ -165,9 +171,12 @@ public unsafe class IntegrationsController : IDisposable
|
||||
RequestSilentRefresh(); // objectives added (e.g. new quest)
|
||||
if (_lastQuestSequenceSnapshot.Length > 0 && sequenceSnapshot != _lastQuestSequenceSnapshot)
|
||||
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;
|
||||
_lastTempMarkerCount = tempCount;
|
||||
_lastQuestSequenceSnapshot = sequenceSnapshot;
|
||||
_lastTempMarkerSnapshot = tempMarkerSnapshot;
|
||||
} else {
|
||||
// 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
|
||||
@@ -188,16 +197,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()
|
||||
{
|
||||
try
|
||||
{
|
||||
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;
|
||||
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);
|
||||
}
|
||||
@@ -207,6 +222,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>
|
||||
private void SuppressSilentRefreshForUserMapOpen()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user