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
|
if qData[11] and qData[11] > 0 then
|
||||||
local iData = learned.items[qData[11]]
|
local iData = learned.items[qData[11]]
|
||||||
if iData then
|
if iData then
|
||||||
|
iData.questRelevant = true
|
||||||
if not iData[5] then
|
if not iData[5] then
|
||||||
iData[5] = questId
|
iData[5] = questId
|
||||||
if liveEnabled and QuestieDB and QuestieDB.itemDataOverrides then
|
if liveEnabled and QuestieDB and QuestieDB.itemDataOverrides then
|
||||||
local ovr = QuestieDB.itemDataOverrides[qData[11]] or {}
|
local ovr = QuestieDB.itemDataOverrides[qData[11]] or {}
|
||||||
QuestieDB.itemDataOverrides[qData[11]] = ovr
|
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
|
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
|
end
|
||||||
end
|
end
|
||||||
@@ -1212,6 +1221,7 @@ local function CrossLinkAfterQuest(questId)
|
|||||||
local itemId = entry[1]
|
local itemId = entry[1]
|
||||||
local iData = learned.items[itemId]
|
local iData = learned.items[itemId]
|
||||||
if iData and iData[2] then
|
if iData and iData[2] then
|
||||||
|
iData.questRelevant = true
|
||||||
for _, dropNpcId in ipairs(iData[2]) do
|
for _, dropNpcId in ipairs(iData[2]) do
|
||||||
_AddToQuestObjective(qData, 1, dropNpcId, nil, qOvr, questId)
|
_AddToQuestObjective(qData, 1, dropNpcId, nil, qOvr, questId)
|
||||||
end
|
end
|
||||||
@@ -2097,11 +2107,81 @@ end
|
|||||||
-- Item learning
|
-- 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)
|
function QuestieLearner:LearnItem(itemId, name, itemLevel, requiredLevel, itemClass, itemSubClass)
|
||||||
if not self:IsEnabled() then return end
|
if not self:IsEnabled() then return end
|
||||||
if not Questie.dbLearner.global.settings.learnItems then return end
|
if not Questie.dbLearner.global.settings.learnItems then return end
|
||||||
itemId = tonumber(itemId)
|
itemId = tonumber(itemId)
|
||||||
if not itemId or itemId <= 0 then return end
|
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 existing = Questie.dbLearner.global.items[itemId]
|
||||||
local isNew = existing == nil
|
local isNew = existing == nil
|
||||||
@@ -2110,6 +2190,10 @@ function QuestieLearner:LearnItem(itemId, name, itemLevel, requiredLevel, itemCl
|
|||||||
Questie.dbLearner.global.items[itemId] = existing
|
Questie.dbLearner.global.items[itemId] = existing
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if itemClass == 12 or HasQuestReferences(itemId) then
|
||||||
|
existing.questRelevant = true
|
||||||
|
end
|
||||||
|
|
||||||
if name and not existing[1] then existing[1] = name 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 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
|
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)
|
CrossLinkAfterItem(itemId)
|
||||||
end
|
end
|
||||||
_Learner:BroadcastIfCommsAvailable("ITEM", itemId, existing)
|
_Learner:BroadcastIfCommsAvailable("ITEM", itemId, existing)
|
||||||
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function QuestieLearner:LearnItemDrop(itemId, npcId)
|
function QuestieLearner:LearnItemDrop(itemId, npcId)
|
||||||
@@ -2713,9 +2798,11 @@ function QuestieLearner:InjectLearnedData()
|
|||||||
if type(itemId) == "string" and iid then
|
if type(itemId) == "string" and iid then
|
||||||
itemIdsToFix[itemId] = iid
|
itemIdsToFix[itemId] = iid
|
||||||
end
|
end
|
||||||
if not QuestieDB.itemDataOverrides[iid or itemId] then
|
if HasQuestReferences(iid or itemId) then
|
||||||
QuestieDB.itemDataOverrides[iid or itemId] = data
|
if not QuestieDB.itemDataOverrides[iid or itemId] then
|
||||||
itemCount = itemCount + 1
|
QuestieDB.itemDataOverrides[iid or itemId] = data
|
||||||
|
itemCount = itemCount + 1
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
for old, new in pairs(itemIdsToFix) do
|
for old, new in pairs(itemIdsToFix) do
|
||||||
@@ -3474,8 +3561,8 @@ function QuestieLearner:OnLootOpened()
|
|||||||
if itemId and itemId > 0 then
|
if itemId and itemId > 0 then
|
||||||
local itemName, _, _, itemLevel, requiredLevel, _, _, _, _, _, _, itemClassId, itemSubClassId = GetItemInfo(link)
|
local itemName, _, _, itemLevel, requiredLevel, _, _, _, _, _, _, itemClassId, itemSubClassId = GetItemInfo(link)
|
||||||
if itemName then
|
if itemName then
|
||||||
self:LearnItem(itemId, itemName, itemLevel, requiredLevel, itemClassId, itemSubClassId)
|
local learnedItem = self:LearnItem(itemId, itemName, itemLevel, requiredLevel, itemClassId, itemSubClassId)
|
||||||
if npcId then self:LearnItemDrop(itemId, npcId) end
|
if learnedItem and npcId then self:LearnItemDrop(itemId, npcId) end
|
||||||
else
|
else
|
||||||
-- GetItemInfo returned nil; queue for retry (class check happens on retry)
|
-- GetItemInfo returned nil; queue for retry (class check happens on retry)
|
||||||
table.insert(_Learner.pendingItemLinks, { link = link, itemId = itemId, npcId = npcId })
|
table.insert(_Learner.pendingItemLinks, { link = link, itemId = itemId, npcId = npcId })
|
||||||
@@ -3571,8 +3658,8 @@ function QuestieLearner:OnGetItemInfoReceived(itemId)
|
|||||||
if entry.itemId == itemId then
|
if entry.itemId == itemId then
|
||||||
local itemName, _, _, itemLevel, requiredLevel, _, _, _, _, _, _, itemClassId, itemSubClassId = GetItemInfo(entry.link)
|
local itemName, _, _, itemLevel, requiredLevel, _, _, _, _, _, _, itemClassId, itemSubClassId = GetItemInfo(entry.link)
|
||||||
if itemName then
|
if itemName then
|
||||||
self:LearnItem(itemId, itemName, itemLevel, requiredLevel, itemClassId, itemSubClassId)
|
local learnedItem = self:LearnItem(itemId, itemName, itemLevel, requiredLevel, itemClassId, itemSubClassId)
|
||||||
if entry.npcId then self:LearnItemDrop(itemId, entry.npcId) end
|
if learnedItem and entry.npcId then self:LearnItemDrop(itemId, entry.npcId) end
|
||||||
else
|
else
|
||||||
table.insert(remaining, entry) -- still not cached, keep
|
table.insert(remaining, entry) -- still not cached, keep
|
||||||
end
|
end
|
||||||
@@ -4540,6 +4627,9 @@ function QuestieLearner:_ApplyIncomingNetworkMerge(typ, id, d, op)
|
|||||||
store = Questie.dbLearner.global.quests
|
store = Questie.dbLearner.global.quests
|
||||||
elseif typ == "ITEM" then
|
elseif typ == "ITEM" then
|
||||||
if not Questie.dbLearner.global.settings.learnItems then return false end
|
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
|
store = Questie.dbLearner.global.items
|
||||||
elseif typ == "OBJECT" then
|
elseif typ == "OBJECT" then
|
||||||
if not Questie.dbLearner.global.settings.learnObjects then return false end
|
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)
|
assert.equals("Creature", unitType)
|
||||||
end)
|
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 learnedItemId = nil
|
||||||
local dropItemId = nil
|
local dropItemId = nil
|
||||||
local dropNpcId = nil
|
local dropNpcId = nil
|
||||||
|
|
||||||
QuestieLearner.LearnItem = function(self, itemId, name, itemLevel, requiredLevel, itemClassId, itemSubClassId)
|
QuestieLearner.LearnItem = function(self, itemId, name, itemLevel, requiredLevel, itemClassId, itemSubClassId)
|
||||||
learnedItemId = itemId
|
if itemClassId == 12 then
|
||||||
|
learnedItemId = itemId
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
return false
|
||||||
end
|
end
|
||||||
QuestieLearner.LearnItemDrop = function(self, itemId, npcId)
|
QuestieLearner.LearnItemDrop = function(self, itemId, npcId)
|
||||||
dropItemId = itemId
|
dropItemId = itemId
|
||||||
dropNpcId = npcId
|
dropNpcId = npcId
|
||||||
end
|
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()
|
QuestieLearner:OnLootOpened()
|
||||||
|
|
||||||
assert.equals(20470, learnedItemId)
|
assert.is_nil(learnedItemId)
|
||||||
assert.equals(20470, dropItemId)
|
assert.is_nil(dropItemId)
|
||||||
assert.equals(15297, dropNpcId)
|
assert.is_nil(dropNpcId)
|
||||||
|
|
||||||
|
_G.GetItemInfo = originalGetItemInfo
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ describe("QuestieLearner kill-path batching", function()
|
|||||||
npcCache = {
|
npcCache = {
|
||||||
[1001] = { name = "Cached Boar" },
|
[1001] = { name = "Cached Boar" },
|
||||||
},
|
},
|
||||||
|
itemCache = {},
|
||||||
}
|
}
|
||||||
QuestiePlayer.currentQuestlog = {}
|
QuestiePlayer.currentQuestlog = {}
|
||||||
|
|
||||||
@@ -141,20 +142,37 @@ describe("QuestieLearner kill-path batching", function()
|
|||||||
assert.equals(1, table.getn(Questie.dbLearner.global.npcs[4001][7][44]))
|
assert.equals(1, table.getn(Questie.dbLearner.global.npcs[4001][7][44]))
|
||||||
end)
|
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"
|
Questie.dbLearner.global.settings.dataSourceMode = "learner"
|
||||||
QuestieDB.private.itemCache = {
|
QuestieDB.private.itemCache = {}
|
||||||
[2301] = { cached = true },
|
|
||||||
}
|
|
||||||
|
|
||||||
QuestieLearner:LearnItem(2301, "Quest Shard", 1, 1, 1, 0)
|
local learned = QuestieLearner:LearnItem(2301, "Quest Shard", 1, 1, 1, 0)
|
||||||
QuestieLearner:LearnItemDrop(2301, 7301)
|
|
||||||
|
|
||||||
assert.is_table(Questie.dbLearner.global.items[2301][2])
|
assert.is_false(learned)
|
||||||
assert.equals(7301, Questie.dbLearner.global.items[2301][2][1])
|
assert.is_nil(Questie.dbLearner.global.items[2301])
|
||||||
assert.is_nil(QuestieDB.private.itemCache[2301])
|
assert.is_nil(QuestieDB.private.itemCache[2301])
|
||||||
end)
|
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()
|
it("clears cached quest data when learner adds questgiver links", function()
|
||||||
Questie.dbLearner.global.settings.dataSourceMode = "learner"
|
Questie.dbLearner.global.settings.dataSourceMode = "learner"
|
||||||
QuestieDB.private.questCache = {
|
QuestieDB.private.questCache = {
|
||||||
|
|||||||
Reference in New Issue
Block a user