fix(tracker): group quests under their quest log header for server categories

Ascension files its main quest chain under a header of its own,
"Ascension Main Quest", which exists in no zone table. The tracker fell
back to the quest's zoneOrSort, and for anything the Learner recorded
that is the zone the quest was picked up in -- so the whole chain showed
up under "Red Cloud Mesa".

A header that resolves to no area is a category the server invented, and
the client's own grouping is the only thing that knows about it, so use
it. Headers are now mapped in a single pass per draw instead of a walk of
the quest log per quest.
This commit is contained in:
2026-07-30 18:15:10 +02:00
parent c2b1b82b2f
commit 706fc0b8ad
+45 -19
View File
@@ -676,27 +676,37 @@ local function GetAreaIdByZoneName(zoneName)
return l10n:GetAreaIdByLocalName(zoneName) return l10n:GetAreaIdByLocalName(zoneName)
end end
-- Walk the quest log to find the zone header for a given questId. -- questId -> the header the client filed it under in the quest log. In 3.3.5 those headers are
-- In 3.3.5, zone names appear as isHeader=true entries above their quests. -- isHeader=true entries sitting above the quests they cover. Built in one pass and kept, because
-- Returns the header title string, or nil if not found. -- the tracker asks per quest and redraws often -- walking the log once per quest is quadratic.
local questLogHeaders = {}
local function BuildQuestLogHeaders()
local headers = {}
local header
for i = 1, (GetNumQuestLogEntries and GetNumQuestLogEntries() or 0) do
local title, _, _, isHeader, _, _, _, logId = GetQuestLogTitle(i)
if isHeader then
if title and title ~= "" then
header = title
end
elseif logId and header then
headers[logId] = header
end
end
questLogHeaders = headers
end
-- Returns the header title string, or nil if the quest is not in the log under one.
local function GetQuestLogZoneName(questId) local function GetQuestLogZoneName(questId)
local targetIndex = nil if not questLogHeaders[questId] then
local total = GetNumQuestLogEntries and GetNumQuestLogEntries() or 0 -- Asked about a quest the last pass did not see, so the log has moved on since.
for i = 1, total do BuildQuestLogHeaders()
local _, _, _, isHeader, _, _, _, logId = GetQuestLogTitle(i)
if not isHeader and logId == questId then
targetIndex = i
break
end
end end
if not targetIndex then return nil end
for i = targetIndex, 1, -1 do return questLogHeaders[questId]
local title, _, _, isHeader = GetQuestLogTitle(i)
if isHeader and title and title ~= "" then
return title
end
end
return nil
end end
local function _GetZoneName(zoneOrSort, questId, zoneNameOverride) local function _GetZoneName(zoneOrSort, questId, zoneNameOverride)
@@ -707,6 +717,19 @@ local function _GetZoneName(zoneOrSort, questId, zoneNameOverride)
local zoneName local zoneName
local sortObj = Questie.db.profile.trackerSortObjectives local sortObj = Questie.db.profile.trackerSortObjectives
if sortObj == "byZone" or sortObj == "byZoneComplete" or sortObj == "byZoneCompleteReversed" or sortObj == "byZonePlayerProximity" or sortObj == "byZonePlayerProximityReversed" then if sortObj == "byZone" or sortObj == "byZoneComplete" or sortObj == "byZoneCompleteReversed" or sortObj == "byZonePlayerProximity" or sortObj == "byZonePlayerProximityReversed" then
-- A server can file quests under categories of its own -- Ascension's "Ascension Main
-- Quest" -- and those exist nowhere in the zone tables, so the quest data points at a zone
-- instead: for anything the Learner recorded, whichever zone it was picked up in. A header
-- that does not resolve to an area is one of those categories, and the client's own
-- grouping is the only thing that knows about it.
local logHeader = GetQuestLogZoneName(questId)
if logHeader and logHeader ~= "" then
local headerAreaId = GetAreaIdByZoneName(logHeader)
if (not headerAreaId) or headerAreaId == 0 then
return logHeader
end
end
if (zoneOrSort) > 0 then if (zoneOrSort) > 0 then
zoneName = TrackerUtils:GetZoneNameByID(zoneOrSort) zoneName = TrackerUtils:GetZoneNameByID(zoneOrSort)
if not zoneName or zoneName == "Unknown Zone" then if not zoneName or zoneName == "Unknown Zone" then
@@ -813,6 +836,9 @@ function TrackerUtils:GetSortedQuestIds()
local sortedQuestIds = {} local sortedQuestIds = {}
local questDetails = {} local questDetails = {}
local sortObj = Questie.db.profile.trackerSortObjectives local sortObj = Questie.db.profile.trackerSortObjectives
-- One walk of the quest log for the whole draw, so the per-quest zone lookups below are reads.
BuildQuestLogHeaders()
-- Update quest objectives -- Update quest objectives
for questId, quest in pairs(QuestiePlayer.currentQuestlog) do for questId, quest in pairs(QuestiePlayer.currentQuestlog) do