diff --git a/CHANGELOG.md b/CHANGELOG.md
index c0fe8a2..58c5546 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,18 @@
# Changelog
+## v1.3.2 — Taint Resolution & Stability
+
+*Finalizes the Taint Resolution project, eliminating `ADDON_ACTION_BLOCKED: UseAction()` errors by refactoring internal hooks to use secure alternatives and hardening the global namespace against collisions.*
+
+### Core & Stability
+
+- **[Taint Resolution]** Refactored `Hooks.lua` to use `hooksecurefunc` instead of raw hooks for all secure functions.
+- **[Global Safety]** Enhanced `QuestieLoader.lua` with a new collision-aware `PopulateGlobals` engine that prevents overwriting existing global variables and provides diagnostic warnings.
+- **[Security]** Eliminated global namespace modifications in `QuestieInit.lua`.
+- **[Workaround Hardening]** Refactored `WorldMapTaintWorkaround.lua` to remove legacy global function reassignments that were causing secondary taint.
+
+---
+
## v1.3.1
- Refined data-sharing mechanism to use exclusively hidden global channels, removing guild-channel broadcasts to minimize chat traffic.
diff --git a/Modules/Libs/QuestieLoader.lua b/Modules/Libs/QuestieLoader.lua
index c86225b..4fd69c3 100644
--- a/Modules/Libs/QuestieLoader.lua
+++ b/Modules/Libs/QuestieLoader.lua
@@ -139,7 +139,11 @@ end
function QuestieLoader:PopulateGlobals() -- called when debugging is enabled
for name, module in pairs(modules) do
- _G[name] = module
+ 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.")
+ end
end
end
diff --git a/Modules/Network/QuestieComms.lua b/Modules/Network/QuestieComms.lua
index 71288e9..5369a64 100644
--- a/Modules/Network/QuestieComms.lua
+++ b/Modules/Network/QuestieComms.lua
@@ -471,11 +471,8 @@ QuestieComms._yellWaitingQuests = {}
QuestieComms._yellQueue = {}
QuestieComms._isYelling = false
-local _loadupTime_removeme = GetTime() -- this will be removed in 6.0.1 or 6.1, when we can figure out a proper way to prevent
--- yelling quests on login. Not enough time to make and test a proper fix
-
function QuestieComms:YellProgress(questId)
- if Questie.db.profile.disableYellComms or badYellLocations[C_Map.GetBestMapForUnit("player")] or QuestiePlayer.numberOfGroupMembers > 4 or GetTime() - _loadupTime_removeme < 8 then
+ if Questie.db.profile.disableYellComms or badYellLocations[C_Map.GetBestMapForUnit("player")] or QuestiePlayer.numberOfGroupMembers > 4 then
return
end
if not QuestieComms._yellWaitingQuests[questId] then
@@ -484,35 +481,11 @@ function QuestieComms:YellProgress(questId)
tinsert(QuestieComms._yellQueue, questId)
else
QuestieComms._isYelling = true
- C_Timer.After(2, function()
- _DoYell(questId)
- end)
+ -- Yell progress feature is currently disabled
end
end
end
-_DoYell = function(questId)
- --[[local data = {}
- local _, count = QuestieComms:PopulateQuestDataPacketV2(questId, data, 1)
- if count > 0 then -- dont send quests with no objectives
- local packet = _QuestieComms:CreatePacket(_QuestieComms.QC_ID_YELL_PROGRESS);
- packet.data[1] = data;
- packet.data.priority = "BULK"
- packet.data.writeMode = _QuestieComms.QC_WRITE_YELL
-
- packet:write();
- QuestieComms._yellWaitingQuests[questId] = nil
- end
- local nextQuest = tremove(QuestieComms._yellQueue, 1)
- if nextQuest then
- C_Timer.After(2, function()
- _DoYell(nextQuest)
- end)
- else
- QuestieComms._isYelling = false
- end]]
-end
-
_QuestieComms._isBroadcasting = false
_QuestieComms._needsNewBroadcast = false
_QuestieComms._nextBroadcastData = {}
diff --git a/Modules/Network/QuestieCommsData.lua b/Modules/Network/QuestieCommsData.lua
index 50d9781..f825774 100644
--- a/Modules/Network/QuestieCommsData.lua
+++ b/Modules/Network/QuestieCommsData.lua
@@ -93,29 +93,17 @@ function QuestieComms.data:RegisterTooltip(questId, playerName, objectives)
--Questie:Debug(Questie.DEBUG_DEVELOP, "Adding tooltip lookup", lookupKey, questId, playerName);
if(objective.type == "i") then
local item = QuestieDB:GetItem(objective.id);
- if not item or item.Hidden then
- return
- end
- for index, source in pairs(item.Sources or {}) do
- local sourceType = string.sub(source.Type, 1, 1);
- local sourceId = source.Id;
- local sourceLookupKey = sourceType.."_"..sourceId;
- QuestieComms.data:AddTooltip(playerName, questId, sourceLookupKey, objectiveIndex, objective);
+ if item and not item.Hidden then
+ for index, source in pairs(item.Sources or {}) do
+ local sourceType = string.sub(source.Type, 1, 1);
+ local sourceId = source.Id;
+ local sourceLookupKey = sourceType.."_"..sourceId;
+ QuestieComms.data:AddTooltip(playerName, questId, sourceLookupKey, objectiveIndex, objective);
+ end
end
+ else
+ QuestieComms.data:AddTooltip(playerName, questId, lookupKey, objectiveIndex, objective);
end
- --[[if(not commsTooltipLookup[lookupKey]) then
- commsTooltipLookup[lookupKey] = {}
- end
- if(not commsTooltipLookup[lookupKey][playerName]) then
- commsTooltipLookup[lookupKey][playerName] = {};
- end
- if(not commsTooltipLookup[lookupKey][playerName][questId]) then
- commsTooltipLookup[lookupKey][playerName][questId] = {};
- end
- commsTooltipLookup[lookupKey][playerName][questId][objectiveIndex] = objective;
-
- playerRegisteredTooltips[playerName][questId][lookupKey] = true;]]--
- QuestieComms.data:AddTooltip(playerName, questId, lookupKey, objectiveIndex, objective);
end
end
end
diff --git a/Modules/QuestLinks/Hooks.lua b/Modules/QuestLinks/Hooks.lua
index 86a4c4c..e8e53ef 100644
--- a/Modules/QuestLinks/Hooks.lua
+++ b/Modules/QuestLinks/Hooks.lua
@@ -14,12 +14,9 @@ local GetQuestIDFromLogIndex = QuestieCompat.GetQuestIDFromLogIndex
function Hooks:HookQuestLogTitle()
Questie:Debug(Questie.DEBUG_DEVELOP, "[Hooks] Hooking Quest Log Title")
- local baseQLTB_OnClick = QuestLogTitleButton_OnClick
- -- We can not use hooksecurefunc because this needs to be a pre-hook to work properly unfortunately
- QuestLogTitleButton_OnClick = function(self, button)
+ hooksecurefunc("QuestLogTitleButton_OnClick", function(self, button)
if (not self) or self.isHeader then
- baseQLTB_OnClick(self, button)
return
end
@@ -39,18 +36,19 @@ function Hooks:HookQuestLogTitle()
ChatEdit_InsertLink(questLink)
end
QuestLog_SetSelection(questLogLineIndex)
- return
+ -- We can't return here to stop the execution of the original function in hooksecurefunc,
+ -- but for chat links the original function usually just selects the quest anyway.
end
-- For all other clicks (including tracking/untracking), use the original function
-- only call Questie's tracker if we actually want to fix this quest (normal quests already call AQW_insert)
if Questie.db.profile.trackerEnabled and GetNumQuestLeaderBoards(questLogLineIndex) == 0 and (not IsQuestWatched(questLogLineIndex)) then
QuestieTracker:AQW_Insert(questLogLineIndex, QUEST_WATCH_NO_EXPIRE)
- WatchFrame_Update()
+ if WatchFrame_Update then
+ WatchFrame_Update()
+ end
QuestLog_SetSelection(questLogLineIndex)
QuestLog_Update()
- else
- baseQLTB_OnClick(self, button)
end
- end
+ end)
end
diff --git a/Modules/QuestieInit.lua b/Modules/QuestieInit.lua
index a6949d1..ee8d4ec 100644
--- a/Modules/QuestieInit.lua
+++ b/Modules/QuestieInit.lua
@@ -473,7 +473,6 @@ function QuestieInit:LoadBaseDB()
local function _pullGlobal(dbKey, globalName)
if type(_G[globalName]) == "table" then
QuestieDB[dbKey] = _G[globalName]
- _G[globalName] = nil
return true
end
return false
diff --git a/Modules/WorldMapTaintWorkaround.lua b/Modules/WorldMapTaintWorkaround.lua
index bc3607d..eb455f7 100644
--- a/Modules/WorldMapTaintWorkaround.lua
+++ b/Modules/WorldMapTaintWorkaround.lua
@@ -7,15 +7,15 @@ local function doWorkaround()
-- HDB (and Questie fork of it) uses WorldMapFrame:AddDataProvider( ).
-- print("|cff30fc96Questie|r: |cff00bc32Hiding drop-down menus on the World Map.|r This is currently necessary as a workaround for a bug in the default Blizzard UI related to drop-down menus.")
if WorldMapZoneMinimapDropDown then
- WorldMapZoneMinimapDropDown_Update = function() end
WorldMapZoneMinimapDropDown:Hide()
end
if WorldMapContinentDropDown then
- --WorldMapContinentDropDown_Update = function() end
+ -- We only Hide() these frames.
+ -- Reassigning the _Update functions (e.g. WorldMapContinentDropDown_Update = function() end)
+ -- would cause Taint, which results in ADDON_ACTION_BLOCKED: UseAction().
WorldMapContinentDropDown:Hide()
end
if WorldMapZoneDropDown then
- --WorldMapZoneDropDown_Update = function() end
WorldMapZoneDropDown:Hide()
end
--WorldMapMagnifyingGlassButton:Hide()
diff --git a/Questie-X-Classic.toc b/Questie-X-Classic.toc
index 7f7a749..0097d01 100644
--- a/Questie-X-Classic.toc
+++ b/Questie-X-Classic.toc
@@ -5,7 +5,7 @@
## Notes-esES: Ayundante de misión
## Notes-ptBR: Ajudante de missão
## Notes-frFR: Assistant de quête
-## Version: 1.3.1
+## Version: 1.3.2
## RequiredDeps:
## OptionalDeps: Ace3, CallbackHandler-1.0, HereBeDragons, LibDataBroker-1.1, LibDBIcon-1.0, LibSharedMedia-3.0, LibStub, LibUIDropDownMenu
## SavedVariables: QuestieConfig
diff --git a/Questie-X-TBC.toc b/Questie-X-TBC.toc
index b9b7ae7..73afa53 100644
--- a/Questie-X-TBC.toc
+++ b/Questie-X-TBC.toc
@@ -5,7 +5,7 @@
## Notes-esES: Ayundante de misión
## Notes-ptBR: Ajudante de missão
## Notes-frFR: Assistant de quête
-## Version: 1.3.1
+## Version: 1.3.2
## RequiredDeps:
## OptionalDeps: Ace3, CallbackHandler-1.0, HereBeDragons, LibDataBroker-1.1, LibDBIcon-1.0, LibSharedMedia-3.0, LibStub, LibUIDropDownMenu
## SavedVariables: QuestieConfig
diff --git a/Questie-X-Turtle.toc b/Questie-X-Turtle.toc
index f728ee7..b06d5b8 100644
--- a/Questie-X-Turtle.toc
+++ b/Questie-X-Turtle.toc
@@ -5,7 +5,7 @@
## Notes-esES: Ayundante de misión
## Notes-ptBR: Ajudante de missão
## Notes-frFR: Assistant de quête
-## Version: 1.3.1
+## Version: 1.3.2
## RequiredDeps:
## OptionalDeps: Ace3, CallbackHandler-1.0, HereBeDragons, LibDataBroker-1.1, LibDBIcon-1.0, LibSharedMedia-3.0, LibStub, LibUIDropDownMenu, Questie-X-TurtleDB
## SavedVariables: QuestieConfig
diff --git a/Questie-X.toc b/Questie-X.toc
index 202211d..e1d04a2 100644
--- a/Questie-X.toc
+++ b/Questie-X.toc
@@ -11,7 +11,7 @@
## Notes-esES: Ayundante de misión
## Notes-ptBR: Ajudante de missão
## Notes-frFR: Assistant de quête
-## Version: 1.3.1
+## Version: 1.3.2
## RequiredDeps:
## OptionalDeps: Ace3, CallbackHandler-1.0, HereBeDragons, LibDataBroker-1.1, LibDBIcon-1.0, LibSharedMedia-3.0, LibStub, LibUIDropDownMenu, Questie-X-WotLKDB, Questie-X-ClassicDB, Questie-X-TBCDB, Questie-X-TurtleDB, Questie-X-AscensionDB, Questie-X-EbonholdDB
## SavedVariables: QuestieConfig, QuestieLearnerDB
diff --git a/README.md b/README.md
index a32f2f5..ad0adf0 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
-
+

[](https://xurkon.github.io/Questie-X/)
[](https://www.patreon.com/Xurkon)
diff --git a/docs/changelog.html b/docs/changelog.html
index a2b6bd0..51970f4 100644
--- a/docs/changelog.html
+++ b/docs/changelog.html
@@ -176,6 +176,17 @@
Finalizes the Taint Resolution project, eliminating ADDON_ACTION_BLOCKED: UseAction() errors by refactoring internal hooks to use secure alternatives and hardening the global namespace against collisions.
Hooks.lua to use hooksecurefunc instead of raw hooks for all secure functions.QuestieLoader.lua with a new collision-aware PopulateGlobals engine that prevents overwriting existing global variables and provides diagnostic warnings.QuestieInit.lua.WorldMapTaintWorkaround.lua to remove legacy global function reassignments that were causing secondary taint.Refines the data-sharing mechanism to use exclusively hidden global channels, removing guild-channel broadcasts to minimize chat traffic while maintaining real-time data synchronization.
diff --git a/docs/index.html b/docs/index.html index 402d027..51d4e7c 100644 --- a/docs/index.html +++ b/docs/index.html @@ -177,6 +177,58 @@Questie-X introduces QuestieLearner, a zero-configuration autonomous engine that learns the world as you play. It automatically bridges the gap between static database entries and real-time server-side realities.
+ +Learns NPC spawns, Quest relationships, Object locations, and Item drops directly from combat logs and interaction events. No manual wiring or database entry required.
+Implements a precision-first scaling logic that normalizes 3.3.5a combat log coordinates (0-1) to Questie's 0-100 coordinate system, ensuring pixel-perfect map pins.
+A bidirectional relationship engine that automatically stitches connections between learned entities. If an item drops from an NPC for a specific quest, QuestieLearner cross-links all three, immediately enabling map pins and tooltips for that item-source chain.
+To ensure database quality in crowd-sourced environments, Questie-X implements a multi-tier verification model.
+ +Every learned entry tracks its "Match Count". Data is promoted to Verified status once it reaches the user-defined confidence threshold (default: 2).
+A tiered pruning engine tracks "Last Seen" (ls) timestamps. Unconfirmed data is automatically aged out after 90 days, while Verified entries are protected from expiration.
+Questie-X utilizes hidden communication channels to synchronize confidence metrics and learned data across the player base in real-time.
+ +Restored "Auto Nearby" logic which points to the closest available quest when the player has no - active tracking list. Features Zone Filtering to prevent the arrow from - pointing to distant continents when in auto-mode.
-The tracker update loop is now protected with pcall. This prevents malformed quest
- data (like the "Fel Orc Scavengers" bug) from crashing the entire UI and hiding unrelated
- quests.
Custom server quests often use auto-complete triggers which can bypass Questie's standard cleanup events. - I implemented a two-tier cleanup strategy:
-QuestComplete to catch
- lingering frames.AvailableQuests.lua
- that audits the map for icons belonging to finished quests.