From f9b19218cb4cedd8792d33a35ec293e951016f28 Mon Sep 17 00:00:00 2001 From: Xurkon Date: Wed, 10 Jun 2026 19:27:56 -0500 Subject: [PATCH] fix(quest): snapshot completion at QUEST_REMOVED so turn-ins are not misclassified as abandoned (#9) Some Ascension turn-ins (crafting/auto-complete) fire QUEST_REMOVED with no preceding QUEST_TURNED_IN, so the 1s abandon timer runs after QuestLogCache.RemoveQuest has cleared the quest, making IsComplete return 0 and the turned-in quest get marked abandoned -- its objective pins and turn-in ? then linger. Capture IsComplete at QUEST_REMOVED time and use that snapshot in MarkQuestAsAbandoned. --- CHANGELOG.md | 1 + Modules/Quest/QuestEventHandler.lua | 19 +++++++++++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e3a5195..ab9db72 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,7 @@ ### Bug Fixes +- **[Quest - Turned-In Quests Misclassified As Abandoned]** (#9) On Ascension some turn-ins (notably crafting/auto-complete quests) fire `QUEST_REMOVED` without a preceding `QUEST_TURNED_IN`, so Questie's 1-second abandon timer ran `MarkQuestAsAbandoned`. By then `QuestLogCache.RemoveQuest` had already cleared the quest, so the `IsComplete` check returned 0 and the *turned-in* quest was treated as abandoned — leaving its objective pins and turn-in `?` lingering on the map and minimap. The completion state is now snapshotted at `QUEST_REMOVED` time (while the quest is still in the cache) and used by the abandon timer, so a quest that was complete at removal is correctly completed (pins/`?` cleared) rather than abandoned. - **[Map - Minimap Range Cutoff No Longer Clips Visible Icons]** (#17) The "Minimap Icon Range Cutoff" added in a prior build hid every quest icon beyond its yard value *before* checking whether the icon was within the minimap's visible circle. Because the minimap's view radius is 133–466 yards depending on zoom, a cutoff of 100 (the default) hid icons that were clearly on the minimap — they only appeared once the player was very close. The cutoff now only clips icons that fall *outside* the minimap's visible radius: in HBD's pin renderer it is gated on `dist > 1` (outside the visible circle), and in `QuestieMap`'s minimap `FadeLogic` the effective cutoff is raised to at least the current minimap view radius (read from the new `HBDPins:GetMinimapRadius()`). Icons within the visible minimap always show again; the cutoff still controls how far edge-floating icons reach for far-apart objectives when zoomed out. - **[Tooltip - Stop Eating ID Lines & Other Addons' Tooltip Text]** `HideAscensionQuestLines` (which hides Ascension's injected quest-objective progress text from tooltips) was too greedy: once it found an objective line (e.g. `0/8 Arcane Wraith slain`) it kept hiding every following non-indented line until an indented one. Because Questie's own `Item ID`/`NPC ID`/`Object ID` lines and other addons' additions (e.g. an item-count overlay) are appended at the *bottom* of the tooltip — after the objective block — a refresh pass wiped them too, so the ID you needed to report data never showed. It now hides only the lines that themselves match an Ascension objective pattern (`N/M`, `[N] ...`, `- N/M ...`) and never the trailing lines, so IDs and other addons' text are left intact. - **[Learner - Don't Purge NPCs With Useful State But No Spawns]** The `InjectLearnedData` purge loop was deleting entire NPC entries from `Questie.dbLearner.global.npcs` whenever `data[7]` (spawns) was empty, even if the entry still had a name, home zone, recorded kills, or quest references. This caused learner data to silently disappear on `/reload` for NPCs that had been learned but never killed in a position the learner could record (e.g. party-kill position attribution fix now passes nil coords for uncredited kills). Now only purges when ALL of name, zone, kills, and quest references are missing. Entries with other useful state get `data[7] = nil` instead so the row survives. diff --git a/Modules/Quest/QuestEventHandler.lua b/Modules/Quest/QuestEventHandler.lua index c87b9bd..68f6159 100644 --- a/Modules/Quest/QuestEventHandler.lua +++ b/Modules/Quest/QuestEventHandler.lua @@ -419,9 +419,18 @@ function _QuestEventHandler:QuestRemoved(questId) end -- QUEST_REMOVED can fire before QUEST_TURNED_IN. If QUEST_TURNED_IN is not called after X seconds the quest - -- was abandoned + -- was abandoned. + -- + -- Capture the completion state NOW, while the quest is still in QuestLogCache. On Ascension some + -- turn-ins (notably crafting/auto-complete quests) never fire QUEST_TURNED_IN, only QUEST_REMOVED, + -- so MarkQuestAsAbandoned runs a second later — by which point the cache has been cleared and + -- IsComplete can no longer tell the quest was finished, causing a turned-in quest to be misclassified + -- as abandoned (its objective pins / turn-in "?" then linger). Snapshot it here so the timer can + -- treat a quest that was complete at removal as a completion. + local completeAtRemoval = QuestieDB.IsComplete(questId) questLog[questId] = { state = QUEST_LOG_STATES.QUEST_REMOVED, + completeAtRemoval = completeAtRemoval, timer = C_Timer.NewTicker(1, function() _QuestEventHandler:MarkQuestAsAbandoned(questId) end, 1) @@ -448,9 +457,15 @@ function _QuestEventHandler:MarkQuestAsAbandoned(questId) -- If objectives were complete, treat it as a completion (not abandonment) so objective pins get hidden. local objectivesWereComplete = false local quest = QuestieDB.GetQuest(questId) + -- Prefer the completion state snapshotted at QUEST_REMOVED time (before the cache was + -- cleared); fall back to a live IsComplete if no snapshot was captured. This reliably + -- catches turn-ins that skipped QUEST_TURNED_IN so they are completed, not abandoned. + if questEntry.completeAtRemoval == 1 then + objectivesWereComplete = true + end if quest then local isComplete = QuestieDB.IsComplete(questId) - objectivesWereComplete = (isComplete == 1) + objectivesWereComplete = objectivesWereComplete or (isComplete == 1) -- Check for Ebonhold auto-complete quests which might be removed before IsComplete returns 1 local desc = quest.Description