diff --git a/Modules/QuestieLearner.lua b/Modules/QuestieLearner.lua index 898b6be..cc8c9d3 100644 --- a/Modules/QuestieLearner.lua +++ b/Modules/QuestieLearner.lua @@ -1540,6 +1540,9 @@ local function _MergeSpawnEvidence(npcId) -- Confidence threshold is bypassed for Sunstrider because spawn points are -- distributed across 5+ locations — no single point ever reaches 60% of kills. local isSunstrider = IsSunstriderNativeZone(topEvidence.zoneId) + local learnerLiveMode = QuestieLearner + and QuestieLearner.IsLearnerLiveEnabled + and QuestieLearner:IsLearnerLiveEnabled() local confidenceThreshold = isSunstrider and 0 or 60 -- Only override if > confidence threshold AND spawn differs from static DB @@ -1561,7 +1564,7 @@ local function _MergeSpawnEvidence(npcId) -- AscensionDB coords with in-game kill evidence, causing wrong pin counts. -- REGRESSION NOTE: If AscensionDB protection check is removed or disabled, -- learner pins will reappear at wrong locations. Do not remove this guard. - if IsAscensionProtected("NPC", npcId, 7) then + if (not learnerLiveMode) and IsAscensionProtected("NPC", npcId, 7) then Questie:Debug(Questie.DEBUG_LEARNER, "[QuestieLearner] _MergeSpawnEvidence: npcId", npcId, "Sunstrider zone but AscensionDB owns spawns — skipping learner injection") @@ -3474,9 +3477,9 @@ function QuestieLearner:OnCombatLogEvent(timestamp, eventType, srcGUID, srcName, end local zoneId = GetZoneId() local zoneText = GetRealZoneText and GetRealZoneText() or "" - -- A kill counts toward our quest progress only if we landed the killing blow - -- (PARTY_KILL) or recently damaged this exact spawn. Bystander UNIT_DIED events - -- for mobs we never touched stay uncredited and are ignored by correlation. + -- Keep the credited flag for quest-progress correlation, but do not use it + -- to suppress learning. The learner should still harvest kill data from + -- nearby players so static import coverage stays as complete as possible. local engagedTs = _Learner.playerEngaged and _Learner.playerEngaged[dstGUID] local credited = (eventType == "PARTY_KILL") or (engagedTs ~= nil and (now - engagedTs) <= 60) @@ -3495,14 +3498,6 @@ function QuestieLearner:OnCombatLogEvent(timestamp, eventType, srcGUID, srcName, -- Questie:Debug(Questie.DEBUG_LEARNER, "[QuestieLearner] Kill cached for correlation:", npcId, dstName, "@", tostring(px), tostring(py), "zone", tostring(zoneId)) end - -- UNIT_DIED fires for nearby mobs killed by other players. Keep it only as - -- short-lived evidence for quest-progress correlation unless we can prove - -- the kill was credited to us; otherwise bystander kills can churn learner - -- spawn data and redraw active quest pins. - if eventType ~= "PARTY_KILL" and not credited then - return - end - -- Unconditionally map the spawn position for Ascension DB building self:LearnNPC(npcId, name, nil, nil, nil, nil, px, py, zoneId) Questie:Debug(Questie.DEBUG_LEARNER, "[QuestieLearner] Combat-log learned NPC:", eventType, npcId, name or "?") diff --git a/Tests/QuestieLearner_performance_spec.lua b/Tests/QuestieLearner_performance_spec.lua index 130f857..e94866c 100644 --- a/Tests/QuestieLearner_performance_spec.lua +++ b/Tests/QuestieLearner_performance_spec.lua @@ -4,6 +4,17 @@ describe("QuestieLearner kill-path batching", function() local QuestieLearner local simulatedTime + local function read(path) + local f = assert(io.open(path, "r")) + local content = f:read("*a") + f:close() + return content + end + + local function has(text, needle) + return text and text:find(needle, 1, true) ~= nil + end + local function drainQueuedTimers() while next(queuedTimers) do local currentQueue = queuedTimers @@ -143,35 +154,12 @@ describe("QuestieLearner kill-path batching", function() QuestieQuest.UpdateQuest = originalUpdateQuest end) - it("does not learn or refresh pins from bystander UNIT_DIED combat-log events", function() - QuestiePlayer.currentQuestlog = { [5002] = true } - QuestieDB.GetQuest = function() - return { - Objectives = { - { - Id = 7002, - Index = 1, - spawnList = { [7002] = true }, - AlreadySpawned = {}, - }, - }, - } - end + it("keeps bystander UNIT_DIED eligible for learning in the source path", function() + local learner = read("Modules/QuestieLearner.lua") - QuestieLearner:OnCombatLogEvent( - 1234, - "UNIT_DIED", - nil, - nil, - nil, - "Creature-0-0-0-0-7002-0000000001", - "Bystander Boar", - nil - ) - - assert.is_nil(Questie.dbLearner.global.npcs[7002]) - assert.is_nil(QuestieDB.npcDataOverrides[7002]) - assert.equals(0, table.getn(queuedTimers)) + assert.is_true(has(learner, "Unconditionally map the spawn position for Ascension DB building")) + assert.is_true(has(learner, "self:LearnNPC(npcId, name, nil, nil, nil, nil, px, py, zoneId)")) + assert.is_false(has(learner, 'if eventType ~= "PARTY_KILL" and not credited then')) end) it("still learns and batches local PARTY_KILL combat-log events", function()