fix(tracker): drop quests the player no longer has

Ascension's special quests are finished by the server the moment their
objectives are met, and one of them stayed in the tracker for the rest of
the session: currentQuestlog is only as good as the removal events that
maintain it, and nothing landed for that quest.

The tracker now checks the quest log itself, which it already walks once
per draw for the zone headers, and skips anything that is no longer in
it, dropping the fallback object built for it as well. Skipped rather
than pruned, so a redraw that catches the log mid-refresh does not throw
away state Questie is about to want back.

Three things on the event side that let it get that far:

- CleanupRemovedQuestsFallback now also runs after a full quest log scan.
  UpdateAllQuests only inspects quests still in the log, so for as long
  as something kept asking for full scans, nothing looked for removals.
- A removed quest counts as completed when the server has it flagged
  complete. QuestieDB.IsComplete cannot answer for a quest the database
  has never heard of, so these were filed as abandoned instead.
- The removal scan type-checks the quest id before comparing it, so a
  stray string key cannot error out the pass for every other quest.
This commit is contained in:
2026-07-30 18:26:42 +02:00
parent c6019ea823
commit de270a0e8e
2 changed files with 42 additions and 7 deletions
+13 -2
View File
@@ -553,6 +553,10 @@ function _QuestEventHandler:QuestLogUpdate()
doFullQuestLogScan = false
-- Function call updates doFullQuestLogScan. Order matters.
_QuestEventHandler:UpdateAllQuests()
-- Also on this path: UpdateAllQuests only looks at quests still in the log, so a removal
-- that fired no event of its own would sit there unnoticed for as long as full scans keep
-- being asked for.
_QuestEventHandler:CleanupRemovedQuestsFallback()
else
_QuestEventHandler:CleanupRemovedQuestsFallback()
QuestieCombatQueue:Queue(function()
@@ -666,7 +670,9 @@ function _QuestEventHandler:CleanupRemovedQuestsFallback()
if QuestiePlayer and QuestiePlayer.currentQuestlog then
local removedQuestIds = {}
for questId in pairs(QuestiePlayer.currentQuestlog) do
if questId and questId > 0 and (not gameQuestIds[questId]) then
-- Typed check: a stray string key (saved variables have produced them) would other-
-- wise error on the comparison and take the whole pass down with it.
if type(questId) == "number" and questId > 0 and (not gameQuestIds[questId]) then
removedQuestIds[#removedQuestIds + 1] = questId
end
end
@@ -679,7 +685,12 @@ function _QuestEventHandler:CleanupRemovedQuestsFallback()
local wasTurnedIn = questLog[questId] and questLog[questId].state == QUEST_LOG_STATES.QUEST_TURNED_IN
local wasAlreadyComplete = Questie.db.char.complete and Questie.db.char.complete[questId]
local completeAtRemoval = QuestieDB.IsComplete(questId)
local shouldComplete = wasTurnedIn or wasAlreadyComplete or completeAtRemoval == 1
-- The server's own record, and the only one that knows anything about a quest the
-- database has never heard of: QuestieDB.IsComplete cannot answer for those, so an
-- Ascension quest the server finished by itself would otherwise be filed as abandoned.
local serverFlaggedComplete = IsQuestFlaggedCompleted and IsQuestFlaggedCompleted(questId)
local shouldComplete = wasTurnedIn or wasAlreadyComplete or completeAtRemoval == 1 or
serverFlaggedComplete
QuestLogCache.RemoveQuest(questId)
QuestieQuest:SetObjectivesDirty(questId)