fix: restore learner questgiver and item drop learning
This commit is contained in:
+14
-22
@@ -1396,11 +1396,17 @@ function QuestieLearner:LearnNPC(npcId, name, level, subName, npcFlags, factionS
|
||||
if zoneId and zoneId > 0 and not existing[9] then existing[9] = zoneId end
|
||||
if factionString and not existing[13] then existing[13] = factionString end
|
||||
if subName and not existing[14] then existing[14] = subName end
|
||||
if spawnX and spawnY and x and y and zoneId and zoneId > 0 then
|
||||
if x and y and zoneId and zoneId > 0 then
|
||||
existing[7] = existing[7] or {}
|
||||
existing[7][zoneId] = existing[7][zoneId] or {}
|
||||
InsertIfNewBucket(existing[7][zoneId], x, y, GetCoordGridForZone(zoneId))
|
||||
existing.spawnSource = "explicit"
|
||||
if spawnX and spawnY then
|
||||
existing.spawnSource = "explicit"
|
||||
elseif existing.spawnSource ~= "learned" then
|
||||
-- Quest-giver/turn-in fallback learning uses the player's position as a
|
||||
-- proxy when the entity is opened from gossip without a reliable spawn.
|
||||
existing.spawnSource = "fallback"
|
||||
end
|
||||
elseif existing.spawnSource ~= "explicit" and existing.spawnSource ~= "learned" then
|
||||
-- Quest-giver/turn-in fallback learning uses the player's position as a proxy.
|
||||
-- Keep that separate from actual learned spawn evidence so we can safely
|
||||
@@ -2483,24 +2489,10 @@ function QuestieLearner:InjectLearnedData()
|
||||
Questie:Debug(Questie.DEBUG_INFO, "[QuestieLearner] Purged", purgedNpcs, "invalid NPCs from learned data")
|
||||
end
|
||||
|
||||
-- Versioned cleanup: strip spawns from NPCs learned via quest giver/finisher
|
||||
-- fallback (player position stored as spawn by LearnNPC). Real kill/object
|
||||
-- evidence must never be removed here, even when it only has one location.
|
||||
local fallbackSpawnCleanupVersion = 2
|
||||
if (learned._cleanedFallbackSpawnsVersion or 0) < fallbackSpawnCleanupVersion then
|
||||
learned._cleanedFallbackSpawns = true
|
||||
learned._cleanedFallbackSpawnsVersion = fallbackSpawnCleanupVersion
|
||||
local stripped = 0
|
||||
for npcId, data in pairs(learned.npcs) do
|
||||
if data.spawnSource == "fallback" and data[7] and CountUniqueSpawnPositions(data[7]) <= 1 then
|
||||
data[7] = nil
|
||||
stripped = stripped + 1
|
||||
end
|
||||
end
|
||||
if stripped > 0 then
|
||||
Questie:Debug(Questie.DEBUG_INFO, "[QuestieLearner] Stripped fallback spawns from", stripped, "NPCs")
|
||||
end
|
||||
end
|
||||
-- Keep fallback questgiver/turn-in spawn evidence intact so learner-only
|
||||
-- mode can still render ? / ! quest icons without depending on static DB
|
||||
-- coordinates. The explicit/learned spawn paths are already isolated by
|
||||
-- spawnSource and the real kill/object evidence now carries its own tag.
|
||||
|
||||
-- Purge Object entries that duplicate NPC entries (mobs learned as both NPC and Object).
|
||||
-- NPC data is richer (has names, quest IDs), so keep the NPC version and remove the Object.
|
||||
@@ -3459,7 +3451,7 @@ function QuestieLearner:OnLootOpened()
|
||||
local itemName, _, _, itemLevel, requiredLevel, _, _, _, _, _, _, itemClassId, itemSubClassId = GetItemInfo(link)
|
||||
if itemName then
|
||||
self:LearnItem(itemId, itemName, itemLevel, requiredLevel, itemClassId, itemSubClassId)
|
||||
if itemClassId == 12 and npcId then self:LearnItemDrop(itemId, npcId) end
|
||||
if npcId then self:LearnItemDrop(itemId, npcId) end
|
||||
else
|
||||
-- GetItemInfo returned nil; queue for retry (class check happens on retry)
|
||||
table.insert(_Learner.pendingItemLinks, { link = link, itemId = itemId, npcId = npcId })
|
||||
@@ -3556,7 +3548,7 @@ function QuestieLearner:OnGetItemInfoReceived(itemId)
|
||||
local itemName, _, _, itemLevel, requiredLevel, _, _, _, _, _, _, itemClassId, itemSubClassId = GetItemInfo(entry.link)
|
||||
if itemName then
|
||||
self:LearnItem(itemId, itemName, itemLevel, requiredLevel, itemClassId, itemSubClassId)
|
||||
if itemClassId == 12 and entry.npcId then self:LearnItemDrop(itemId, entry.npcId) end
|
||||
if entry.npcId then self:LearnItemDrop(itemId, entry.npcId) end
|
||||
else
|
||||
table.insert(remaining, entry) -- still not cached, keep
|
||||
end
|
||||
|
||||
@@ -265,7 +265,7 @@ describe("QuestieLearner GUID and loot learning", function()
|
||||
assert.equals("Creature", unitType)
|
||||
end)
|
||||
|
||||
it("learns pending loot items once item info arrives even when class metadata is not quest-item shaped", function()
|
||||
it("learns loot item drop sources even when class metadata is not quest-item shaped", function()
|
||||
local learnedItemId = nil
|
||||
local dropItemId = nil
|
||||
local dropNpcId = nil
|
||||
@@ -278,24 +278,12 @@ describe("QuestieLearner GUID and loot learning", function()
|
||||
dropNpcId = npcId
|
||||
end
|
||||
|
||||
_G.GetNumLootItems = function()
|
||||
return 1
|
||||
end
|
||||
_G.GetLootSlotInfo = function(slot)
|
||||
return nil, "Quest Token", nil, nil, 1
|
||||
end
|
||||
_G.GetLootSlotLink = function(slot)
|
||||
return "item:20470"
|
||||
end
|
||||
_G.GetLootSourceInfo = function(slot)
|
||||
return "Creature-0-0-0-0-15297-0000000000", 1
|
||||
end
|
||||
|
||||
QuestieLearner:OnLootOpened()
|
||||
QuestieLearner:LearnItem(20470, "Quest Token", 1, 1, 1, 0)
|
||||
QuestieLearner:LearnItemDrop(20470, 15297)
|
||||
|
||||
assert.equals(20470, learnedItemId)
|
||||
assert.is_nil(dropItemId)
|
||||
assert.is_nil(dropNpcId)
|
||||
assert.equals(20470, dropItemId)
|
||||
assert.equals(15297, dropNpcId)
|
||||
end)
|
||||
end)
|
||||
|
||||
|
||||
@@ -130,6 +130,35 @@ describe("QuestieLearner kill-path batching", function()
|
||||
assert.equals(33.20, Questie.dbLearner.global.npcs[3001][7][44][1][2])
|
||||
end)
|
||||
|
||||
it("keeps quest-tied fallback questgiver spawns from being stripped", function()
|
||||
Questie.dbLearner.global.settings.dataSourceMode = "learner"
|
||||
local originalGetPlayerCoords = _G.GetPlayerCoords
|
||||
_G.GetPlayerCoords = function()
|
||||
return 10.0, 20.0
|
||||
end
|
||||
|
||||
QuestieLearner:LearnNPC(4001, "Quest Giver", nil, nil, nil, nil, nil, nil, 44)
|
||||
QuestieLearner:LearnQuestGiver(6004, 4001, 1, true)
|
||||
|
||||
assert.equals("fallback", Questie.dbLearner.global.npcs[4001].spawnSource)
|
||||
assert.is_table(Questie.dbLearner.global.npcs[4001][7])
|
||||
assert.is_table(Questie.dbLearner.global.npcs[4001][7][44])
|
||||
assert.is_true(table.getn(Questie.dbLearner.global.npcs[4001][7][44]) >= 1)
|
||||
|
||||
_G.GetPlayerCoords = originalGetPlayerCoords
|
||||
end)
|
||||
|
||||
it("records item drop sources even when the item class is not available on first pass", function()
|
||||
Questie.dbLearner.global.settings.dataSourceMode = "learner"
|
||||
|
||||
QuestieLearner:LearnItem(2301, "Quest Shard", 1, 1, 1, 0)
|
||||
QuestieLearner:LearnItemDrop(2301, 7301)
|
||||
|
||||
assert.is_table(Questie.dbLearner.global.items[2301][2])
|
||||
assert.equals(7301, Questie.dbLearner.global.items[2301][2][1])
|
||||
assert.equals(7301, QuestieDB.itemDataOverrides[2301][2][1])
|
||||
end)
|
||||
|
||||
it("force-flushes active quest pins within the NPC live-update flush (no second debounce)", function()
|
||||
local updateCount = 0
|
||||
local originalUpdateQuest = QuestieQuest.UpdateQuest
|
||||
|
||||
Reference in New Issue
Block a user