fix(tracker): name and group quests built from partial records

Quests assembled from a Learner entry or a questDataOverrides entry that
never captured every field reach the tracker with nil fields, since GetQuest
copies rawdata key by key. Two of those show: a nil name printed as the
quest id, and a nil zoneOrSort that sent _GetZoneName down its very first
line, `if not zoneOrSort then return "Unknown Zone" end`, before it could
consult the quest log header the earlier fix added. Those objects are cached
for the session, so neither repaired itself.

GetQuest now fills a missing name from the quest log and defaults zoneOrSort
to 0, the value every caller already reads as "no zone on file" -- and which
some of them require, `quest.zoneOrSort > 0` erroring outright on nil.
_GetZoneName treats nil the same way rather than short-circuiting, which
also stops a nil quest from labelling its group Unknown Zone under the sort
modes that do not group by zone at all.

The tracker asks the quest log for a title before printing an id, so quests
already cached without a name come out right too, and the live-fallback
builder stops discarding the override data it just looked up.
This commit is contained in:
2026-08-17 15:57:17 +02:00
parent 26a135a2ca
commit 30fe4b83a9
3 changed files with 84 additions and 8 deletions
+43 -5
View File
@@ -1785,16 +1785,36 @@ function QuestieDB.GetQuest(questId, ...) -- /dump QuestieDB.GetQuest(867)
end
return nil
end
-- Build a minimal live-fallback quest from the quest log so the tracker still works
-- Build a minimal live-fallback quest from the quest log so the tracker still works.
-- The override that got us here is partial by nature -- a Learner record of a single
-- field, a correction -- but whatever it does carry beats guessing, and the quest object
-- built here is cached for the session, so anything left blank stays blank.
local logEntry = QuestLogCache.GetQuest(questId)
if not logEntry then return nil end
local function NonEmpty(text)
if text and text ~= "" then return text end
return nil
end
local overrideName = NonEmpty(overrideData[QuestieDB.questKeys.name])
local overrideLevel = overrideData[QuestieDB.questKeys.questLevel]
local overrideZone = overrideData[QuestieDB.questKeys.zoneOrSort]
local cachedTitle = NonEmpty(logEntry.title)
local liveTitle
if (not overrideName) and (not cachedTitle) and GetQuestLogIndexByID and GetQuestLogTitle then
-- QuestLogCache is a snapshot and can be missing the title of a quest the client
-- has since filled in, which is what leaves a quest showing as its own id.
local questLogIndex = GetQuestLogIndexByID(questId)
if questLogIndex and questLogIndex > 0 then
liveTitle = NonEmpty(GetQuestLogTitle(questLogIndex))
end
end
local fallback = {
Id = questId,
name = logEntry.title or tostring(questId),
level = logEntry.level or 0,
questLevel = logEntry.level or 0,
name = overrideName or cachedTitle or liveTitle or tostring(questId),
level = overrideLevel or logEntry.level or 0,
questLevel = overrideLevel or logEntry.level or 0,
requiredLevel = 0,
zoneOrSort = 0,
zoneOrSort = overrideZone or 0,
questFlags = 0,
specialFlags = 0,
Starts = { CreatureStarts = {}, ObjectStarts = {}, ItemStarts = {} },
@@ -1916,6 +1936,24 @@ function QuestieDB.GetQuest(questId, ...) -- /dump QuestieDB.GetQuest(867)
if learnerRecord.objIndex and not QO.objIndex then QO.objIndex = learnerRecord.objIndex end
end
-- A record that never captured a name -- a Learner entry written from an objective update, an
-- override carrying a single key -- leaves QO.name nil, and this object is cached for the rest
-- of the session, so everything downstream ends up printing the quest id. Ask the client.
if ((not QO.name) or QO.name == "") and GetQuestLogIndexByID and GetQuestLogTitle then
local questLogIndex = GetQuestLogIndexByID(questId)
if questLogIndex and questLogIndex > 0 then
local logTitle = GetQuestLogTitle(questLogIndex)
if logTitle and logTitle ~= "" then
QO.name = logTitle
end
end
end
-- Same story for the zone: partial records leave it nil, and callers all treat it as a number
-- (`quest.zoneOrSort > 0` errors outright on nil). 0 is the value everything already reads as
-- "no zone on file", which sends the tracker to the quest log for one.
QO.zoneOrSort = QO.zoneOrSort or 0
local questLevel, requiredLevel = QuestieLib.GetTbcLevel(questId)
QO.level = questLevel
QO.requiredLevel = requiredLevel