mirror of
https://github.com/brues-code/pfUI.git
synced 2026-10-20 19:30:49 +00:00
Drive questitem off QUEST_ACCEPTED/QUEST_REMOVED instead of rescanning
The item->quest map only changes when a quest enters or leaves the log, not on progress, yet it was fully rebuilt on every QUEST_LOG_UPDATE burst (a whole log walk + GetQuestDetails per quest). Maintain it incrementally from ClassicAPI's QUEST_ACCEPTED / QUEST_REMOVED, keyed on the stable questID with title/level cached at add time (the old log index shifted on any add/remove). QUEST_LOG_UPDATE now only drives a one-time login seed until the detail cache warms, since QUEST_ACCEPTED is suppressed for the bulk sync; afterward it's a no-op and questing does no rebuilds.
This commit is contained in:
+57
-36
@@ -1,8 +1,43 @@
|
|||||||
pfUI:RegisterModule("questitem", function ()
|
pfUI:RegisterModule("questitem", function ()
|
||||||
-- [itemID] = { index = questLogIndex, count = requiredCount }. Rebuilt
|
|
||||||
-- on QUEST_LOG_UPDATE from ClassicAPI's per-quest cached requirements.
|
|
||||||
local requiredItems = {}
|
local requiredItems = {}
|
||||||
|
|
||||||
|
local function AddQuest(questID)
|
||||||
|
local details = C_QuestLog.GetQuestDetails(questID)
|
||||||
|
if not details then return false end
|
||||||
|
if details.requirements then
|
||||||
|
for _, req in ipairs(details.requirements) do
|
||||||
|
if req.kind == "item" and req.id and req.id > 0 then
|
||||||
|
requiredItems[req.id] = {
|
||||||
|
questID = questID,
|
||||||
|
title = details.title,
|
||||||
|
level = details.level,
|
||||||
|
count = req.count,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
local function RemoveQuest(questID)
|
||||||
|
for itemID, entry in pairs(requiredItems) do
|
||||||
|
if entry.questID == questID then requiredItems[itemID] = nil end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function Seed()
|
||||||
|
for k in pairs(requiredItems) do requiredItems[k] = nil end
|
||||||
|
local complete = true
|
||||||
|
local i = 1
|
||||||
|
while true do
|
||||||
|
local questID = C_QuestLog.GetQuestIDForLogIndex(i)
|
||||||
|
if questID == nil then break end
|
||||||
|
if questID > 0 and not AddQuest(questID) then complete = false end
|
||||||
|
i = i + 1
|
||||||
|
end
|
||||||
|
return complete
|
||||||
|
end
|
||||||
|
|
||||||
local function AddTooltip(frame, itemID)
|
local function AddTooltip(frame, itemID)
|
||||||
if not itemID then return end
|
if not itemID then return end
|
||||||
if C.tooltip.questitem.showquest ~= "1" then return end
|
if C.tooltip.questitem.showquest ~= "1" then return end
|
||||||
@@ -19,7 +54,7 @@ pfUI:RegisterModule("questitem", function ()
|
|||||||
if not entry and not replace then return end
|
if not entry and not replace then return end
|
||||||
|
|
||||||
local quest, level = UNKNOWN, 255
|
local quest, level = UNKNOWN, 255
|
||||||
if entry then quest, level = GetQuestLogTitle(entry.index) end
|
if entry then quest, level = entry.title, entry.level end
|
||||||
if not quest then return end
|
if not quest then return end
|
||||||
|
|
||||||
local color = GetDifficultyColor(level)
|
local color = GetDifficultyColor(level)
|
||||||
@@ -42,48 +77,37 @@ pfUI:RegisterModule("questitem", function ()
|
|||||||
pfUI.questitem = CreateFrame("Frame", "pfQuestItemScanner", UIParent)
|
pfUI.questitem = CreateFrame("Frame", "pfQuestItemScanner", UIParent)
|
||||||
pfUI.questitem:RegisterEvent("PLAYER_ENTERING_WORLD")
|
pfUI.questitem:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||||
pfUI.questitem:RegisterEvent("QUEST_LOG_UPDATE")
|
pfUI.questitem:RegisterEvent("QUEST_LOG_UPDATE")
|
||||||
|
pfUI.questitem:RegisterEvent("QUEST_ACCEPTED")
|
||||||
|
pfUI.questitem:RegisterEvent("QUEST_REMOVED")
|
||||||
pfUI.questitem:SetScript("OnEvent", function()
|
pfUI.questitem:SetScript("OnEvent", function()
|
||||||
-- debounce rebuilds — QUEST_LOG_UPDATE fires in bursts
|
if C.tooltip.questitem.showquest ~= "1" then return end
|
||||||
this.run = GetTime() + .5
|
if event == "QUEST_ACCEPTED" then -- arg1 = logIndex, arg2 = questID
|
||||||
|
if not AddQuest(arg2) then -- cache cold (rare) -> reseed
|
||||||
|
this.seeding = true
|
||||||
|
this.run = GetTime() + .5
|
||||||
|
end
|
||||||
|
elseif event == "QUEST_REMOVED" then -- arg1 = questID
|
||||||
|
RemoveQuest(arg1)
|
||||||
|
elseif event == "PLAYER_ENTERING_WORLD" then
|
||||||
|
this.seeding = true -- seed pre-existing quests
|
||||||
|
this.run = GetTime() + .5
|
||||||
|
elseif event == "QUEST_LOG_UPDATE" and this.seeding then
|
||||||
|
this.run = GetTime() + .5 -- keep retrying while cache warms
|
||||||
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
pfUI.questitem:SetScript("OnUpdate", function()
|
pfUI.questitem:SetScript("OnUpdate", function()
|
||||||
if C.tooltip.questitem.showquest ~= "1" then return end
|
|
||||||
if not this.run or GetTime() < this.run then return end
|
if not this.run or GetTime() < this.run then return end
|
||||||
|
|
||||||
for k in pairs(requiredItems) do requiredItems[k] = nil end
|
|
||||||
|
|
||||||
-- GetQuestIDForLogIndex returns nil past the end, 0 for headers, else
|
|
||||||
-- the questID. GetQuestDetails reads the engine's static-info cache —
|
|
||||||
-- nil if not yet populated; we'll catch it on the next refresh.
|
|
||||||
local i = 1
|
|
||||||
while true do
|
|
||||||
local questID = C_QuestLog.GetQuestIDForLogIndex(i)
|
|
||||||
if questID == nil then break end
|
|
||||||
if questID > 0 then
|
|
||||||
local details = C_QuestLog.GetQuestDetails(questID)
|
|
||||||
if details and details.requirements then
|
|
||||||
for _, req in ipairs(details.requirements) do
|
|
||||||
if req.kind == "item" and req.id and req.id > 0 then
|
|
||||||
requiredItems[req.id] = { index = i, count = req.count }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
i = i + 1
|
|
||||||
end
|
|
||||||
|
|
||||||
this.run = nil
|
this.run = nil
|
||||||
|
if Seed() then this.seeding = nil end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
-- reload quest entries on config change
|
|
||||||
pfUI.questitem.UpdateConfig = function()
|
pfUI.questitem.UpdateConfig = function()
|
||||||
|
if C.tooltip.questitem.showquest ~= "1" then return end
|
||||||
|
pfUI.questitem.seeding = true
|
||||||
pfUI.questitem.run = GetTime() + .5
|
pfUI.questitem.run = GetTime() + .5
|
||||||
end
|
end
|
||||||
|
|
||||||
-- regular tooltip: catch every Show via a child frame's OnShow, then ask
|
|
||||||
-- the tooltip directly for the item it's displaying. Replaces a libtooltip
|
|
||||||
-- indirection that did the same query with extra caching layers.
|
|
||||||
pfUI.questitem.tooltip = CreateFrame("Frame", "pfQuestItems", GameTooltip)
|
pfUI.questitem.tooltip = CreateFrame("Frame", "pfQuestItems", GameTooltip)
|
||||||
pfUI.questitem.tooltip:SetScript("OnShow", function()
|
pfUI.questitem.tooltip:SetScript("OnShow", function()
|
||||||
if GameTooltip:HasItem() then
|
if GameTooltip:HasItem() then
|
||||||
@@ -92,9 +116,6 @@ pfUI:RegisterModule("questitem", function ()
|
|||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
-- itemref tooltip (chat link clicks): hooksecurefunc runs after SetItemRef
|
|
||||||
-- populates ItemRefTooltip, so we just read the item back out of the tooltip
|
|
||||||
-- instead of re-parsing the "item:NNN" out of the link string.
|
|
||||||
hooksecurefunc("SetItemRef", function()
|
hooksecurefunc("SetItemRef", function()
|
||||||
if IsModifierKeyDown() then return end
|
if IsModifierKeyDown() then return end
|
||||||
if ItemRefTooltip:HasItem() then
|
if ItemRefTooltip:HasItem() then
|
||||||
|
|||||||
Reference in New Issue
Block a user