v1.0.8.26: Duty List hidden quests filtered; priority quests on top; no map flag on quest map open

Made-with: Cursor
This commit is contained in:
2026-03-04 22:01:33 -05:00
parent bd9164c896
commit 57e4736e22
5 changed files with 27 additions and 49 deletions
+18 -44
View File
@@ -70,7 +70,7 @@ namespace HSUI.Helpers
return questData.ClassJobLevel.FirstOrDefault();
}
/// <summary>Returns active duty list entries (quests with objectives).</summary>
/// <summary>Returns active duty list entries (quests with objectives). Prioritized/tracked quests appear at the top.</summary>
public static unsafe List<DutyListEntry> GetDutyListEntries()
{
var result = new List<DutyListEntry>();
@@ -79,11 +79,15 @@ namespace HSUI.Helpers
var questSheet = Plugin.DataManager.GetExcelSheet<Quest>();
if (questSheet == null) return result;
var priorityEntries = new List<DutyListEntry>();
var otherEntries = new List<DutyListEntry>();
var span = QuestManager.Instance()->NormalQuests;
for (int i = 0; i < span.Length; i++)
{
ref var q = ref span[i];
if (q.QuestId == 0) continue;
if (q.IsHidden) continue; // Don't show quests the player hid in their journal
uint rowId = q.QuestId + 65536u;
if (!questSheet.HasRow(rowId)) continue;
@@ -97,9 +101,16 @@ namespace HSUI.Helpers
// Current objective text from Sequence
string objectiveText = GetObjectiveText(questData, q.Sequence);
result.Add(new DutyListEntry(q.QuestId, q.Sequence, questName, objectiveText, iconId));
var entry = new DutyListEntry(q.QuestId, q.Sequence, questName, objectiveText, iconId);
if (q.IsPriority)
priorityEntries.Add(entry);
else
otherEntries.Add(entry);
}
result.AddRange(priorityEntries);
result.AddRange(otherEntries);
// If Lumina didn't give objective text, try the game's ToDoList string array (same source as the default Duty List UI).
TryFillObjectivesFromToDoListStringArray(result);
// Do not read from _ToDoList addon text nodes: addon memory can be invalid when Duty Finder is open or when queuing, causing AccessViolationException in Utf8String.ToString().
@@ -113,6 +124,7 @@ namespace HSUI.Helpers
{
ref var lq = ref leveSpan[i];
if (lq.LeveId == 0) continue;
if (lq.IsHidden) continue; // Don't show levequests the player hid in their journal
var leveData = leveSheet.GetRow(lq.LeveId);
@@ -542,7 +554,7 @@ namespace HSUI.Helpers
catch { /* ignore */ }
}
/// <summary>Gets territory ID for a map (for SetFlagMapMarker). Returns 0 if not found.</summary>
/// <summary>Gets territory ID for a map (for opening the map). Returns 0 if not found.</summary>
private static uint GetTerritoryIdForMap(uint mapId)
{
try
@@ -556,7 +568,7 @@ namespace HSUI.Helpers
catch { return 0; }
}
/// <summary>Opens the Area Map centered on the quest's current objective location. Sets a flag marker when coordinates are available so the map centers on the objective.</summary>
/// <summary>Opens the Area Map to the quest's current objective location. Does not place a map flag; opens the map centered (no marker).</summary>
public static unsafe void OpenMapForQuestObjective(ushort questId, byte sequence)
{
try
@@ -577,40 +589,11 @@ namespace HSUI.Helpers
if (territoryId == 0) return;
var agent = AgentMap.Instance();
(float x, float y)? coords = TryGetMapCoordinates(location.Value);
if (coords.HasValue)
{
agent->SetFlagMapMarker(territoryId, mapId, coords.Value.x, coords.Value.y);
agent->OpenMap(mapId, territoryId, null, FFXIVClientStructs.FFXIV.Client.UI.Agent.MapType.FlagMarker);
}
else
{
agent->OpenMap(mapId, territoryId, null, FFXIVClientStructs.FFXIV.Client.UI.Agent.MapType.Centered);
}
agent->OpenMap(mapId, territoryId, null, FFXIVClientStructs.FFXIV.Client.UI.Agent.MapType.Centered);
}
catch { /* ignore */ }
}
/// <summary>Tries to get map X,Y from a Level/location row (Lumina column names may vary).</summary>
private static (float x, float y)? TryGetMapCoordinates(object? locationRow)
{
if (locationRow == null) return null;
try
{
var type = locationRow.GetType();
var xProp = type.GetProperty("X") ?? type.GetProperty("MapX");
var yProp = type.GetProperty("Y") ?? type.GetProperty("MapY");
if (xProp == null || yProp == null) return null;
var xVal = xProp.GetValue(locationRow);
var yVal = yProp.GetValue(locationRow);
if (xVal == null || yVal == null) return null;
float x = Convert.ToSingle(xVal);
float y = Convert.ToSingle(yVal);
return (x, y);
}
catch { return null; }
}
/// <summary>Opens the Area Map to the quest's current objective (for scenario guide hints). Prefers current objective so MSQ and Job hints each open the correct map on first click; falls back to issuer location if quest is not in the duty list.</summary>
public static unsafe void OpenMapForQuestIssuer(uint questRowId)
{
@@ -641,16 +624,7 @@ namespace HSUI.Helpers
if (territoryId != 0)
{
var agent = AgentMap.Instance();
(float x, float y)? coords = TryGetMapCoordinates(loc);
if (coords.HasValue)
{
agent->SetFlagMapMarker(territoryId, mapId, coords.Value.x, coords.Value.y);
agent->OpenMap(mapId, territoryId, null, FFXIVClientStructs.FFXIV.Client.UI.Agent.MapType.FlagMarker);
}
else
{
agent->OpenMap(mapId, territoryId, null, FFXIVClientStructs.FFXIV.Client.UI.Agent.MapType.Centered);
}
agent->OpenMap(mapId, territoryId, null, FFXIVClientStructs.FFXIV.Client.UI.Agent.MapType.Centered);
}
}
}