fix: gate learner item learning to quest items
This commit is contained in:
@@ -1195,12 +1195,21 @@ local function CrossLinkAfterQuest(questId)
|
||||
if qData[11] and qData[11] > 0 then
|
||||
local iData = learned.items[qData[11]]
|
||||
if iData then
|
||||
iData.questRelevant = true
|
||||
if not iData[5] then
|
||||
iData[5] = questId
|
||||
if liveEnabled and QuestieDB and QuestieDB.itemDataOverrides then
|
||||
local ovr = QuestieDB.itemDataOverrides[qData[11]] or {}
|
||||
QuestieDB.itemDataOverrides[qData[11]] = ovr
|
||||
if ovr[1] == nil and iData[1] ~= nil and not IsAscensionProtected("ITEM", qData[11], 1) then
|
||||
ovr[1] = iData[1]
|
||||
end
|
||||
if not ovr[5] then ovr[5] = questId end
|
||||
for k, v in pairs(iData) do
|
||||
if k ~= 1 and k ~= 5 and k ~= "mc" and ovr[k] == nil and not IsAscensionProtected("ITEM", qData[11], k) then
|
||||
ovr[k] = v
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1212,6 +1221,7 @@ local function CrossLinkAfterQuest(questId)
|
||||
local itemId = entry[1]
|
||||
local iData = learned.items[itemId]
|
||||
if iData and iData[2] then
|
||||
iData.questRelevant = true
|
||||
for _, dropNpcId in ipairs(iData[2]) do
|
||||
_AddToQuestObjective(qData, 1, dropNpcId, nil, qOvr, questId)
|
||||
end
|
||||
@@ -2097,11 +2107,81 @@ end
|
||||
-- Item learning
|
||||
------------------------------------------------------------------------
|
||||
|
||||
local function IsQuestRelevantItem(itemId, itemClass)
|
||||
local learned = Questie and Questie.dbLearner and Questie.dbLearner.global
|
||||
if not learned or not learned.quests then
|
||||
return false
|
||||
end
|
||||
|
||||
if itemClass == 12 then
|
||||
return true
|
||||
end
|
||||
|
||||
for _, qData in pairs(learned.quests) do
|
||||
if qData[11] == itemId then
|
||||
return true
|
||||
end
|
||||
if qData[10] and qData[10][3] then
|
||||
for _, entry in ipairs(qData[10][3]) do
|
||||
if entry[1] == itemId then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
if qData[2] and qData[2][3] then
|
||||
for _, entry in ipairs(qData[2][3]) do
|
||||
if entry[1] == itemId then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
local function HasQuestReferences(itemId)
|
||||
local learned = Questie and Questie.dbLearner and Questie.dbLearner.global
|
||||
if not learned or not learned.quests then
|
||||
return false
|
||||
end
|
||||
|
||||
local itemData = learned.items and learned.items[itemId]
|
||||
if itemData and itemData.questRelevant then
|
||||
return true
|
||||
end
|
||||
|
||||
for _, qData in pairs(learned.quests) do
|
||||
if qData[11] == itemId then
|
||||
return true
|
||||
end
|
||||
if qData[10] and qData[10][3] then
|
||||
for _, entry in ipairs(qData[10][3]) do
|
||||
if entry[1] == itemId then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
if qData[2] and qData[2][3] then
|
||||
for _, entry in ipairs(qData[2][3]) do
|
||||
if entry[1] == itemId then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
function QuestieLearner:LearnItem(itemId, name, itemLevel, requiredLevel, itemClass, itemSubClass)
|
||||
if not self:IsEnabled() then return end
|
||||
if not Questie.dbLearner.global.settings.learnItems then return end
|
||||
itemId = tonumber(itemId)
|
||||
if not itemId or itemId <= 0 then return end
|
||||
if not IsQuestRelevantItem(itemId, itemClass) then
|
||||
return false
|
||||
end
|
||||
|
||||
local existing = Questie.dbLearner.global.items[itemId]
|
||||
local isNew = existing == nil
|
||||
@@ -2110,6 +2190,10 @@ function QuestieLearner:LearnItem(itemId, name, itemLevel, requiredLevel, itemCl
|
||||
Questie.dbLearner.global.items[itemId] = existing
|
||||
end
|
||||
|
||||
if itemClass == 12 or HasQuestReferences(itemId) then
|
||||
existing.questRelevant = true
|
||||
end
|
||||
|
||||
if name and not existing[1] then existing[1] = name end
|
||||
if itemLevel and itemLevel > 0 and not existing[9] then existing[9] = itemLevel end
|
||||
if requiredLevel and requiredLevel > 0 and not existing[10] then existing[10] = requiredLevel end
|
||||
@@ -2138,6 +2222,7 @@ function QuestieLearner:LearnItem(itemId, name, itemLevel, requiredLevel, itemCl
|
||||
CrossLinkAfterItem(itemId)
|
||||
end
|
||||
_Learner:BroadcastIfCommsAvailable("ITEM", itemId, existing)
|
||||
return true
|
||||
end
|
||||
|
||||
function QuestieLearner:LearnItemDrop(itemId, npcId)
|
||||
@@ -2713,9 +2798,11 @@ function QuestieLearner:InjectLearnedData()
|
||||
if type(itemId) == "string" and iid then
|
||||
itemIdsToFix[itemId] = iid
|
||||
end
|
||||
if not QuestieDB.itemDataOverrides[iid or itemId] then
|
||||
QuestieDB.itemDataOverrides[iid or itemId] = data
|
||||
itemCount = itemCount + 1
|
||||
if HasQuestReferences(iid or itemId) then
|
||||
if not QuestieDB.itemDataOverrides[iid or itemId] then
|
||||
QuestieDB.itemDataOverrides[iid or itemId] = data
|
||||
itemCount = itemCount + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
for old, new in pairs(itemIdsToFix) do
|
||||
@@ -3474,8 +3561,8 @@ function QuestieLearner:OnLootOpened()
|
||||
if itemId and itemId > 0 then
|
||||
local itemName, _, _, itemLevel, requiredLevel, _, _, _, _, _, _, itemClassId, itemSubClassId = GetItemInfo(link)
|
||||
if itemName then
|
||||
self:LearnItem(itemId, itemName, itemLevel, requiredLevel, itemClassId, itemSubClassId)
|
||||
if npcId then self:LearnItemDrop(itemId, npcId) end
|
||||
local learnedItem = self:LearnItem(itemId, itemName, itemLevel, requiredLevel, itemClassId, itemSubClassId)
|
||||
if learnedItem and 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 })
|
||||
@@ -3571,8 +3658,8 @@ function QuestieLearner:OnGetItemInfoReceived(itemId)
|
||||
if entry.itemId == itemId then
|
||||
local itemName, _, _, itemLevel, requiredLevel, _, _, _, _, _, _, itemClassId, itemSubClassId = GetItemInfo(entry.link)
|
||||
if itemName then
|
||||
self:LearnItem(itemId, itemName, itemLevel, requiredLevel, itemClassId, itemSubClassId)
|
||||
if entry.npcId then self:LearnItemDrop(itemId, entry.npcId) end
|
||||
local learnedItem = self:LearnItem(itemId, itemName, itemLevel, requiredLevel, itemClassId, itemSubClassId)
|
||||
if learnedItem and entry.npcId then self:LearnItemDrop(itemId, entry.npcId) end
|
||||
else
|
||||
table.insert(remaining, entry) -- still not cached, keep
|
||||
end
|
||||
@@ -4540,6 +4627,9 @@ function QuestieLearner:_ApplyIncomingNetworkMerge(typ, id, d, op)
|
||||
store = Questie.dbLearner.global.quests
|
||||
elseif typ == "ITEM" then
|
||||
if not Questie.dbLearner.global.settings.learnItems then return false end
|
||||
if not ((type(d) == "table" and d.questRelevant) or HasQuestReferences(id)) then
|
||||
return false
|
||||
end
|
||||
store = Questie.dbLearner.global.items
|
||||
elseif typ == "OBJECT" then
|
||||
if not Questie.dbLearner.global.settings.learnObjects then return false end
|
||||
|
||||
@@ -289,24 +289,38 @@ describe("QuestieLearner GUID and loot learning", function()
|
||||
assert.equals("Creature", unitType)
|
||||
end)
|
||||
|
||||
it("learns loot item drop sources even when class metadata is not quest-item shaped", function()
|
||||
it("ignores non-quest loot items and only learns quest-item drops", function()
|
||||
local learnedItemId = nil
|
||||
local dropItemId = nil
|
||||
local dropNpcId = nil
|
||||
|
||||
QuestieLearner.LearnItem = function(self, itemId, name, itemLevel, requiredLevel, itemClassId, itemSubClassId)
|
||||
learnedItemId = itemId
|
||||
if itemClassId == 12 then
|
||||
learnedItemId = itemId
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
QuestieLearner.LearnItemDrop = function(self, itemId, npcId)
|
||||
dropItemId = itemId
|
||||
dropNpcId = npcId
|
||||
end
|
||||
|
||||
local originalGetItemInfo = _G.GetItemInfo
|
||||
_G.GetItemInfo = function(link)
|
||||
if link == "item:20470" then
|
||||
return "Quest Token", nil, nil, 1, 1, nil, nil, nil, nil, nil, nil, 1, 0
|
||||
end
|
||||
return originalGetItemInfo(link)
|
||||
end
|
||||
|
||||
QuestieLearner:OnLootOpened()
|
||||
|
||||
assert.equals(20470, learnedItemId)
|
||||
assert.equals(20470, dropItemId)
|
||||
assert.equals(15297, dropNpcId)
|
||||
assert.is_nil(learnedItemId)
|
||||
assert.is_nil(dropItemId)
|
||||
assert.is_nil(dropNpcId)
|
||||
|
||||
_G.GetItemInfo = originalGetItemInfo
|
||||
end)
|
||||
end)
|
||||
|
||||
|
||||
@@ -77,6 +77,7 @@ describe("QuestieLearner kill-path batching", function()
|
||||
npcCache = {
|
||||
[1001] = { name = "Cached Boar" },
|
||||
},
|
||||
itemCache = {},
|
||||
}
|
||||
QuestiePlayer.currentQuestlog = {}
|
||||
|
||||
@@ -141,20 +142,37 @@ describe("QuestieLearner kill-path batching", function()
|
||||
assert.equals(1, table.getn(Questie.dbLearner.global.npcs[4001][7][44]))
|
||||
end)
|
||||
|
||||
it("records item drop sources even when the item class is not available on first pass", function()
|
||||
it("ignores non-quest loot items so they do not pollute learner state", function()
|
||||
Questie.dbLearner.global.settings.dataSourceMode = "learner"
|
||||
QuestieDB.private.itemCache = {
|
||||
[2301] = { cached = true },
|
||||
}
|
||||
QuestieDB.private.itemCache = {}
|
||||
|
||||
QuestieLearner:LearnItem(2301, "Quest Shard", 1, 1, 1, 0)
|
||||
QuestieLearner:LearnItemDrop(2301, 7301)
|
||||
local learned = QuestieLearner:LearnItem(2301, "Quest Shard", 1, 1, 1, 0)
|
||||
|
||||
assert.is_table(Questie.dbLearner.global.items[2301][2])
|
||||
assert.equals(7301, Questie.dbLearner.global.items[2301][2][1])
|
||||
assert.is_false(learned)
|
||||
assert.is_nil(Questie.dbLearner.global.items[2301])
|
||||
assert.is_nil(QuestieDB.private.itemCache[2301])
|
||||
end)
|
||||
|
||||
it("keeps quest item drop sources when the item is a quest item", function()
|
||||
Questie.dbLearner.global.settings.dataSourceMode = "learner"
|
||||
local learned = QuestieLearner:LearnItem(2302, "Quest Shard", 1, 1, 12, 0)
|
||||
assert.is_true(learned)
|
||||
assert.is_true(Questie.dbLearner.global.items[2302].questRelevant)
|
||||
|
||||
QuestieLearner:LearnItemDrop(2302, 7301)
|
||||
|
||||
assert.is_table(Questie.dbLearner.global.items[2302][2])
|
||||
assert.equals(7301, Questie.dbLearner.global.items[2302][2][1])
|
||||
end)
|
||||
|
||||
it("rejects non-quest item network merges without quest references", function()
|
||||
Questie.dbLearner.global.settings.dataSourceMode = "learner"
|
||||
local changed = QuestieLearner:_ApplyIncomingNetworkMerge("ITEM", 2401, { [1] = "Arcane Sliver" }, "NEW")
|
||||
|
||||
assert.is_false(changed)
|
||||
assert.is_nil(Questie.dbLearner.global.items[2401])
|
||||
end)
|
||||
|
||||
it("clears cached quest data when learner adds questgiver links", function()
|
||||
Questie.dbLearner.global.settings.dataSourceMode = "learner"
|
||||
QuestieDB.private.questCache = {
|
||||
|
||||
Reference in New Issue
Block a user