feat: idempotent quest tracking and robustness improvements v1.3.7

This commit is contained in:
Xurkon
2026-03-19 00:22:26 -05:00
parent 301d7185fb
commit c5c3897421
12 changed files with 71 additions and 41 deletions
+1 -1
View File
@@ -11,7 +11,7 @@ local QuestiePlayer = QuestieLoader:ImportModule("QuestiePlayer")
local l10n = QuestieLoader:ImportModule("l10n")
--- COMPATIBILITY ---
local addonName = QuestieCompat.Is335 and QuestieCompat.addonName or "Questie"
local addonName = QuestieLoader.addonName
QuestieLib.AddonPath = "Interface\\Addons\\"..addonName.."\\"
+9 -1
View File
@@ -61,6 +61,8 @@ end
---@class QuestieLoader
QuestieLoader = QuestieLoader or {}
local addonName = ...
QuestieLoader.addonName = addonName or "Questie"
local modules = (QuestieLoader._modules) or {}
@@ -101,7 +103,13 @@ function QuestieLoader:PopulateGlobals() -- called when debugging is enabled
if _G[name] == nil then
_G[name] = module
elseif _G[name] ~= module then
Questie:Debug(Questie.DEBUG_CRITICAL, "[QuestieLoader] GLOBAL COLLISION: '" .. tostring(name) .. "' already exists in _G! Skipping population to avoid Taint.")
-- Use a safe print fallback if Questie is not yet initialized or does not have Debug
local msg = "[QuestieLoader] WARNING: Global collision detected for '" .. tostring(name) .. "'. Skipping population to avoid taining the global namespace."
if Questie and Questie.Debug then
Questie:Debug(1, msg)
else
print("|cFFFF0000" .. msg .. "|r")
end
end
end
end
+2
View File
@@ -1,6 +1,8 @@
---@diagnostic disable: undefined-global, return-type-mismatch, undefined-field
---@class QuestieCompat
---@type table|_G
QuestieCompat = setmetatable({}, { __index = _G })
QuestieCompat.addonName = QuestieLoader.addonName
------------------------------------------
-- Lua 5.0 / 5.1 / 5.2 compatibility shims
+9 -10
View File
@@ -2288,11 +2288,13 @@ function QuestieTracker.RemoveQuestWatch(index, isQuestie)
if not isQuestie then
if index then
local questId = select(8, GetQuestLogTitle(index))
if questId == 0 then
if (not questId) or questId == 0 then
-- When an objective progresses in TBC "index" is the questId, but when a quest is manually removed from
-- the quest watch (e.g. shift clicking it in the quest log) "index" is the questLogIndex.
-- We should NOT untrack when Blizzard calls this with a questId internally during objective updates.
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieTracker.RemoveQuestWatch] - Internal Blizzard update, skipping untrack for ID:", index)
if questId == 0 then
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieTracker.RemoveQuestWatch] - Internal Blizzard update, skipping untrack for ID:", index)
end
return
end
@@ -2351,22 +2353,19 @@ function QuestieTracker:AQW_Insert(index, expire)
RemoveQuestWatch(index, true)
local questId = select(8, GetQuestLogTitle(index))
if questId == 0 then
if (not questId) or questId == 0 then
-- When an objective progresses in TBC "index" is the questId, but when a quest is manually added to the quest watch
-- (e.g. shift clicking it in the quest log) "index" is the questLogIndex.
questId = index
end
if questId > 0 then
if questId and questId > 0 then
-- These checks makes sure the only way to track a quest is through the Blizzard Quest Log
-- or another Addon hooked into the Blizzard Quest Log that replaces the default Quest Log.
if not Questie.db.profile.autoTrackQuests then
if Questie.db.char.TrackedQuests[questId] then
Questie.db.char.TrackedQuests[questId] = nil
else
-- Add quest to the tracker
Questie.db.char.TrackedQuests[questId] = true
end
-- Manual track mode: force track when AddQuestWatch is called
Questie.db.char.TrackedQuests[questId] = true
Questie.db.char.AutoUntrackedQuests[questId] = nil
else
if Questie.db.char.AutoUntrackedQuests[questId] then
-- Quest was manually hidden — shift-click re-tracks it
+21 -16
View File
@@ -2,23 +2,28 @@
-- This should be independednt of Questie and all libraries.
local function doWorkaround()
-- Blizzard's bugs
-- https://github.com/Stanzilla/WoWUIBugs/issues/114 and https://github.com/Stanzilla/WoWUIBugs/issues/165
-- HDB (and Questie fork of it) uses WorldMapFrame:AddDataProvider().
-- Reassigning the _Update functions (e.g. WorldMapContinentDropDown_Update = function() end)
-- BEFORE any calls are made is often more reliable than only Hiding the frame.
-- On 3.3.5, the WorldMap has several dropdowns that are prone to tainting UIDropDownMenu.
-- We hide them and replace their global update functions with no-ops.
-- This prevents Blizzard code from calling tainted logic when opening the map.
if WorldMapZoneMinimapDropDown then
WorldMapZoneMinimapDropDown:Hide()
WorldMapZoneMinimapDropDown.Update = function() end
end
if WorldMapContinentDropDown then
WorldMapContinentDropDown:Hide()
WorldMapContinentDropDown.Update = function() end
end
if WorldMapZoneDropDown then
WorldMapZoneDropDown:Hide()
WorldMapZoneDropDown.Update = function() end
local dropdowns = {
"WorldMapContinentDropDown",
"WorldMapZoneDropDown",
"WorldMapZoneMinimapDropDown",
"WorldMapMagnifyingGlassButton"
}
for _, name in ipairs(dropdowns) do
local frame = _G[name]
if frame then
if frame.Hide then frame:Hide() end
-- Replacing the global update function is the standard workaround.
-- Do NOT assign to frame.Update as that taints the frame object itself.
local updateFuncName = name .. "_Update"
if _G[updateFuncName] then
_G[updateFuncName] = function() end
end
end
end
end