From d92ae93870028f4e0829b6b1446565543165b758 Mon Sep 17 00:00:00 2001 From: Xurkon Date: Mon, 8 Jun 2026 08:00:15 -0500 Subject: [PATCH] fix(learner): seed objective pins on accept; handle monster objectives MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit OnQuestAccepted now seeds objective pins directly from the SavedVariables learner payload (objIndex) on accept in learner mode, instead of waiting for quest-log text sync — so quests like 8325 spawn pins immediately when the objective mapping already exists. The accept-time ID lookup is widened from killcredit to also cover monster objectives, and falls back to objData.Id when no IdList is present. --- CHANGELOG.md | 1 + Modules/QuestieLearner.lua | 43 +++++++++++++++++++++++++++++++++----- 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2fbda6b..b71eb21 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ - **[Tooltip - Item ID Always Shown]** `AddItemDataToTooltip` previously gated the "Item ID" line on the item having a registered quest-objective tooltip — for items that are not part of any quest objective (e.g. trade goods, vendor trash, quest-start items with no other Questie data attached), the option to show IDs had no visible effect. The line is now added for every item hover when the option is enabled, mirroring the NPC/Object tooltip behavior. Also switched the call to `self:AddDoubleLine` so the ID lands on the actual frame that fired `OnTooltipSetItem` (which can be `ItemRefTooltip` for chat links, not just `GameTooltip`). - **[Tooltip - Item Starts Quest]** Item tooltips now surface a "Drops a quest !" line with the quest title when the item has a non-zero `startQuest` value in the static DB / Ascension override table and the player does not already have the quest (active or turned in). The item→quest relationship is a build-time DB field — we never know it ahead of runtime observation — so it is read directly from `QueryItemSingle` at hover time. The line uses `QuestieLib:GetColoredQuestName` so the quest title respects the same level/complete state formatting the rest of Questie uses. - **[QuestieDB - Auto Mode Learner Enrichment]** In `auto` data-source mode, `QuestieDB.GetQuest` now overlays the SavedVariables learner payload on top of the static DB record, filling only fields the static record leaves `nil` and deep-merging `objectives`/`objIndex`. This fixes quests like 8325 where the shipped DB carries only a stub record but QuestieLearner holds the real objective mapping — previously the stub blocked the learned objectives from ever surfacing. Learner data never clobbers a present static value, so it strictly enriches and cannot regress shipped data. +- **[QuestieLearner - Accept-Time Objective Pin Seeding]** `OnQuestAccepted` now seeds objective pins directly from the SavedVariables learner payload (`objIndex`) the moment a quest is accepted in learner mode, instead of waiting for quest-log text sync. This makes quests like 8325 spawn pins immediately on accept when the objective mapping already exists. The accept-time ID lookup was also widened from `killcredit` to also cover `monster` objectives, and now falls back to `objData.Id` when no `IdList` is present, catching cases where the quest-log text does not normalize cleanly to the NPC name. ### Tooltip diff --git a/Modules/QuestieLearner.lua b/Modules/QuestieLearner.lua index c59aaef..47b6ee4 100644 --- a/Modules/QuestieLearner.lua +++ b/Modules/QuestieLearner.lua @@ -3550,13 +3550,19 @@ function QuestieLearner:OnQuestAccepted(firstArg, secondArg) if targetName and targetName ~= "" then local npcId = nil local objectId = nil - -- For killcredit, try ID-based lookup first using quest objectives data - if objType == "killcredit" then + -- For monster/killcredit objectives, try ID-based lookup first using quest objectives data. + -- This catches accept-time pins before the first kill event for quests like 8325, + -- where the quest log text may not normalize cleanly to the NPC name. + if objType == "killcredit" or objType == "monster" then local quest = QuestieDB and QuestieDB.GetQuest and QuestieDB.GetQuest(questId) if quest and quest.ObjectiveData and quest.ObjectiveData[j] then local objData = quest.ObjectiveData[j] - if objData.IdList then - for _, possibleId in ipairs(objData.IdList) do + local candidateIds = objData.IdList + if not candidateIds and objData.Id and objData.Id > 0 then + candidateIds = { objData.Id } + end + if candidateIds then + for _, possibleId in ipairs(candidateIds) do if possibleId and possibleId > 0 then local npc = QuestieDB:GetNPC(possibleId) if npc and npc.name and string.lower(npc.name) == string.lower(targetName) then @@ -3567,7 +3573,7 @@ function QuestieLearner:OnQuestAccepted(firstArg, secondArg) end -- Fallback: try first valid ID in the list even if name doesn't match if not npcId then - for _, possibleId in ipairs(objData.IdList) do + for _, possibleId in ipairs(candidateIds) do if possibleId and possibleId > 0 then local npc = QuestieDB:GetNPC(possibleId) if npc then @@ -3615,10 +3621,37 @@ function QuestieLearner:OnQuestAccepted(firstArg, secondArg) end end + -- In learner mode, seed objective pins directly from the SavedVariables payload. + -- This bypasses quest-log text sync timing and ensures quests like 8325 spawn pins + -- immediately on accept when the objective mapping already exists in QuestieLearnerDB. + if GetDataSourceMode() == "learner" then + local learnedQuest = Questie and Questie.dbLearner and Questie.dbLearner.global and Questie.dbLearner.global.quests and Questie.dbLearner.global.quests[questId] + if learnedQuest and learnedQuest.objIndex then + local objIndex, entry = next(learnedQuest.objIndex) + while objIndex do + if entry and entry.id then + local entryId = entry.id + if type(entryId) == "table" then + entryId = entryId[1] + end + if entryId and entryId > 0 then + if entry.type == "object" then + self:LearnQuestObjectiveObject(questId, entryId, entry.text or entry.Text or "", objIndex) + else + self:LearnQuestObjectiveNPC(questId, entryId, entry.text or entry.Text or "", objIndex) + end + end + end + objIndex, entry = next(learnedQuest.objIndex, objIndex) + end + end + end + -- Associate the quest giver: prefer live UnitGUID("npc"), fall back to last gossip entity -- (for Objectives Board quests, GOSSIP_CLOSED fires before QUEST_ACCEPTED so "npc" is nil) local npcGuid = UnitGUID("npc") local giverEntity = nil + if npcGuid then local entityId, unitType = self:ResolveNpcIdFromGuidAndName(npcGuid, UnitName("npc")) if entityId and entityId > 0 then