fix: resolve QUEST_ACCEPTED log-index vs questID ambiguity and add quest-log fallback to tracker for DB-unknown quests

This commit is contained in:
Xurkon
2026-03-16 22:57:18 -05:00
parent 5e35aa6cb5
commit d9828e6159
3 changed files with 79 additions and 14 deletions
+11 -12
View File
@@ -648,18 +648,17 @@ function QuestieLearner:OnQuestComplete()
end end
end end
-- Fires when a quest is accepted; in 3.3.5 the first (and only) arg IS the questID directly -- Fires when a quest is accepted.
function QuestieLearner:OnQuestAccepted(questId) -- Ascension 3.3.5 passes the quest log index as the first arg; some builds pass questID directly.
-- Fallback: scan log for an unknown quest in case the server sends log index instead -- We detect which by checking if the value could be a log index and resolving via GetQuestLogTitle.
if not questId or questId <= 0 then function QuestieLearner:OnQuestAccepted(firstArg)
for i = 1, GetNumQuestLogEntries() do local questId = firstArg
local _, _, _, _, isHeader, _, _, _, id = GetQuestLogTitle(i) local maxLog = GetNumQuestLogEntries and GetNumQuestLogEntries() or 25
if not isHeader and id and id > 0 and not Questie.db.global.learnedData.quests[id] then -- If arg looks like a log index (small int ≤ log size), resolve to quest ID via GetQuestLogTitle
if not (QuestieDB and QuestieDB.questData and QuestieDB.questData[id]) then if firstArg and firstArg > 0 and firstArg <= maxLog then
questId = id local resolvedId = select(8, GetQuestLogTitle(firstArg))
break if resolvedId and resolvedId > 0 then
end questId = resolvedId
end
end end
end end
Questie:Debug(Questie.DEBUG_LEARNER, "[QuestieLearner] OnQuestAccepted id=" .. tostring(questId)) Questie:Debug(Questie.DEBUG_LEARNER, "[QuestieLearner] OnQuestAccepted id=" .. tostring(questId))
+10 -2
View File
@@ -2375,8 +2375,16 @@ function QuestieTracker:AQW_Insert(index, expire)
if Questie.IsSoD then if Questie.IsSoD then
QuestieDebugOffer.QuestTracking(questId) QuestieDebugOffer.QuestTracking(questId)
else else
Questie:Error("Missing quest " .. -- Quest not in DB — try building a fallback object from the quest log
tostring(questId) .. "," .. tostring(expire) .. " during tracker update") local fallback = TrackerUtils:BuildFallbackQuest(questId)
if fallback then
QuestiePlayer.currentQuestlog[questId] = fallback
QuestieCombatQueue:Queue(function()
QuestieTracker:Update()
end)
else
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieTracker] Quest " .. tostring(questId) .. " not in DB and not in quest log, skipping")
end
end end
end end
end end
+58
View File
@@ -694,6 +694,54 @@ end
---@return table sortedQuestIds Table with sorted Quest ID's by Sort Type ---@return table sortedQuestIds Table with sorted Quest ID's by Sort Type
---@return table questDetails Table with raw quest table from QuestiePlayer.currentQuestLog, percentage completed value per quest, and a "translated" zoneName ---@return table questDetails Table with raw quest table from QuestiePlayer.currentQuestLog, percentage completed value per quest, and a "translated" zoneName
-- Builds a minimal quest-like object from the quest log for quests not in QuestieDB.
-- Returns nil if the quest is not currently in the quest log.
function TrackerUtils:BuildFallbackQuest(questId)
for i = 1, GetNumQuestLogEntries() do
local title, level, _, isHeader, _, isComplete, _, logQuestId = GetQuestLogTitle(i)
if not isHeader and logQuestId == questId then
-- Parse objectives from the leaderboard
local objectives = {}
local numObj = GetNumQuestLeaderBoards and GetNumQuestLeaderBoards(i) or 0
for j = 1, numObj do
local text, _, finished = GetQuestLogLeaderBoard(j, i)
if text then
-- Parse "Description: X/Y" or just "Description"
local collected, needed = string.match(text, ":.-(%d+)/(%d+)%s*$")
collected = tonumber(collected) or (finished and 1 or 0)
needed = tonumber(needed) or 1
objectives[j] = {
text = text,
Needed = needed,
Collected = collected,
Finished = finished or (collected >= needed),
Type = "fallback",
}
end
end
local zoneId = GetCurrentMapAreaID and GetCurrentMapAreaID() or 0
local quest = {
Id = questId,
name = title or ("Quest " .. questId),
level = level or 0,
zoneOrSort = zoneId,
Objectives = objectives,
SpecialObjectives = {},
isFallback = true,
}
-- IsComplete must be a method (called as quest:IsComplete())
quest.IsComplete = function(self)
return (isComplete == 1 or IsQuestFlaggedCompleted(questId)) and 1 or 0
end
return quest
end
end
return nil
end
function TrackerUtils:GetSortedQuestIds() function TrackerUtils:GetSortedQuestIds()
local sortedQuestIds = {} local sortedQuestIds = {}
local questDetails = {} local questDetails = {}
@@ -711,6 +759,16 @@ function TrackerUtils:GetSortedQuestIds()
end end
end end
-- Fallback for quests not in QuestieDB (e.g. custom server quests).
-- Build a minimal quest object from the quest log so the tracker can still display it.
if type(quest) ~= "table" or not quest.IsComplete or not quest.Objectives then
local fallback = TrackerUtils:BuildFallbackQuest(qid)
if fallback then
quest = fallback
QuestiePlayer.currentQuestlog[qid] = fallback
end
end
if type(quest) == "table" and quest.IsComplete and quest.Objectives then if type(quest) == "table" and quest.IsComplete and quest.Objectives then
-- Insert Quest Ids into sortedQuestIds table -- Insert Quest Ids into sortedQuestIds table
tinsert(sortedQuestIds, qid) tinsert(sortedQuestIds, qid)