diff --git a/Modules/QuestieLearner.lua b/Modules/QuestieLearner.lua index e262ab2..39ec5aa 100644 --- a/Modules/QuestieLearner.lua +++ b/Modules/QuestieLearner.lua @@ -3346,6 +3346,12 @@ function QuestieLearner:OnQuestComplete() local questId = GetQuestID and GetQuestID() if not questId or questId <= 0 then return end + _Learner.lastQuestComplete = { + id = questId, + ts = time(), + zoneId = GetZoneId(), + } + -- Get current zone for quest giver spawn data local zoneId = GetZoneId() @@ -3457,6 +3463,24 @@ local function ResolveAcceptedQuestId(firstArg, secondArg) return nil end +local function ResolveTurnedInQuestId(rawQuestId) + if rawQuestId and type(rawQuestId) == "number" and rawQuestId > 0 then + if QuestieCompat.GetQuestLogIndexByID and QuestieCompat.GetQuestLogIndexByID(rawQuestId) then + return rawQuestId + end + if _Learner.lastQuestComplete and _Learner.lastQuestComplete.id == rawQuestId then + return rawQuestId + end + end + + local last = _Learner.lastQuestComplete + if last and last.id and last.ts and (time() - last.ts) <= 10 then + return last.id + end + + return nil +end + -- Fires when a quest is accepted. function QuestieLearner:OnQuestAccepted(firstArg, secondArg) Questie:Debug(Questie.DEBUG_INFO, "[QuestieLearner] OnQuestAccepted raw args: first=" .. tostring(firstArg) .. " second=" .. tostring(secondArg)) @@ -3607,7 +3631,7 @@ end function QuestieLearner:OnQuestTurnedIn(questId, xpReward, moneyReward) if not self:IsEnabled() then return end if not Questie.dbLearner.global.settings.learnQuests then return end - questId = tonumber(questId) + questId = ResolveTurnedInQuestId(tonumber(questId)) if not questId or questId <= 0 then return end local data = {} diff --git a/Tests/QuestieLearnerDataSourceMode_spec.lua b/Tests/QuestieLearnerDataSourceMode_spec.lua index 60fd017..fd63a2d 100644 --- a/Tests/QuestieLearnerDataSourceMode_spec.lua +++ b/Tests/QuestieLearnerDataSourceMode_spec.lua @@ -270,6 +270,68 @@ describe("QuestieLearner quest accept resolution", function() end) end) +describe("QuestieLearner quest turn-in resolution", function() + local QuestieLearner + local originalLearnQuest + local originalGetQuestID + local originalGetRewardText + local originalUnitGUID + + before_each(function() + dofile("Tests/wow_api_mock.lua") + + originalGetQuestID = _G.GetQuestID + originalGetRewardText = _G.GetRewardText + originalUnitGUID = _G.UnitGUID + + Questie.dbLearner.global.settings.enabled = true + Questie.dbLearner.global.settings.dataSourceMode = "learner" + + _G.GetQuestID = function() + return 4321 + end + _G.GetRewardText = function() + return "Reward text" + end + _G.UnitGUID = function() + return nil + end + + QuestieLearner = dofile("Modules/QuestieLearner.lua") + originalLearnQuest = QuestieLearner.LearnQuest + end) + + after_each(function() + QuestieLearner.LearnQuest = originalLearnQuest + _G.GetQuestID = originalGetQuestID + _G.GetRewardText = originalGetRewardText + _G.UnitGUID = originalUnitGUID + end) + + it("rejects malformed turn-in quest ids unless they resolve to a recent completion", function() + local capturedQuestId = nil + QuestieLearner.LearnQuest = function(self, questId, data) + capturedQuestId = questId + end + + QuestieLearner:OnQuestTurnedIn(545915281, nil, nil) + + assert.is_nil(capturedQuestId) + end) + + it("uses the recent quest-complete cache when the raw turn-in quest id is malformed", function() + local capturedQuestId = nil + QuestieLearner.LearnQuest = function(self, questId, data) + capturedQuestId = questId + end + + QuestieLearner:OnQuestComplete() + QuestieLearner:OnQuestTurnedIn(545915281, nil, nil) + + assert.equals(4321, capturedQuestId) + end) +end) + describe("QuestieLearner GUID and loot learning", function() local QuestieLearner local originalGetNPC