feat: release v1.4.6 - Fix SavedVariables persistence and red textures for MafWow/3.3.5a

This commit is contained in:
Xurkon
2026-03-22 08:30:20 -05:00
parent d342fd3461
commit 6e34cebead
40 changed files with 654 additions and 558 deletions
+7
View File
@@ -1,5 +1,12 @@
# Changelog
## v1.4.6 (2026-03-22)
- **[Fix]** Resolved issue where Questie would not save options or show the Welcome screen repeatedly. This was caused by version mismatches in `.toc` files and an initialization race condition.
- **[Fix]** Synchronized AceAddon registration name to `"Questie-X"` to match the folder name, ensuring proper `ADDON_LOADED` event handling and database initialization.
- **[Fix]** Patched `AceGUI-3.0` widgets (`Heading`, `Frame`, `Window`, `Icon`, `DropDown-Items`, `ColorPicker`) to use string texture paths instead of numeric `FileDataIDs`, resolving "red texture" issues on WotLK 3.3.5a clients.
- **[Cleanup]** Systematically removed all `QX:` debug print statements across the entire codebase for a cleaner production experience.
- **[Version]** Bumped version to 1.4.6 and updated `Interface` version to 30300 across all `.toc` files.
## v1.4.5 — Network & Taint Stability Update
- **[Network Fix]** Resolved a critical crash ("`Usage: AceSerializer:Deserialize(str): str must be a string, got table`") occurring in QuestieLearnerComms and Export functions. This was caused by a lightweight, customized `AceSerializer-3.0.lua` implementation in Questie-X that lacked proper `self` parameter handling for standard colon-syntax method calls (`:`). As a result, method calls were serializing/deserializing the library table itself instead of the intended payload string. We patched `AceSerializer` natively to dynamically support both dot (`.`) and colon (`:`) syntax seamlessly without dropping arguments, while ensuring `Deserialize` correctly yields `(success, result)` tuples expected by the calling functions.
+25 -10
View File
@@ -190,6 +190,7 @@ local function timerOnFinished(self)
end
end
if not QuestieCompat.C_Timer then
QuestieCompat.C_Timer = {
-- Schedules a (repeating) timer that can be canceled. (https://wowpedia.fandom.com/wiki/API_C_Timer.NewTimer)
NewTicker = function(duration, callback, iterations)
@@ -221,6 +222,7 @@ QuestieCompat.C_Timer = {
return QuestieCompat.C_Timer.NewTicker(duration, callback, 1)
end
}
end
local mapIdToUiMapId = {}
-- convert current mapAreaID and mapLevel to UiMapId
@@ -408,23 +410,36 @@ end
local questObjectivesCache = {}
local function parseQuestObjective(text)
return string.match(string.gsub(text, "\239\188\154", ":"), "(.*):%s*([%d]+)%s*/%s*([%d]+)")
local name, fulfilled, required = string.match(string.gsub(text, "\239\188\154", ":"), "(.*):%s*([%d]+)%s*/%s*([%d]+)")
if not name then
end
return name, fulfilled, required
end
QuestieCompat.C_QuestLog = {
GetQuestObjectives = function(questID, questLogIndex)
if not rawget(QuestieCompat, "C_QuestLog") then
QuestieCompat.C_QuestLog = {}
end
local cLog = QuestieCompat.C_QuestLog
cLog.GetQuestObjectives = function(questID, questLogIndex)
local questObjectives = {}
if questLogIndex then
local numObjectives = GetNumQuestLeaderBoards(questLogIndex)
for i = 1, numObjectives do
local description, objectiveType, isCompleted = GetQuestLogLeaderBoard(i, questLogIndex)
if objectiveType ~= "log" then
if objectiveType ~= "log" and description then
local objectiveName, numFulfilled, numRequired = parseQuestObjective(description)
if objectiveName then
local fulfilled = questObjectivesCache[objectiveName]
if fulfilled then
numFulfilled = fulfilled
questObjectivesCache[objectiveName] = nil
end
end
table.insert(questObjectives, {
text = description,
@@ -437,16 +452,16 @@ QuestieCompat.C_QuestLog = {
end
end
return questObjectives
end,
end
GetMaxNumQuestsCanAccept = function()
cLog.GetMaxNumQuestsCanAccept = function()
return MAX_QUESTLOG_QUESTS
end,
end
IsOnQuest = function(questId)
cLog.IsOnQuest = function(questId)
return QuestieCompat.GetQuestLogIndexByID(questId) ~= nil
end,
}
end
-- Can't find anything about this function.
+13 -21
View File
@@ -1,34 +1,26 @@
<Ui xsi:schemaLocation="http://www.blizzard.com/wow/ui/ ..\FrameXML\UI.xsd">
<Ui xmlns="http://www.blizzard.com/wow/ui/">
<Script file="..\Libs\LibStub\LibStub.lua"/>
<Include file="Libs\CallbackHandler-1.0\CallbackHandler-1.0.xml"/>
<Include file="Libs\AceAddon-3.0\AceAddon-3.0.xml"/>
<Include file="..\Libs\CallbackHandler-1.0\CallbackHandler-1.0.xml"/>
<Include file="..\Libs\AceAddon-3.0\AceAddon-3.0.xml"/>
<Include file="..\Libs\AceEvent-3.0\AceEvent-3.0.xml"/>
<Include file="Libs\AceTimer-3.0\AceTimer-3.0.xml"/>
<Include file="Libs\AceBucket-3.0\AceBucket-3.0.xml"/>
<!--Include file="Libs\AceHook-3.0\AceHook-3.0.xml"/-->
<Include file="Libs\AceDB-3.0\AceDB-3.0.xml"/>
<Include file="..\Libs\AceTimer-3.0\AceTimer-3.0.xml"/>
<Include file="..\Libs\AceBucket-3.0\AceBucket-3.0.xml"/>
<Include file="..\Libs\AceDB-3.0\AceDB-3.0.xml"/>
<Include file="..\Libs\AceDBOptions-3.0\AceDBOptions-3.0.xml"/>
<!--<Include file="Libs\AceLocale-3.0\AceLocale-3.0.xml"/-->
<Include file="..\Libs\AceConsole-3.0\AceConsole-3.0.xml"/>
<Include file="Libs\AceGUI-3.0\AceGUI-3.0.xml"/>
<!--Include file="Libs\AceConfig-3.0\AceConfig-3.0.xml"/-->
<Include file="..\Libs\AceConfig-3.0\AceConfigRegistry-3.0\AceConfigRegistry-3.0.xml"/>
<Include file="..\Libs\AceConfig-3.0\AceConfigCmd-3.0\AceConfigCmd-3.0.xml"/>
<Include file="Libs\AceConfigDialog-3.0\AceConfigDialog-3.0.xml"/>
<Script file="..\Libs\AceConfig-3.0\AceConfig-3.0.lua"/>
<Include file="Libs\AceComm-3.0\AceComm-3.0.xml"/>
<!--Include file="AceTab-3.0\AceTab-3.0.xml"/-->
<Include file="..\Libs\AceGUI-3.0\AceGUI-3.0.xml"/>
<Include file="..\Libs\AceConfig-3.0\AceConfig-3.0.xml"/>
<Include file="..\Libs\AceComm-3.0\AceComm-3.0.xml"/>
<Include file="..\Libs\AceSerializer-3.0\AceSerializer-3.0.xml"/>
<!-- Ace3 frame work end -->
<Include file="Libs\LibSharedMedia-3.0\lib.xml"/>
<Include file="..\Libs\LibSharedMedia-3.0\lib.xml"/>
<Include file="..\Libs\AceGUI-3.0-SharedMediaWidgets\widget.xml"/>
<Include file="..\Libs\LibDeflate\lib.xml"/>
<Script file="..\Libs\LibDataBroker-1.1\LibDataBroker-1.1.lua"/>
<Script file="Libs\LibDBIcon-1.0\LibDBIcon-1.0.lua"/>
<!--Script file="Libs\Krowi_WorldMapButtons\Krowi_WorldMapButtons-1.4.lua"/-->
<Script file="..\Libs\LibDBIcon-1.0\LibDBIcon-1.0.lua"/>
<Script file="Debug.lua"/>
<Script file="Compat.lua"/>
<Script file="Corrections.lua"/>
<Script file="FactionId.lua"/>
<Script file="QuestTag.lua"/>
+21 -18
View File
@@ -269,24 +269,27 @@ function QuestieDB:Initialize()
-- For now we store both, the SoD database and the Era/HC database
local npcBin, npcPtrs, questBin, questPtrs, objBin, objPtrs, itemBin, itemPtrs
local binaryBucket = Questie.dbCache and Questie.dbCache.global or Questie.db.global
if Questie.IsSoD then
npcBin = Questie.db.global.sod.npcBin
npcPtrs = Questie.db.global.sod.npcPtrs
questBin = Questie.db.global.sod.questBin
questPtrs = Questie.db.global.sod.questPtrs
objBin = Questie.db.global.sod.objBin
objPtrs = Questie.db.global.sod.objPtrs
itemBin = Questie.db.global.sod.itemBin
itemPtrs = Questie.db.global.sod.itemPtrs
binaryBucket = binaryBucket.sod or {}
npcBin = binaryBucket.npcBin
npcPtrs = binaryBucket.npcPtrs
questBin = binaryBucket.questBin
questPtrs = binaryBucket.questPtrs
objBin = binaryBucket.objBin
objPtrs = binaryBucket.objPtrs
itemBin = binaryBucket.itemBin
itemPtrs = binaryBucket.itemPtrs
else
npcBin = Questie.db.global.npcBin
npcPtrs = Questie.db.global.npcPtrs
questBin = Questie.db.global.questBin
questPtrs = Questie.db.global.questPtrs
objBin = Questie.db.global.objBin
objPtrs = Questie.db.global.objPtrs
itemBin = Questie.db.global.itemBin
itemPtrs = Questie.db.global.itemPtrs
npcBin = binaryBucket.npcBin
npcPtrs = binaryBucket.npcPtrs
questBin = binaryBucket.questBin
questPtrs = binaryBucket.questPtrs
objBin = binaryBucket.objBin
objPtrs = binaryBucket.objPtrs
itemBin = binaryBucket.itemBin
itemPtrs = binaryBucket.itemPtrs
end
QuestieDB.QueryNPC = QuestieDBCompiler:GetDBHandle(npcBin, npcPtrs, QuestieDBCompiler:BuildSkipMap(QuestieDB.npcCompilerTypes, QuestieDB.npcCompilerOrder), QuestieDB.npcKeys, QuestieDB.npcDataOverrides)
@@ -592,7 +595,7 @@ end
---@return table<number, boolean>
function QuestieDB.GetSuppressedNPCs(zoneId)
local suppressed = {}
local ld = Questie.db.global.learnedData
local ld = Questie.dbLearner.global
if ld and ld.settings and ld.settings.prioritizeMyData and ld.npcs then
local threshold = ld.settings.minConfidencePins or 2
for npcId, entry in pairs(ld.npcs) do
@@ -610,7 +613,7 @@ end
---@return table<number, boolean>
function QuestieDB.GetSuppressedObjects(zoneId)
local suppressed = {}
local ld = Questie.db.global.learnedData
local ld = Questie.dbLearner.global
if ld and ld.settings and ld.settings.prioritizeMyData and ld.objects then
local threshold = ld.settings.minConfidencePins or 2
for objId, entry in pairs(ld.objects) do
+41 -30
View File
@@ -22,6 +22,12 @@ local lshift = bit.lshift
local TICKS_PER_YIELD = 48
local TICKS_PER_YIELD_DEBUG = TICKS_PER_YIELD * 3
local function safeYield()
if coroutine.running() then
coroutine.yield()
end
end
---@alias CompilerTypes
---| "u8"
---| "u16"
@@ -924,7 +930,7 @@ function QuestieDBCompiler:DecodePointerMap(stream)
ret[stream:ReadInt24()] = stream:ReadInt24()
end
i = i + 768
coroutine.yield()
safeYield()
end
return ret
end
@@ -972,16 +978,17 @@ function QuestieDBCompiler:CompileTableCoroutine(tbl, types, order, lookup, data
local supportedTypes = QuestieDBCompiler.supportedTypes
while true do
coroutine.yield()
safeYield()
for _=0,Questie.db.profile.debugEnabled and TICKS_PER_YIELD_DEBUG or (entriesPerTick or TICKS_PER_YIELD) do
index = index + 1
if index == count then
local binaryBucket = Questie.dbCache and Questie.dbCache.global or Questie.db.global
if Questie.IsSoD then
Questie.db.global.sod[databaseKey.."Bin"] = stream:Save()
Questie.db.global.sod[databaseKey.."Ptrs"] = QuestieDBCompiler:EncodePointerMap(stream, pointerMap)
binaryBucket.sod[databaseKey.."Bin"] = stream:Save()
binaryBucket.sod[databaseKey.."Ptrs"] = QuestieDBCompiler:EncodePointerMap(stream, pointerMap)
else
Questie.db.global[databaseKey.."Bin"] = stream:Save()
Questie.db.global[databaseKey.."Ptrs"] = QuestieDBCompiler:EncodePointerMap(stream, pointerMap)
binaryBucket[databaseKey.."Bin"] = stream:Save()
binaryBucket[databaseKey.."Ptrs"] = QuestieDBCompiler:EncodePointerMap(stream, pointerMap)
end
stream:finished() -- relief memory pressure
return
@@ -1096,12 +1103,14 @@ end
function QuestieDBCompiler:ValidateNPCs()
local npcBin, npcPtrs
local binaryBucket = Questie.dbCache and Questie.dbCache.global or Questie.db.global
if Questie.IsSoD then
npcBin = Questie.db.global.sod.npcBin
npcPtrs = Questie.db.global.sod.npcPtrs
binaryBucket = binaryBucket.sod or {}
npcBin = binaryBucket.npcBin
npcPtrs = binaryBucket.npcPtrs
else
npcBin = Questie.db.global.npcBin
npcPtrs = Questie.db.global.npcPtrs
npcBin = binaryBucket.npcBin
npcPtrs = binaryBucket.npcPtrs
end
local validator = QuestieDBCompiler:GetDBHandle(npcBin, npcPtrs, QuestieDBCompiler:BuildSkipMap(QuestieDB.npcCompilerTypes, QuestieDB.npcCompilerOrder))
@@ -1129,7 +1138,7 @@ function QuestieDBCompiler:ValidateNPCs()
if count == TICKS_PER_YIELD_DEBUG then
count = 0
coroutine.yield()
safeYield()
end
count = count + 1
end
@@ -1173,7 +1182,7 @@ function QuestieDBCompiler:ValidateObjects()
if count == TICKS_PER_YIELD_DEBUG then
count = 0
coroutine.yield()
safeYield()
end
count = count + 1
end
@@ -1185,20 +1194,22 @@ function QuestieDBCompiler:ValidateObjects()
function QuestieDBCompiler:ValidateItems()
local itemBin, objBin, npcBin, objPtrs, itemPtrs, npcPtrs
local binaryBucket = Questie.dbCache and Questie.dbCache.global or Questie.db.global
if Questie.IsSoD then
itemBin = Questie.db.global.sod.itemBin
itemPtrs = Questie.db.global.sod.itemPtrs
objBin = Questie.db.global.sod.objBin
objPtrs = Questie.db.global.sod.objPtrs
npcBin = Questie.db.global.sod.npcBin
npcPtrs = Questie.db.global.sod.npcPtrs
binaryBucket = binaryBucket.sod or {}
itemBin = binaryBucket.itemBin
itemPtrs = binaryBucket.itemPtrs
objBin = binaryBucket.objBin
objPtrs = binaryBucket.objPtrs
npcBin = binaryBucket.npcBin
npcPtrs = binaryBucket.npcPtrs
else
itemBin = Questie.db.global.itemBin
itemPtrs = Questie.db.global.itemPtrs
objBin = Questie.db.global.objBin
objPtrs = Questie.db.global.objPtrs
npcBin = Questie.db.global.npcBin
npcPtrs = Questie.db.global.npcPtrs
itemBin = binaryBucket.itemBin
itemPtrs = binaryBucket.itemPtrs
objBin = binaryBucket.objBin
objPtrs = binaryBucket.objPtrs
npcBin = binaryBucket.npcBin
npcPtrs = binaryBucket.npcPtrs
end
local validator = QuestieDBCompiler:GetDBHandle(itemBin, itemPtrs, QuestieDBCompiler:BuildSkipMap(QuestieDB.itemCompilerTypes, QuestieDB.itemCompilerOrder))
@@ -1258,7 +1269,7 @@ function QuestieDBCompiler:ValidateItems()
--end
if count == TICKS_PER_YIELD_DEBUG then
count = 0
coroutine.yield()
safeYield()
end
count = count + 1
end
@@ -1286,7 +1297,7 @@ function QuestieDBCompiler:ValidateItems()
if count == TICKS_PER_YIELD_DEBUG then
count = 0
coroutine.yield()
safeYield()
end
count = count + 1
end
@@ -1379,7 +1390,7 @@ function QuestieDBCompiler:ValidateQuests()
if count == TICKS_PER_YIELD_DEBUG then
count = 0
coroutine.yield()
safeYield()
end
count = count + 1
end
@@ -1393,12 +1404,12 @@ function QuestieDBCompiler:GetDBHandle(data, pointers, skipMap, keyToRootIndex,
local map, lastIndex, lastPtr, types, _, indexToKey, keyToIndex = unpack(skipMap)
local stream = QuestieStream:GetStream("raw")
coroutine.yield()
safeYield()
stream:Load(pointers)
coroutine.yield()
safeYield()
pointers = QuestieDBCompiler:DecodePointerMap(stream)
--Questie.db.global.__pointers = pointers
coroutine.yield()
safeYield()
stream:Load(data)
handle.stream = stream
@@ -221,7 +221,7 @@ local function Constructor()
statustext:SetText("")
local titlebg = frame:CreateTexture(nil, "OVERLAY")
titlebg:SetTexture(131080) -- Interface\\DialogFrame\\UI-DialogBox-Header
titlebg:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Header") -- Interface\\DialogFrame\\UI-DialogBox-Header
titlebg:SetTexCoord(0.31, 0.67, 0, 0.63)
titlebg:SetPoint("TOP", 0, 12)
titlebg:SetWidth(100)
@@ -237,14 +237,14 @@ local function Constructor()
titletext:SetPoint("TOP", titlebg, "TOP", 0, -14)
local titlebg_l = frame:CreateTexture(nil, "OVERLAY")
titlebg_l:SetTexture(131080) -- Interface\\DialogFrame\\UI-DialogBox-Header
titlebg_l:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Header") -- Interface\\DialogFrame\\UI-DialogBox-Header
titlebg_l:SetTexCoord(0.21, 0.31, 0, 0.63)
titlebg_l:SetPoint("RIGHT", titlebg, "LEFT")
titlebg_l:SetWidth(30)
titlebg_l:SetHeight(40)
local titlebg_r = frame:CreateTexture(nil, "OVERLAY")
titlebg_r:SetTexture(131080) -- Interface\\DialogFrame\\UI-DialogBox-Header
titlebg_r:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Header") -- Interface\\DialogFrame\\UI-DialogBox-Header
titlebg_r:SetTexCoord(0.67, 0.77, 0, 0.63)
titlebg_r:SetPoint("LEFT", titlebg, "RIGHT")
titlebg_r:SetWidth(30)
@@ -262,7 +262,7 @@ local function Constructor()
line1:SetWidth(14)
line1:SetHeight(14)
line1:SetPoint("BOTTOMRIGHT", -8, 8)
line1:SetTexture(137057) -- Interface\\Tooltips\\UI-Tooltip-Border
line1:SetTexture("Interface\\Tooltips\\UI-Tooltip-Border") -- Interface\\Tooltips\\UI-Tooltip-Border
local x = 0.1 * 14/17
line1:SetTexCoord(0.05 - x, 0.5, 0.05, 0.5 + x, 0.05, 0.5 - x, 0.5 + x, 0.5)
@@ -270,7 +270,7 @@ local function Constructor()
line2:SetWidth(8)
line2:SetHeight(8)
line2:SetPoint("BOTTOMRIGHT", -8, 8)
line2:SetTexture(137057) -- Interface\\Tooltips\\UI-Tooltip-Border
line2:SetTexture("Interface\\Tooltips\\UI-Tooltip-Border") -- Interface\\Tooltips\\UI-Tooltip-Border
x = 0.1 * 8/17
line2:SetTexCoord(0.05 - x, 0.5, 0.05, 0.5 + x, 0.05, 0.5 - x, 0.5 + x, 0.5)
@@ -190,67 +190,67 @@ do
frame:SetToplevel(true)
local titlebg = frame:CreateTexture(nil, "BACKGROUND")
titlebg:SetTexture(251966) -- Interface\\PaperDollInfoFrame\\UI-GearManager-Title-Background
titlebg:SetTexture("Interface\\PaperDollInfoFrame\\UI-GearManager-Title-Background") -- Interface\\PaperDollInfoFrame\\UI-GearManager-Title-Background
titlebg:SetPoint("TOPLEFT", 9, -6)
titlebg:SetPoint("BOTTOMRIGHT", frame, "TOPRIGHT", -28, -24)
local dialogbg = frame:CreateTexture(nil, "BACKGROUND")
dialogbg:SetTexture(137056) -- Interface\\Tooltips\\UI-Tooltip-Background
dialogbg:SetTexture("Interface\\Tooltips\\UI-Tooltip-Background") -- Interface\\Tooltips\\UI-Tooltip-Background
dialogbg:SetPoint("TOPLEFT", 8, -24)
dialogbg:SetPoint("BOTTOMRIGHT", -6, 8)
dialogbg:SetVertexColor(0, 0, 0, .75)
local topleft = frame:CreateTexture(nil, "BORDER")
topleft:SetTexture(251963) -- Interface\\PaperDollInfoFrame\\UI-GearManager-Border
topleft:SetTexture("Interface\\PaperDollInfoFrame\\UI-GearManager-Border") -- Interface\\PaperDollInfoFrame\\UI-GearManager-Border
topleft:SetWidth(64)
topleft:SetHeight(64)
topleft:SetPoint("TOPLEFT")
topleft:SetTexCoord(0.501953125, 0.625, 0, 1)
local topright = frame:CreateTexture(nil, "BORDER")
topright:SetTexture(251963) -- Interface\\PaperDollInfoFrame\\UI-GearManager-Border
topright:SetTexture("Interface\\PaperDollInfoFrame\\UI-GearManager-Border") -- Interface\\PaperDollInfoFrame\\UI-GearManager-Border
topright:SetWidth(64)
topright:SetHeight(64)
topright:SetPoint("TOPRIGHT")
topright:SetTexCoord(0.625, 0.75, 0, 1)
local top = frame:CreateTexture(nil, "BORDER")
top:SetTexture(251963) -- Interface\\PaperDollInfoFrame\\UI-GearManager-Border
top:SetTexture("Interface\\PaperDollInfoFrame\\UI-GearManager-Border") -- Interface\\PaperDollInfoFrame\\UI-GearManager-Border
top:SetHeight(64)
top:SetPoint("TOPLEFT", topleft, "TOPRIGHT")
top:SetPoint("TOPRIGHT", topright, "TOPLEFT")
top:SetTexCoord(0.25, 0.369140625, 0, 1)
local bottomleft = frame:CreateTexture(nil, "BORDER")
bottomleft:SetTexture(251963) -- Interface\\PaperDollInfoFrame\\UI-GearManager-Border
bottomleft:SetTexture("Interface\\PaperDollInfoFrame\\UI-GearManager-Border") -- Interface\\PaperDollInfoFrame\\UI-GearManager-Border
bottomleft:SetWidth(64)
bottomleft:SetHeight(64)
bottomleft:SetPoint("BOTTOMLEFT")
bottomleft:SetTexCoord(0.751953125, 0.875, 0, 1)
local bottomright = frame:CreateTexture(nil, "BORDER")
bottomright:SetTexture(251963) -- Interface\\PaperDollInfoFrame\\UI-GearManager-Border
bottomright:SetTexture("Interface\\PaperDollInfoFrame\\UI-GearManager-Border") -- Interface\\PaperDollInfoFrame\\UI-GearManager-Border
bottomright:SetWidth(64)
bottomright:SetHeight(64)
bottomright:SetPoint("BOTTOMRIGHT")
bottomright:SetTexCoord(0.875, 1, 0, 1)
local bottom = frame:CreateTexture(nil, "BORDER")
bottom:SetTexture(251963) -- Interface\\PaperDollInfoFrame\\UI-GearManager-Border
bottom:SetTexture("Interface\\PaperDollInfoFrame\\UI-GearManager-Border") -- Interface\\PaperDollInfoFrame\\UI-GearManager-Border
bottom:SetHeight(64)
bottom:SetPoint("BOTTOMLEFT", bottomleft, "BOTTOMRIGHT")
bottom:SetPoint("BOTTOMRIGHT", bottomright, "BOTTOMLEFT")
bottom:SetTexCoord(0.376953125, 0.498046875, 0, 1)
local left = frame:CreateTexture(nil, "BORDER")
left:SetTexture(251963) -- Interface\\PaperDollInfoFrame\\UI-GearManager-Border
left:SetTexture("Interface\\PaperDollInfoFrame\\UI-GearManager-Border") -- Interface\\PaperDollInfoFrame\\UI-GearManager-Border
left:SetWidth(64)
left:SetPoint("TOPLEFT", topleft, "BOTTOMLEFT")
left:SetPoint("BOTTOMLEFT", bottomleft, "TOPLEFT")
left:SetTexCoord(0.001953125, 0.125, 0, 1)
local right = frame:CreateTexture(nil, "BORDER")
right:SetTexture(251963) -- Interface\\PaperDollInfoFrame\\UI-GearManager-Border
right:SetTexture("Interface\\PaperDollInfoFrame\\UI-GearManager-Border") -- Interface\\PaperDollInfoFrame\\UI-GearManager-Border
right:SetWidth(64)
right:SetPoint("TOPRIGHT", topright, "BOTTOMRIGHT")
right:SetPoint("BOTTOMRIGHT", bottomright, "TOPRIGHT")
@@ -290,7 +290,7 @@ do
line1:SetWidth(14)
line1:SetHeight(14)
line1:SetPoint("BOTTOMRIGHT", -8, 8)
line1:SetTexture(137057) -- Interface\\Tooltips\\UI-Tooltip-Border
line1:SetTexture("Interface\\Tooltips\\UI-Tooltip-Border") -- Interface\\Tooltips\\UI-Tooltip-Border
local x = 0.1 * 14/17
line1:SetTexCoord(0.05 - x, 0.5, 0.05, 0.5 + x, 0.05, 0.5 - x, 0.5 + x, 0.5)
@@ -299,7 +299,7 @@ do
line2:SetWidth(8)
line2:SetHeight(8)
line2:SetPoint("BOTTOMRIGHT", -8, 8)
line2:SetTexture(137057) -- Interface\\Tooltips\\UI-Tooltip-Border
line2:SetTexture("Interface\\Tooltips\\UI-Tooltip-Border") -- Interface\\Tooltips\\UI-Tooltip-Border
x = 0.1 * 8/17
line2:SetTexCoord(0.05 - x, 0.5, 0.05, 0.5 + x, 0.05, 0.5 - x, 0.5 + x, 0.5)
@@ -151,21 +151,21 @@ local methods = {
local size
if type == "radio" then
size = 16
checkbg:SetTexture(130843) -- Interface\\Buttons\\UI-RadioButton
checkbg:SetTexture("Interface\\Buttons\\UI-RadioButton")
checkbg:SetTexCoord(0, 0.25, 0, 1)
check:SetTexture(130843) -- Interface\\Buttons\\UI-RadioButton
check:SetTexture("Interface\\Buttons\\UI-RadioButton")
check:SetTexCoord(0.25, 0.5, 0, 1)
check:SetBlendMode("ADD")
highlight:SetTexture(130843) -- Interface\\Buttons\\UI-RadioButton
highlight:SetTexture("Interface\\Buttons\\UI-RadioButton")
highlight:SetTexCoord(0.5, 0.75, 0, 1)
else
size = 24
checkbg:SetTexture(130755) -- Interface\\Buttons\\UI-CheckBox-Up
checkbg:SetTexture("Interface\\Buttons\\UI-CheckBox-Up")
checkbg:SetTexCoord(0, 1, 0, 1)
check:SetTexture(130751) -- Interface\\Buttons\\UI-CheckBox-Check
check:SetTexture("Interface\\Buttons\\UI-CheckBox-Check")
check:SetTexCoord(0, 1, 0, 1)
check:SetBlendMode("BLEND")
highlight:SetTexture(130753) -- Interface\\Buttons\\UI-CheckBox-Highlight
highlight:SetTexture("Interface\\Buttons\\UI-CheckBox-Highlight")
highlight:SetTexCoord(0, 1, 0, 1)
end
checkbg:SetHeight(size)
@@ -251,11 +251,11 @@ local function Constructor()
checkbg:SetWidth(24)
checkbg:SetHeight(24)
checkbg:SetPoint("TOPLEFT")
checkbg:SetTexture(130755) -- Interface\\Buttons\\UI-CheckBox-Up
checkbg:SetTexture("Interface\\Buttons\\UI-CheckBox-Up")
local check = frame:CreateTexture(nil, "OVERLAY")
check:SetAllPoints(checkbg)
check:SetTexture(130751) -- Interface\\Buttons\\UI-CheckBox-Check
check:SetTexture("Interface\\Buttons\\UI-CheckBox-Check")
local text = frame:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
text:SetJustifyH("LEFT")
@@ -264,7 +264,7 @@ local function Constructor()
text:SetPoint("RIGHT")
local highlight = frame:CreateTexture(nil, "HIGHLIGHT")
highlight:SetTexture(130753) -- Interface\\Buttons\\UI-CheckBox-Highlight
highlight:SetTexture("Interface\\Buttons\\UI-CheckBox-Highlight")
highlight:SetBlendMode("ADD")
highlight:SetAllPoints(checkbg)
@@ -136,7 +136,7 @@ local function Constructor()
local colorSwatch = frame:CreateTexture(nil, "OVERLAY")
colorSwatch:SetWidth(19)
colorSwatch:SetHeight(19)
colorSwatch:SetTexture(130939) -- Interface\\ChatFrame\\ChatFrameColorSwatch
colorSwatch:SetTexture("Interface\\ChatFrame\\ChatFrameColorSwatch") -- Interface\\ChatFrame\\ChatFrameColorSwatch
colorSwatch:SetPoint("LEFT")
local texture = frame:CreateTexture(nil, "BACKGROUND")
@@ -156,7 +156,7 @@ local function Constructor()
colorSwatch.checkers = checkers
checkers:SetWidth(14)
checkers:SetHeight(14)
checkers:SetTexture(188523) -- Tileset\\Generic\\Checkers
checkers:SetTexture("Tileset\\Generic\\Checkers") -- Tileset\\Generic\\Checkers
checkers:SetTexCoord(.25, 0, 0.5, .25)
checkers:SetDesaturated(true)
checkers:SetVertexColor(1, 1, 1, 0.75)
@@ -171,7 +171,7 @@ local function Constructor()
text:SetPoint("RIGHT")
--local highlight = frame:CreateTexture(nil, "HIGHLIGHT")
--highlight:SetTexture(136810) -- Interface\\QuestFrame\\UI-QuestTitleHighlight
--highlight:SetTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight") -- Interface\\QuestFrame\\UI-QuestTitleHighlight
--highlight:SetBlendMode("ADD")
--highlight:SetAllPoints(frame)
@@ -169,7 +169,7 @@ function ItemBase.Create(type)
self.text = text
local highlight = frame:CreateTexture(nil, "OVERLAY")
highlight:SetTexture(136810) -- Interface\\QuestFrame\\UI-QuestTitleHighlight
highlight:SetTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight") -- Interface\\QuestFrame\\UI-QuestTitleHighlight
highlight:SetBlendMode("ADD")
highlight:SetHeight(14)
highlight:ClearAllPoints()
@@ -182,7 +182,7 @@ function ItemBase.Create(type)
check:SetWidth(16)
check:SetHeight(16)
check:SetPoint("LEFT",frame,"LEFT",3,-1)
check:SetTexture(130751) -- Interface\\Buttons\\UI-CheckBox-Check
check:SetTexture("Interface\\Buttons\\UI-CheckBox-Check") -- Interface\\Buttons\\UI-CheckBox-Check
check:Hide()
self.check = check
@@ -190,7 +190,7 @@ function ItemBase.Create(type)
sub:SetWidth(16)
sub:SetHeight(16)
sub:SetPoint("RIGHT",frame,"RIGHT",-3,-1)
sub:SetTexture(130940) -- Interface\\ChatFrame\\ChatFrameExpandArrow
sub:SetTexture("Interface\\ChatFrame\\ChatFrameExpandArrow") -- Interface\\ChatFrame\\ChatFrameExpandArrow
sub:Hide()
self.sub = sub
@@ -51,14 +51,14 @@ local function Constructor()
left:SetHeight(8)
left:SetPoint("LEFT", 3, 0)
left:SetPoint("RIGHT", label, "LEFT", -5, 0)
left:SetTexture(137057) -- Interface\\Tooltips\\UI-Tooltip-Border
left:SetTexture("Interface\\Tooltips\\UI-Tooltip-Border") -- Interface\\Tooltips\\UI-Tooltip-Border
left:SetTexCoord(0.81, 0.94, 0.5, 1)
local right = frame:CreateTexture(nil, "BACKGROUND")
right:SetHeight(8)
right:SetPoint("RIGHT", -3, 0)
right:SetPoint("LEFT", label, "RIGHT", 5, 0)
right:SetTexture(137057) -- Interface\\Tooltips\\UI-Tooltip-Border
right:SetTexture("Interface\\Tooltips\\UI-Tooltip-Border") -- Interface\\Tooltips\\UI-Tooltip-Border
right:SetTexCoord(0.81, 0.94, 0.5, 1)
local widget = {
@@ -118,7 +118,7 @@ local function Constructor()
local highlight = frame:CreateTexture(nil, "HIGHLIGHT")
highlight:SetAllPoints(image)
highlight:SetTexture(136580) -- Interface\\PaperDollInfoFrame\\UI-Character-Tab-Highlight
highlight:SetTexture("Interface\\PaperDollInfoFrame\\UI-Character-Tab-Highlight") -- Interface\\PaperDollInfoFrame\\UI-Character-Tab-Highlight
highlight:SetTexCoord(0, 1, 0.23, 0.77)
highlight:SetBlendMode("ADD")
+7 -6
View File
@@ -24,12 +24,13 @@ API:
]]
local bit = bit
local band = bit.band
local bor = bit.bor
local bxor = bit.bxor
local lshift = bit.lshift
local rshift = bit.rshift
local bit = _G.bit
local band = bit and bit.band
local bor = bit and bit.bor
local bxor = bit and bit.bxor
local lshift = bit and bit.lshift
local rshift = bit and bit.rshift
local string = string
local sbyte = string.byte
+1
View File
@@ -99,6 +99,7 @@ function l10n:PostBoot()
local count = 0
-- Create {['name'] = {ID, },} table for lookup of possible object IDs by name
if not QuestieDB.ObjectPointers then return end
for id in pairs(QuestieDB.ObjectPointers) do
local name = QuestieDB.QueryObjectSingle(id, "name")
if name then -- We (meaning me, BreakBB) introduced Fake IDs for objects to show additional locations, so we need to check this
+1 -1
View File
@@ -65,7 +65,7 @@ function _QuestieJourney:GetJourneyEntries()
local dateTable = {}
-- -- Sort all of the entries by year and month
-- ---@param v JourneyEntry
for i, v in ipairs(Questie.db.char.journey) do
for i, v in ipairs(Questie.dbJourney.char.journey) do
local year = tonumber(date('%Y', v.Timestamp))
if (not dateTable[year]) then
dateTable[year] = {}
+6 -7
View File
@@ -155,7 +155,7 @@ function QuestieJourney:PlayerLevelUp(level)
Timestamp = time()
}
tinsert(Questie.db.char.journey, entry)
tinsert(Questie.dbJourney.char.journey, entry)
end
function QuestieJourney:AcceptQuest(questId)
@@ -169,16 +169,15 @@ function QuestieJourney:AcceptQuest(questId)
Timestamp = time()
}
tinsert(Questie.db.char.journey, entry)
tinsert(Questie.dbJourney.char.journey, entry)
end
function QuestieJourney:AbandonQuest(questId)
-- Abandon Quest added to Journey
-- first check to see if the quest has been completed already or not
local skipAbandon = false
for i in ipairs(Questie.db.char.journey) do
local entry = Questie.db.char.journey[i]
for i in ipairs(Questie.dbJourney.char.journey) do
local entry = Questie.dbJourney.char.journey[i]
if entry.Event == "Quest" then
if entry.Quest == questId then
if entry.SubType == "Complete" then
@@ -198,7 +197,7 @@ function QuestieJourney:AbandonQuest(questId)
Timestamp = time()
}
tinsert(Questie.db.char.journey, entry)
tinsert(Questie.dbJourney.char.journey, entry)
end
end
@@ -213,5 +212,5 @@ function QuestieJourney:CompleteQuest(questId)
Timestamp = time()
}
tinsert(Questie.db.char.journey, entry)
tinsert(Questie.dbJourney.char.journey, entry)
end
+1 -1
View File
@@ -58,7 +58,7 @@ function _QuestieJourney.myJourney:ManageTree(container)
local created = AceGUI:Create("Label");
created:SetFullWidth(true);
local entry = Questie.db.char.journey[tonumber(e)];
local entry = Questie.dbJourney.char.journey[tonumber(e)];
local day = CALENDAR_WEEKDAY_NAMES[ tonumber(date('%w', entry.Timestamp)) + 1 ];
local month = CALENDAR_FULLDATE_MONTH_NAMES[ tonumber(date('%m', entry.Timestamp)) ];
local timestamp = Questie:Colorize(date( day ..', '.. month ..' %d @ %H:%M' , entry.Timestamp), 'blue');
+13 -13
View File
@@ -28,7 +28,7 @@ function _QuestieJourney.myJourney:DrawTab(container)
QuestieJourneyUtils:Spacer(container);
-- get last 5 elements from table for history
local counter = #Questie.db.char.journey;
local counter = #Questie.dbJourney.char.journey;
local recentEvents = {};
for i = counter, counter-4, -1 do
if i <= 0 then
@@ -39,30 +39,30 @@ function _QuestieJourney.myJourney:DrawTab(container)
recentEvents[i] = AceGUI:Create("Label");
recentEvents[i]:SetFullWidth(true);
local day = CALENDAR_WEEKDAY_NAMES[tonumber(date('%w', Questie.db.char.journey[i].Timestamp)) + 1];
local month = CALENDAR_FULLDATE_MONTH_NAMES[tonumber(date('%m', Questie.db.char.journey[i].Timestamp))];
local day = CALENDAR_WEEKDAY_NAMES[tonumber(date('%w', Questie.dbJourney.char.journey[i].Timestamp)) + 1];
local month = CALENDAR_FULLDATE_MONTH_NAMES[tonumber(date('%m', Questie.dbJourney.char.journey[i].Timestamp))];
local timestamp = Questie:Colorize(date( '[ '..day ..', '.. month ..' %d @ %H:%M ] ' , Questie.db.char.journey[i].Timestamp), 'blue');
local timestamp = Questie:Colorize(date( '[ '..day ..', '.. month ..' %d @ %H:%M ] ' , Questie.dbJourney.char.journey[i].Timestamp), 'blue');
-- if it's a quest event
if Questie.db.char.journey[i].Event == "Quest" then
local qName = QuestieDB.QueryQuestSingle(Questie.db.char.journey[i].Quest, "name");
if Questie.dbJourney.char.journey[i].Event == "Quest" then
local qName = QuestieDB.QueryQuestSingle(Questie.dbJourney.char.journey[i].Quest, "name");
if qName then
qName = Questie:Colorize(qName, 'gray');
if Questie.db.char.journey[i].SubType == "Accept" then
if Questie.dbJourney.char.journey[i].SubType == "Accept" then
recentEvents[i]:SetText(timestamp .. Questie:Colorize(l10n('You Accepted the quest %s', qName), 'yellow'));
elseif Questie.db.char.journey[i].SubType == "Abandon" then
elseif Questie.dbJourney.char.journey[i].SubType == "Abandon" then
recentEvents[i]:SetText(timestamp .. Questie:Colorize(l10n('You Abandoned the quest %s', qName), 'yellow'));
elseif Questie.db.char.journey[i].SubType == "Complete" then
elseif Questie.dbJourney.char.journey[i].SubType == "Complete" then
recentEvents[i]:SetText(timestamp .. Questie:Colorize(l10n('You Completed the quest %s', qName), 'yellow'));
end
end
elseif Questie.db.char.journey[i].Event == "Level" then
local level = Questie:Colorize(l10n('Level %s', Questie.db.char.journey[i].NewLevel), 'gray');
elseif Questie.dbJourney.char.journey[i].Event == "Level" then
local level = Questie:Colorize(l10n('Level %s', Questie.dbJourney.char.journey[i].NewLevel), 'gray');
recentEvents[i]:SetText(timestamp .. Questie:Colorize(l10n('Congratulations! You reached %s !', level), 'yellow'));
elseif Questie.db.char.journey[i].Event == "Note" then
local title = Questie:Colorize(Questie.db.char.journey[i].Title, 'gray');
elseif Questie.dbJourney.char.journey[i].Event == "Note" then
local title = Questie:Colorize(Questie.dbJourney.char.journey[i].Title, 'gray');
recentEvents[i]:SetText(timestamp .. Questie:Colorize(l10n('Note Created: %s', title), 'yellow'));
end
+1 -1
View File
@@ -125,7 +125,7 @@ _HandleNoteEntry = function ()
data.Title = titleBox:GetText()
data.Timestamp = time()
tinsert(Questie.db.char.journey, data)
tinsert(Questie.dbJourney.char.journey, data)
_QuestieJourney.myJourney:ManageTree(_QuestieJourney.treeCache)
_QuestieJourney.notePopup:Hide()
+2
View File
@@ -1,5 +1,6 @@
local GetAddOnMetadata = C_AddOns and C_AddOns.GetAddOnMetadata or GetAddOnMetadata
---@class QuestieLib
local QuestieLib = QuestieLoader:CreateModule("QuestieLib")
@@ -15,6 +16,7 @@ local addonName = QuestieLoader.addonName
QuestieLib.AddonPath = "Interface\\Addons\\" .. addonName .. "\\"
local math_abs = math.abs
local math_sqrt = math.sqrt
local math_max = math.max
+26 -3
View File
@@ -76,9 +76,6 @@ function QuestieLoader:CreateModule(name)
if modules[name] and modules[name]._defined then
-- Print a debug message rather than hard-error so it doesn't break live servers
-- even if another file accidentally calls CreateModule twice.
if Questie and Questie.Debug then
Questie:Debug(1, "[QuestieLoader] WARNING: CreateModule called twice for '" .. tostring(name) .. "'. Using existing module.")
end
return modules[name]
end
if not modules[name] then
@@ -114,3 +111,29 @@ function QuestieLoader:PopulateGlobals() -- called when debugging is enabled
end
end
-- Initialize Questie object early to avoid nil errors during loading
local Questie = QuestieLoader:CreateModule("Questie")
_G.Questie = Questie
-- Initial stubs for Debug and Colorize so early calls don't crash
Questie.DEBUG_CRITICAL = 1
Questie.DEBUG_ELEVATED = 2
Questie.DEBUG_INFO = 4
Questie.DEBUG_DEVELOP = 8
Questie.DEBUG_SPAM = 16
Questie.DEBUG_LEARNER = 32
Questie.DEBUG_COMMS = 64
function Questie:Debug(level, ...)
-- Initial stub: just print to chat if it's a critical message
-- This will be replaced by the real Questie:Debug in Questie.lua
if level == Questie.DEBUG_CRITICAL then
print("|cFFFFFF00[Questie-X Pre-Init Debug]|r", ...)
end
end
function Questie:Colorize(str, color)
-- Initial stub: just return the string without color or with basic color
return str
end
+8
View File
@@ -48,6 +48,14 @@ function QuestiePluginAPI:RegisterPlugin(pluginName)
self.registeredPlugins[pluginName] = plugin
Questie:Debug(Questie.DEBUG_INFO, "[QuestiePluginAPI] Successfully registered plugin: " .. pluginName)
if pluginName == "WotLKDB" and Questie.wotlkStatsCache then
Questie:Debug(Questie.DEBUG_INFO, "[QuestiePluginAPI] Applying cached WotLK stats...")
plugin.stats.QUEST = Questie.wotlkStatsCache.QUEST or 0
plugin.stats.NPC = Questie.wotlkStatsCache.NPC or 0
plugin.stats.OBJECT = Questie.wotlkStatsCache.OBJECT or 0
plugin.stats.ITEM = Questie.wotlkStatsCache.ITEM or 0
end
return plugin
end
+53
View File
@@ -66,6 +66,59 @@ local migrationFunctions = {
end,
[5] = function()
Questie.db.profile.enableTooltipsNextInChain = true
end,
[6] = function()
if Questie.dbCache and Questie.dbCache.global then
Questie:Debug(Questie.DEBUG_INFO, "[Migration] Offloading compiled database binary blobs to separate SavedVariable...")
local keys = {"npcBin", "npcPtrs", "questBin", "questPtrs", "objBin", "objPtrs", "itemBin", "itemPtrs"}
-- Handle standard keys
for _, k in ipairs(keys) do
if Questie.db.global[k] then
Questie.dbCache.global[k] = Questie.db.global[k]
Questie.db.global[k] = nil
end
end
-- Handle SoD keys
if Questie.db.global.sod then
Questie.dbCache.global.sod = Questie.dbCache.global.sod or {}
for _, k in ipairs(keys) do
if Questie.db.global.sod[k] then
Questie.dbCache.global.sod[k] = Questie.db.global.sod[k]
Questie.db.global.sod[k] = nil
end
end
-- Also move other SoD metadata
local sodMetadata = {"dbCompiledOnVersion", "dbCompiledLang", "dbIsCompiled", "dbCompiledCount"}
for _, k in ipairs(sodMetadata) do
if Questie.db.global.sod[k] then
Questie.dbCache.global.sod[k] = Questie.db.global.sod[k]
Questie.db.global.sod[k] = nil
end
end
end
-- Move global metadata
local globalMetadata = {"dbCompiledExpansion", "dbCompiledOnVersion", "dbCompiledLang", "dbIsCompiled", "dbCompiledCount"}
for _, k in ipairs(globalMetadata) do
if Questie.db.global[k] then
Questie.dbCache.global[k] = Questie.db.global[k]
Questie.db.global[k] = nil
end
end
end
end,
[7] = function()
-- Offload Journey history to its own SavedVariable
if Questie.dbJourney and Questie.dbJourney.char then
if Questie.db.char and Questie.db.char.journey and (table.getn(Questie.db.char.journey) > 0) then
Questie:Debug(Questie.DEBUG_INFO, "[Migration] Offloading Journey history to separate SavedVariable...")
Questie.dbJourney.char.journey = Questie.db.char.journey
Questie.db.char.journey = nil
end
end
-- Final cleanup of old learnedData from main config if still present
if Questie.db and Questie.db.global and Questie.db.global.learnedData then
Questie.db.global.learnedData = nil
end
end
}
@@ -28,7 +28,7 @@ local function GetServer()
end
local function GetLearnedCounts()
local ld = Questie.db and Questie.db.global and Questie.db.global.learnedData
local ld = Questie.dbLearner and Questie.dbLearner.global
local none = { npcs = 0, quests = 0, items = 0, objects = 0, total = 0 }
if not ld then return none end
local bucket = ld[GetServer()] or (ld.npcs and ld) or nil
@@ -210,10 +210,10 @@ function QuestieOptions.tabs.database:Initialize()
order = 2.1,
name = function() return l10n("Learn NPCs") end,
desc = function() return l10n("Record quest-relevant NPC positions and data.") end,
get = function() return Questie.db.global.learnedData and Questie.db.global.learnedData.settings and Questie.db.global.learnedData.settings.learnNpcs end,
get = function() return Questie.dbLearner.global and Questie.dbLearner.global.settings and Questie.dbLearner.global.settings.learnNpcs end,
set = function(_, v)
if Questie.db.global.learnedData and Questie.db.global.learnedData.settings then
Questie.db.global.learnedData.settings.learnNpcs = v
if Questie.dbLearner.global and Questie.dbLearner.global.settings then
Questie.dbLearner.global.settings.learnNpcs = v
end
end,
},
@@ -223,10 +223,10 @@ function QuestieOptions.tabs.database:Initialize()
order = 2.2,
name = function() return l10n("Learn Quests") end,
desc = function() return l10n("Record quest metadata, objectives, and rewards.") end,
get = function() return Questie.db.global.learnedData and Questie.db.global.learnedData.settings and Questie.db.global.learnedData.settings.learnQuests end,
get = function() return Questie.dbLearner.global and Questie.dbLearner.global.settings and Questie.dbLearner.global.settings.learnQuests end,
set = function(_, v)
if Questie.db.global.learnedData and Questie.db.global.learnedData.settings then
Questie.db.global.learnedData.settings.learnQuests = v
if Questie.dbLearner.global and Questie.dbLearner.global.settings then
Questie.dbLearner.global.settings.learnQuests = v
end
end,
},
@@ -236,10 +236,10 @@ function QuestieOptions.tabs.database:Initialize()
order = 2.3,
name = function() return l10n("Learn Objects") end,
desc = function() return l10n("Record interactable quest object positions.") end,
get = function() return Questie.db.global.learnedData and Questie.db.global.learnedData.settings and Questie.db.global.learnedData.settings.learnObjects end,
get = function() return Questie.dbLearner.global and Questie.dbLearner.global.settings and Questie.dbLearner.global.settings.learnObjects end,
set = function(_, v)
if Questie.db.global.learnedData and Questie.db.global.learnedData.settings then
Questie.db.global.learnedData.settings.learnObjects = v
if Questie.dbLearner.global and Questie.dbLearner.global.settings then
Questie.dbLearner.global.settings.learnObjects = v
end
end,
},
@@ -249,10 +249,10 @@ function QuestieOptions.tabs.database:Initialize()
order = 2.4,
name = function() return l10n("Learn Items") end,
desc = function() return l10n("Record quest item drop sources.") end,
get = function() return Questie.db.global.learnedData and Questie.db.global.learnedData.settings and Questie.db.global.learnedData.settings.learnItems end,
get = function() return Questie.dbLearner.global and Questie.dbLearner.global.settings and Questie.dbLearner.global.settings.learnItems end,
set = function(_, v)
if Questie.db.global.learnedData and Questie.db.global.learnedData.settings then
Questie.db.global.learnedData.settings.learnItems = v
if Questie.dbLearner.global and Questie.dbLearner.global.settings then
Questie.dbLearner.global.settings.learnItems = v
end
end,
},
@@ -374,9 +374,9 @@ function QuestieOptions.tabs.database:Initialize()
min = 1,
max = 180,
step = 1,
get = function() return (Questie.db.global.learnedData.settings and Questie.db.global.learnedData.settings.staleThreshold) or 90 end,
get = function() return (Questie.dbLearner.global.settings and Questie.dbLearner.global.settings.staleThreshold) or 90 end,
set = function(_, val)
Questie.db.global.learnedData.settings.staleThreshold = val
Questie.dbLearner.global.settings.staleThreshold = val
end,
},
@@ -385,9 +385,9 @@ function QuestieOptions.tabs.database:Initialize()
order = 5.3,
name = function() return l10n("Include Verified Data in Pruning") end,
desc = function() return l10n("If enabled, even high-confidence (Verified) data will be subject to redundancy pruning (e.g., if it's already in the official DB). Time-based pruning still only affects unconfirmed data.") end,
get = function() return (Questie.db.global.learnedData.settings and Questie.db.global.learnedData.settings.pruneVerified) or false end,
get = function() return (Questie.dbLearner.global.settings and Questie.dbLearner.global.settings.pruneVerified) or false end,
set = function(_, val)
Questie.db.global.learnedData.settings.pruneVerified = val
Questie.dbLearner.global.settings.pruneVerified = val
end,
},
@@ -435,7 +435,7 @@ function QuestieOptions.tabs.database:Initialize()
confirmText = "Are you sure? This cannot be undone.",
func = function()
if Questie.db and Questie.db.global then
Questie.db.global.learnedData = nil
Questie.dbLearner.global = nil
Questie:Print("|cFFFF4444[Questie-X]|r All learned data has been reset.")
end
end,
+1 -1
View File
@@ -1324,7 +1324,7 @@ function QuestieQuest:PopulateObjective(quest, objectiveIndex, objective, blockI
end
-- Filter static spawns if prioritizeMyData is enabled and we have high-confidence learned data
if Questie.db.global.learnedData and Questie.db.global.learnedData.settings and Questie.db.global.learnedData.settings.prioritizeMyData then
if Questie.dbLearner and Questie.dbLearner.global and Questie.dbLearner.global.settings and Questie.dbLearner.global.settings.prioritizeMyData then
for zone in pairs(zones) do
local suppressed = (objectiveData.Type == "monster" and QuestieDB.GetSuppressedNPCs(zone)) or (objectiveData.Type == "object" and QuestieDB.GetSuppressedObjects(zone))
if suppressed then
+12 -10
View File
@@ -1,9 +1,11 @@
---@diagnostic disable: undefined-global, return-type-mismatch, undefined-field
---@class QuestieCompat
---@type table|_G
QuestieCompat = setmetatable({}, { __index = _G })
QuestieCompat = QuestieLoader:CreateModule("QuestieCompat")
setmetatable(QuestieCompat, { __index = _G })
QuestieCompat.addonName = QuestieLoader.addonName
------------------------------------------
-- Lua 5.0 / 5.1 / 5.2 compatibility shims
-- NOTE: string.match, select(), and math.mod shims live in QuestieLoader.lua
@@ -17,8 +19,6 @@ end
-- Polyfill for xpcall variadic arguments (missing in standard Lua 5.0/5.1 WoW clients).
-- Modern Ace3 uses xpcall(func, err, ...) which drops arguments on legacy clients,
-- leading to 'self' being nil in addon callbacks.
-- Fix #14: Do NOT write to bare _G.xpcall — store in QuestieCompat namespace only.
-- Writing to _G.xpcall pollutes the global namespace and can cause taint on protected contexts.
local _xpcall = xpcall
local xpcall_supported = false
pcall(function()
@@ -58,6 +58,9 @@ if not xpcall_supported then
-- No extra args provided
return _xpcall(func, err)
end
-- Crucial: Expose to the global environment so that unmodified Ace3 libraries (like AceGUI-3.0)
-- will pick it up instead of using the broken native version which drops arguments causing crashes.
_G.xpcall = QuestieCompat.xpcall
else
-- Native xpcall works fine, expose it
QuestieCompat.xpcall = _xpcall
@@ -241,6 +244,7 @@ else
return ticker
end
}
_G.C_Timer = QuestieCompat.C_Timer
end
---[SetMinResize Documentation](https://wowpedia.fandom.com/wiki/API_Frame_SetMinResize)
@@ -414,7 +418,9 @@ function QuestieCompat.GetItemCooldown(itemID)
end
--- C_QuestLog Shim
QuestieCompat.C_QuestLog = QuestieCompat.C_QuestLog or {}
if not rawget(QuestieCompat, "C_QuestLog") then
QuestieCompat.C_QuestLog = {}
end
function QuestieCompat.C_QuestLog.GetNumQuestLogEntries()
return GetNumQuestLogEntries()
@@ -444,13 +450,8 @@ function QuestieCompat.C_QuestLog.GetAllQuestIDs()
return questIDs
end
function QuestieCompat.C_QuestLog.GetQuestObjectives(questID)
local questIndex = GetQuestLogIndexByID(questID)
if not questIndex then return nil end
return QuestieCompat.GetQuestObjectives(questIndex)
end
function QuestieCompat.C_QuestLog.IsQuestFlaggedCompleted(questID)
return IsQuestFlaggedCompleted(questID)
end
@@ -492,3 +493,4 @@ end
QuestieCompat.LibUIDropDownMenu = QuestieCompat.LibUIDropDownMenu or {}
QuestieCompat.LibUIDropDownMenu.UIDropDownMenu_Menu_NewSize = function()
end
+3
View File
@@ -225,7 +225,10 @@ function QuestieEventHandler:RegisterLateEvents()
end)
end
local _PlayerLoginFired = false
function _EventHandler:PlayerLogin()
if _PlayerLoginFired then return end
_PlayerLoginFired = true
-- Check config exists
if not Questie.db or not QuestieConfig then
-- Did you move Questie.db = LibStub("AceDB-3.0"):New("QuestieConfig",.......) out of Questie:OnInitialize() ?
+74 -9
View File
@@ -1,4 +1,5 @@
---@class QuestieInit
local QuestieInit = QuestieLoader:CreateModule("QuestieInit")
local _QuestieInit = QuestieInit.private
@@ -57,6 +58,8 @@ local QuestieValidateGameCache = QuestieLoader:ImportModule("QuestieValidateGame
local MinimapIcon = QuestieLoader:ImportModule("MinimapIcon")
---@type QuestieComms
local QuestieComms = QuestieLoader:ImportModule("QuestieComms");
---@type QuestieCompat
local QuestieCompat = QuestieLoader:ImportModule("QuestieCompat")
---@type QuestieOptions
local QuestieOptions = QuestieLoader:ImportModule("QuestieOptions");
---@type QuestieCoords
@@ -92,7 +95,14 @@ local QuestieServer = QuestieLoader:ImportModule("QuestieServer")
local WOW_PROJECT_ID = QuestieCompat.WOW_PROJECT_ID
local C_Timer = QuestieCompat.C_Timer
local coYield = coroutine.yield
-- Safe yield: only yields when we are actually inside a running coroutine.
-- Without this check, coroutine.yield() throws "attempt to yield across C-call boundary"
-- when Stage 1 runs synchronously inside AceAddon's pcall (a C stack frame).
local function coYield()
if coroutine.running() then
coroutine.yield()
end
end
local function _dbStats(t)
if type(t) ~= "table" then return "type=" .. type(t) end
@@ -136,6 +146,29 @@ local function loadFullDatabase()
QuestieCorrections:PreCompile()
end
function QuestieInit:OnInitialize()
if QuestieInit.initialized then return end
QuestieInit.initialized = true
if QuestieInit.Stages and QuestieInit.Stages[1] and (not QuestieInit.stage1Done) then
QuestieInit.stage1Done = true
-- Run Stage 1 inside a coroutine so that all coroutine.yield() calls
-- in Stage 1 and its callees (Townsfolk, compiler, etc.) have a valid
-- coroutine context. AceAddon calls OnInitialize from a C pcall boundary
-- so calling coroutine.yield() without an enclosing coroutine crashes.
-- We drain the coroutine synchronously (resume until dead) so that
-- QuestieDB.QuestPointers is set before OnInitialize returns.
local co = coroutine.create(QuestieInit.Stages[1])
while coroutine.status(co) == "suspended" do
local ok, err = coroutine.resume(co)
if not ok then
print(debugstack(co))
break
end
end
else
end
end
---Run the validator
local function runValidator()
if type(QuestieDB.questData) == "string" or type(QuestieDB.npcData) == "string" or type(QuestieDB.objectData) == "string" or type(QuestieDB.itemData) == "string" then
@@ -226,16 +259,22 @@ QuestieInit.Stages[1] = function() -- run as a coroutine
dbCompiledLang = Questie.db.global.dbCompiledLang
end
if Questie.IsSoD then
coYield()
SeasonOfDiscovery.Initialize()
end
-- Check if the DB needs to be recompiled
do
local addonV = QuestieLib:GetAddonVersionString()
local uiLoc = l10n:GetUILocale()
local storedExp = Questie.db.global.dbCompiledExpansion
end
if (not dbIsCompiled) or (QuestieLib:GetAddonVersionString() ~= dbCompiledOnVersion) or (l10n:GetUILocale() ~= dbCompiledLang) or (Questie.db.global.dbCompiledExpansion ~= WOW_PROJECT_ID) then
print("\124cFFAAEEFF" ..
print("|cFFAAEEFF" ..
l10n("Questie DB has updated!") ..
"\124r\124cFFFF6F22 " .. l10n("Data is being processed, this may take a few moments and cause some lag..."))
"|r|cFFFF6F22 " .. l10n("Data is being processed, this may take a few moments and cause some lag..."))
loadFullDatabase()
Questie:Debug(Questie.DEBUG_DEVELOP, "[DBDiag] Before Compile - quest:" .. _dbStats(QuestieDB.questData) .. " npc:" .. _dbStats(QuestieDB.npcData))
QuestieDBCompiler:Compile()
@@ -294,10 +333,15 @@ QuestieInit.Stages[2] = function()
local keepWaiting = true
-- We had users reporting that a quest did not reach a valid state in the game cache.
-- In this case we still need to continue the initialization process, even though a specific quest might be bugged
-- 3-second timeout for cache validation
C_Timer.After(3, function()
if keepWaiting then
Questie:Debug(Questie.DEBUG_CRITICAL, "QuestieInit: Timeout waiting for Game Cache validation. Continuing.")
Questie:Error("[QuestieInit:Stage2] Quest cache validation timed out! Some data may be missing.")
keepWaiting = false
local ok, err = coroutine.resume(QuestieInit.Thread)
if not ok then
Questie:Debug(Questie.DEBUG_INFO, "[QuestieInit:Stage2] Resume failed (timeout): " .. tostring(err))
end
end
end)
@@ -424,6 +468,7 @@ function QuestieInit:LoadDatabase(key)
elseif tocversion >= 20500 and tocversion < 30000 then isModernClient = true -- TBC Classic
elseif tocversion >= 30400 and tocversion < 40000 then isModernClient = true -- WotLK Classic
elseif tocversion >= 40400 and tocversion < 50000 then isModernClient = true -- Cata Classic
elseif tocversion >= 50000 and tocversion < 60000 then isModernClient = true -- MoP (e.g. 50400)
end
end
if isModernClient then
@@ -473,8 +518,7 @@ function QuestieInit:UpdateWotLKDBStats()
OBJECT = _countTable(_G["QuestieX_WotLKDB_object"]),
ITEM = _countTable(_G["QuestieX_WotLKDB_item"]),
}
-- Fix #11: Do NOT write to _G.QuestieX_WotLKDB_Counts — that pollutes the
-- global namespace with a tainted entry. Push counts only to the plugin object.
Questie.wotlkStatsCache = counts
local QuestiePluginAPI = QuestieLoader:ImportModule("QuestiePluginAPI")
if QuestiePluginAPI then
local wotlkPlugin = QuestiePluginAPI:GetPlugin("WotLKDB")
@@ -529,7 +573,7 @@ function QuestieInit:LoadBaseDB()
}
Questie:Debug(Questie.DEBUG_DEVELOP, "[DBDiag] WotLKDB pull: quest=" .. tostring(_pulled.quest) .. " npc=" .. tostring(_pulled.npc) .. " obj=" .. tostring(_pulled.object) .. " item=" .. tostring(_pulled.item))
-- Fix #11: second site — push counts only to plugin object, not to _G.
Questie.wotlkStatsCache = _counts
local QuestiePluginAPI = QuestieLoader:ImportModule("QuestiePluginAPI")
if QuestiePluginAPI then
local wotlkPlugin = QuestiePluginAPI:GetPlugin("WotLKDB")
@@ -549,15 +593,36 @@ end
function _QuestieInit.StartStageCoroutine()
for i = 1, #QuestieInit.Stages do
if i == 1 and QuestieInit.stage1Done then
Questie:Debug(Questie.DEBUG_INFO, "[QuestieInit:StartStageCoroutine] Stage 1 already done, skipping.")
else
if i == 1 then QuestieInit.stage1Done = true end
QuestieInit.Stages[i]()
Questie:Debug(Questie.DEBUG_INFO, "[QuestieInit:StartStageCoroutine] Stage " .. i .. " done.")
end
end
end
-- called by the PLAYER_LOGIN event handler
function QuestieInit:Init()
ThreadLib.ThreadError(_QuestieInit.StartStageCoroutine, Questie.db.profile.initDelay or 0,
l10n("Error during initialization!"))
QuestieInit.Thread = coroutine.create(_QuestieInit.StartStageCoroutine)
local function resumeInit()
if not QuestieInit.Thread or coroutine.status(QuestieInit.Thread) == "dead" then
return -- coroutine finished or failed
end
local ok, err = coroutine.resume(QuestieInit.Thread)
if not ok then
local stack = debugstack(QuestieInit.Thread)
local msg = "QuestieInit Thread CRASHED: " .. tostring(err) .. "\n" .. tostring(stack)
Questie:Error(msg)
print("|cFFFF0000" .. msg .. "|r")
elseif coroutine.status(QuestieInit.Thread) ~= "dead" then
C_Timer.After(0.02, resumeInit) -- continue yielding using the timer shim
end
end
resumeInit()
if Questie.db.profile.trackerEnabled then
-- This needs to be called ASAP otherwise tracked Achievements in the Blizzard WatchFrame shows upon login
+65 -56
View File
@@ -146,15 +146,25 @@ end
------------------------------------------------------------------------
local function EnsureLearnedData()
if not Questie.db then return false end
local ld = Questie.db.global.learnedData
if not ld then
Questie.db.global.learnedData = {
npcs = {},
quests = {},
items = {},
objects = {},
settings = {
if not Questie.db or not Questie.dbLearner then return false end
-- Migration: If data exists in the old QuestieConfig.global.learnedData, move it to the new QuestieLearnerDB.global
if Questie.db.global.learnedData then
Questie:Debug(Questie.DEBUG_INFO, "[QuestieLearner] Migrating learnedData to separate SavedVariable...")
for k, v in pairs(Questie.db.global.learnedData) do
Questie.dbLearner.global[k] = v
end
Questie.db.global.learnedData = nil
Questie:Print("|cFF5EBAF3Questie-X:|r Learned data has been migrated to a separate SavedVariable for better performance.")
end
local ld = Questie.dbLearner.global
if (not ld.npcs) and (not ld.quests) then
ld.npcs = {}
ld.quests = {}
ld.items = {}
ld.objects = {}
ld.settings = {
enabled = true,
learnNpcs = true,
learnQuests = true,
@@ -164,7 +174,6 @@ local function EnsureLearnedData()
prioritizeMyData = true,
staleThreshold = 90, -- days
pruneVerified = false, -- protect verified data by default
},
}
else
-- Backfill sub-tables that may be missing from older SavedVariables
@@ -191,12 +200,12 @@ end
function QuestieLearner:IsEnabled()
if not EnsureLearnedData() then return false end
return Questie.db.global.learnedData.settings.enabled
return Questie.dbLearner.global.settings.enabled
end
function QuestieLearner:GetSettings()
if not EnsureLearnedData() then return {} end
return Questie.db.global.learnedData.settings
return Questie.dbLearner.global.settings
end
------------------------------------------------------------------------
@@ -264,7 +273,7 @@ local function _AddToQuestObjective(qData, slot, entityId, text, ovrTable, quest
end
end
local function _GetDB() return Questie.db.global.learnedData end
local function _GetDB() return Questie.dbLearner.global end
-- Triggers QuestieQuest:UpdateQuest for every active quest in the player's log
-- that is referenced in the provided set (table with questId keys).
@@ -557,7 +566,7 @@ end
function QuestieLearner:LearnNPC(npcId, name, level, subName, npcFlags, factionString, spawnX, spawnY, spawnZoneId)
if not self:IsEnabled() then return end
if not Questie.db.global.learnedData.settings.learnNpcs then return end
if not Questie.dbLearner.global.settings.learnNpcs then return end
if not npcId or npcId <= 0 then return end
-- Use provided spawn coords (e.g. from kill event) or fall back to current player position
@@ -569,11 +578,11 @@ function QuestieLearner:LearnNPC(npcId, name, level, subName, npcFlags, factionS
x, y = GetPlayerCoords()
end
local existing = Questie.db.global.learnedData.npcs[npcId]
local existing = Questie.dbLearner.global.npcs[npcId]
local isNew = existing == nil
if not existing then
existing = {}
Questie.db.global.learnedData.npcs[npcId] = existing
Questie.dbLearner.global.npcs[npcId] = existing
end
if name and not existing[1] then existing[1] = name end
@@ -593,7 +602,7 @@ function QuestieLearner:LearnNPC(npcId, name, level, subName, npcFlags, factionS
existing.ls = time() -- Update last seen
existing.mc = (existing.mc or 0) + 1
local threshold = (Questie.db.global.learnedData.settings and Questie.db.global.learnedData.settings.minConfidencePins) or MIN_CONFIDENCE_PINS
local threshold = (Questie.dbLearner.global.settings and Questie.dbLearner.global.settings.minConfidencePins) or MIN_CONFIDENCE_PINS
-- Live injection: update npcDataOverrides only if confidence threshold is met
if existing.mc >= threshold and QuestieDB and QuestieDB.npcDataOverrides then
@@ -640,17 +649,17 @@ function QuestieLearner:LearnQuest(questId, data)
Questie:Debug(Questie.DEBUG_LEARNER, "[QuestieLearner] LearnQuest blocked: learner not enabled")
return
end
if not Questie.db.global.learnedData.settings.learnQuests then
Questie:Debug(Questie.DEBUG_LEARNER, "[QuestieLearner] LearnQuest blocked: learnQuests=", tostring(Questie.db.global.learnedData.settings.learnQuests))
if not Questie.dbLearner.global.settings.learnQuests then
Questie:Debug(Questie.DEBUG_LEARNER, "[QuestieLearner] LearnQuest blocked: learnQuests=", tostring(Questie.dbLearner.global.settings.learnQuests))
return
end
if not questId or questId <= 0 then return end
local existing = Questie.db.global.learnedData.quests[questId]
local existing = Questie.dbLearner.global.quests[questId]
local isNew = existing == nil
if not existing then
existing = {}
Questie.db.global.learnedData.quests[questId] = existing
Questie.dbLearner.global.quests[questId] = existing
end
existing.ls = time() -- Update last seen
@@ -685,13 +694,13 @@ end
-- Records the NPC/object that starts or finishes a quest (array index [2] or [3])
function QuestieLearner:LearnQuestGiver(questId, entityId, entityType, isStart)
if not self:IsEnabled() then return end
if not Questie.db.global.learnedData.settings.learnQuests then return end
if not Questie.dbLearner.global.settings.learnQuests then return end
if not questId or questId <= 0 or not entityId or entityId <= 0 then return end
local existing = Questie.db.global.learnedData.quests[questId]
local existing = Questie.dbLearner.global.quests[questId]
if not existing then
existing = {}
Questie.db.global.learnedData.quests[questId] = existing
Questie.dbLearner.global.quests[questId] = existing
end
-- Starters/finishers: { [1]={npcIds}, [2]={objIds}, [3]={itemIds} }
@@ -733,12 +742,12 @@ end
-- we only need the quest to reference it so tooltips/map-pins get registered.
function QuestieLearner:LearnQuestObjectiveNPC(questId, npcId, objText)
if not self:IsEnabled() then return end
if not Questie.db.global.learnedData.settings.learnQuests then return end
if not Questie.dbLearner.global.settings.learnQuests then return end
if not questId or questId <= 0 or not npcId or npcId <= 0 then return end
-- 1. Persist to SavedVariables
local existing = Questie.db.global.learnedData.quests[questId] or {}
Questie.db.global.learnedData.quests[questId] = existing
local existing = Questie.dbLearner.global.quests[questId] or {}
Questie.dbLearner.global.quests[questId] = existing
existing[10] = existing[10] or {}
existing[10][1] = existing[10][1] or {} -- creatureObjective slot
local alreadyInSV = false
@@ -787,14 +796,14 @@ end
function QuestieLearner:LearnItem(itemId, name, itemLevel, requiredLevel, itemClass, itemSubClass)
if not self:IsEnabled() then return end
if not Questie.db.global.learnedData.settings.learnItems then return end
if not Questie.dbLearner.global.settings.learnItems then return end
if not itemId or itemId <= 0 then return end
local existing = Questie.db.global.learnedData.items[itemId]
local existing = Questie.dbLearner.global.items[itemId]
local isNew = existing == nil
if not existing then
existing = {}
Questie.db.global.learnedData.items[itemId] = existing
Questie.dbLearner.global.items[itemId] = existing
end
if name and not existing[1] then existing[1] = name end
@@ -826,13 +835,13 @@ end
function QuestieLearner:LearnItemDrop(itemId, npcId)
if not self:IsEnabled() then return end
if not Questie.db.global.learnedData.settings.learnItems then return end
if not Questie.dbLearner.global.settings.learnItems then return end
if not itemId or itemId <= 0 or not npcId or npcId <= 0 then return end
local existing = Questie.db.global.learnedData.items[itemId]
local existing = Questie.dbLearner.global.items[itemId]
if not existing then
existing = {}
Questie.db.global.learnedData.items[itemId] = existing
Questie.dbLearner.global.items[itemId] = existing
end
existing.ls = time() -- Update last seen
@@ -865,17 +874,17 @@ end
function QuestieLearner:LearnObject(objectId, name)
if not self:IsEnabled() then return end
if not Questie.db.global.learnedData.settings.learnObjects then return end
if not Questie.dbLearner.global.settings.learnObjects then return end
if not objectId or objectId <= 0 then return end
local zoneId = GetZoneId()
local x, y = GetPlayerCoords()
local existing = Questie.db.global.learnedData.objects[objectId]
local existing = Questie.dbLearner.global.objects[objectId]
local isNew = existing == nil
if not existing then
existing = {}
Questie.db.global.learnedData.objects[objectId] = existing
Questie.dbLearner.global.objects[objectId] = existing
end
if name and not existing[1] then existing[1] = name end
@@ -957,7 +966,7 @@ end
function QuestieLearner:InjectLearnedData()
if not EnsureLearnedData() then return end
local learned = Questie.db.global.learnedData
local learned = Questie.dbLearner.global
local npcCount, questCount, itemCount, objectCount = 0, 0, 0, 0
-- 1. NPCs
@@ -1079,7 +1088,7 @@ end
function QuestieLearner:GetStats()
if not EnsureLearnedData() then return 0, 0, 0, 0 end
local learned = Questie.db.global.learnedData
local learned = Questie.dbLearner.global
local n, q, i, o = 0, 0, 0, 0
for _ in pairs(learned.npcs) do n = n + 1 end
for _ in pairs(learned.quests) do q = q + 1 end
@@ -1090,10 +1099,10 @@ end
function QuestieLearner:ClearAllData()
if not EnsureLearnedData() then return end
Questie.db.global.learnedData.npcs = {}
Questie.db.global.learnedData.quests = {}
Questie.db.global.learnedData.items = {}
Questie.db.global.learnedData.objects = {}
Questie.dbLearner.global.npcs = {}
Questie.dbLearner.global.quests = {}
Questie.dbLearner.global.items = {}
Questie.dbLearner.global.objects = {}
Questie:Print("Cleared all learned data.")
end
@@ -1113,7 +1122,7 @@ end
function QuestieLearner:ExportData()
if not EnsureLearnedData() then return "" end
local learned = Questie.db.global.learnedData
local learned = Questie.dbLearner.global
local lines = {}
table.insert(lines, "-- QuestieLearner Export")
local n, q, i, o = self:GetStats()
@@ -1461,7 +1470,7 @@ end
-- Fires when any quest is turned in (covers auto-complete quests that skip the QUEST_COMPLETE dialog)
function QuestieLearner:OnQuestTurnedIn(questId, xpReward, moneyReward)
if not self:IsEnabled() then return end
if not Questie.db.global.learnedData.settings.learnQuests then return end
if not Questie.dbLearner.global.settings.learnQuests then return end
if not questId or questId <= 0 then return end
local data = {}
@@ -1487,7 +1496,7 @@ end
-- Loot handler with async GetItemInfo retry
function QuestieLearner:OnLootOpened()
if not self:IsEnabled() then return end
if not Questie.db.global.learnedData.settings.learnItems then return end
if not Questie.dbLearner.global.settings.learnItems then return end
local targetGuid = UnitGUID("target")
local npcId = targetGuid and GetNpcIdFromGUID(targetGuid) or nil
@@ -1806,7 +1815,7 @@ end
function QuestieLearner:Initialize()
EnsureLearnedData()
QuestieLearner.data = Questie.db.global.learnedData
QuestieLearner.data = Questie.dbLearner.global
self:RegisterEvents()
self:InjectLearnedData()
@@ -1843,17 +1852,17 @@ function QuestieLearner:HandleNetworkData(typ, id, d, op)
local store
if typ == "NPC" then
if not Questie.db.global.learnedData.settings.learnNpcs then return end
store = Questie.db.global.learnedData.npcs
if not Questie.dbLearner.global.settings.learnNpcs then return end
store = Questie.dbLearner.global.npcs
elseif typ == "QUEST" then
if not Questie.db.global.learnedData.settings.learnQuests then return end
store = Questie.db.global.learnedData.quests
if not Questie.dbLearner.global.settings.learnQuests then return end
store = Questie.dbLearner.global.quests
elseif typ == "ITEM" then
if not Questie.db.global.learnedData.settings.learnItems then return end
store = Questie.db.global.learnedData.items
if not Questie.dbLearner.global.settings.learnItems then return end
store = Questie.dbLearner.global.items
elseif typ == "OBJECT" then
if not Questie.db.global.learnedData.settings.learnObjects then return end
store = Questie.db.global.learnedData.objects
if not Questie.dbLearner.global.settings.learnObjects then return end
store = Questie.dbLearner.global.objects
else
return
end
@@ -1863,7 +1872,7 @@ function QuestieLearner:HandleNetworkData(typ, id, d, op)
store[id] = d
store[id].mc = 1
self:InjectLearnedData()
QuestieLearner.data = Questie.db.global.learnedData
QuestieLearner.data = Questie.dbLearner.global
return
end
@@ -1909,7 +1918,7 @@ function QuestieLearner:HandleNetworkData(typ, id, d, op)
if changed or (op == "NEW" or op == "UPDATE") then
existing.ls = time() -- Refresh timestamp on network confirmation
existing.mc = (existing.mc or 0) + 1
QuestieLearner.data = Questie.db.global.learnedData
QuestieLearner.data = Questie.dbLearner.global
self:InjectLearnedData()
end
end
+9 -5
View File
@@ -48,9 +48,8 @@ local function GetServerKey()
return realm ~= "" and realm or "unknown"
end
-- Returns the learnedData sub-table for the current server, or nil
local function GetServerBucket(serverKey)
local ld = Questie.db and Questie.db.global and Questie.db.global.learnedData
function QuestieLearnerExport:GetExportTable(serverKey)
local ld = Questie.dbLearner and Questie.dbLearner.global
if not ld then return nil end
if ld[serverKey] then return ld[serverKey] end
-- Fallback: flat (pre-bucket) layout still in use
@@ -58,6 +57,11 @@ local function GetServerBucket(serverKey)
return nil
end
-- Returns the learnedData sub-table for the current server, or nil
local function GetServerBucket(serverKey)
return QuestieLearnerExport:GetExportTable(serverKey)
end
-- Builds a lightweight stats summary table from a bucket
local function BuildStats(bucket)
if not bucket then return { npcs = 0, quests = 0, items = 0, objects = 0, total = 0 } end
@@ -127,7 +131,7 @@ end
--- Exports ALL server buckets merged into one payload.
---@return string|nil, table|string
function QuestieLearnerExport:ExportAll()
local ld = Questie.db and Questie.db.global and Questie.db.global.learnedData
local ld = Questie.dbLearner and Questie.dbLearner.global
if not ld then return nil, "No learned data." end
local merged = { npcs = {}, quests = {}, items = {}, objects = {} }
@@ -326,7 +330,7 @@ function _Export:RunPrune(dryRun)
local result = { npcs = 0, quests = 0, items = 0, objects = 0, total = 0, reasons = {} }
if not bucket then return result end
local settings = (Questie.db.global.learnedData and Questie.db.global.learnedData.settings) or {}
local settings = (Questie.dbLearner and Questie.dbLearner.global and Questie.dbLearner.global.settings) or {}
local thresholdDays = settings.staleThreshold or 90
local thresholdSeconds = thresholdDays * 86400
local minConfidence = settings.minConfidencePins or 2
+99 -93
View File
@@ -1,4 +1,5 @@
--[[
Flow:
-> QuestieValidateGameCache.StartCheck()
--> Wait for PLAYER_ENTERING_WORLD
@@ -10,16 +11,9 @@ Flow:
---@class QuestieValidateGameCache
local QuestieValidateGameCache = QuestieLoader:CreateModule("QuestieValidateGameCache")
---@type QuestieLib
local QuestieLib = QuestieLoader:CreateModule("QuestieLib")
--- COMPATIBILITY ---
local GetNumQuestLogEntries = GetNumQuestLogEntries
local GetQuestLogTitle = QuestieCompat.GetQuestLogTitle
local GetQuestObjectives = QuestieCompat.C_QuestLog.GetQuestObjectives
local HaveQuestData = QuestieCompat.HaveQuestData
local QuestieLib = QuestieLoader:ImportModule("QuestieLib")
local QuestieCompat = QuestieLoader:ImportModule("QuestieCompat")
-- Defer API assignments to runtime to avoid load-order nil errors
local stringByte, tremove = string.byte, table.remove
local tpack = QuestieLib.tpack
@@ -27,94 +21,83 @@ local tunpack = QuestieLib.tunpack
-- 3 * (Max possible number of quests in game quest log)
-- This is a safe value, even smaller would be enough. Too large won't effect performance
local MAX_QUEST_LOG_INDEX = 75
local eventFrame
local numberOfQuestLogUpdatesToSkip
local numberOfQuestLogUpdatesToSkip = 0
local checkStarted = false
local eventFrame = nil
local callbacks = {}
local isCacheGood = false
local callbacks = {} -- example: { [1] = {func, {arg1, arg2, arg3}}, [2] = {func, {arg1, arg2}}, }
---@return boolean
function QuestieValidateGameCache.IsCacheGood()
return isCacheGood
end
--- Calls the callback function imediately if the cache is already good.
--- Otherwise adds it to list of functions called once the cache comes good.
---@param func function @A function to call once cache is good.
---@param ... any @Possible arguments for function.
function QuestieValidateGameCache.AddCallback(func, ...)
if isCacheGood then
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieValidateGameCache] Calling a callback function imediately.")
func(...)
else
callbacks[#callbacks + 1] = { func, tpack(...) }
end
end
local function DestroyEventFrame()
if eventFrame then
eventFrame:UnregisterAllEvents()
eventFrame:SetScript("OnEvent", nil)
eventFrame:SetParent(nil)
eventFrame = nil
end
end
-- Called directly and OnEvent.
local function OnQuestLogUpdate()
local numEntries, numQuests = GetNumQuestLogEntries()
-- Fetch APIs at runtime with extreme defensive checks
local qCompat = QuestieCompat or _G.QuestieCompat
local rawCLog = qCompat and rawget(qCompat, "C_QuestLog")
local cLog = (qCompat and qCompat.C_QuestLog) or {}
-- Player can have 0 quests in quest log for real OR game's cached quest log can be empty while cache is still invalid
-- This is to wait until cache has atleast some refreshed data from a game server.
if numberOfQuestLogUpdatesToSkip > 0 then
numberOfQuestLogUpdatesToSkip = numberOfQuestLogUpdatesToSkip - 1
Questie:Debug(Questie.DEBUG_DEVELOP,
"[QuestieValidateGameCache] Skipping a QUEST_LOG_UPDATE event. Quest log has entries, quests:", numEntries,
numQuests)
local GetNumQuestLogEntries = cLog.GetNumQuestLogEntries or _G.GetNumQuestLogEntries
local GetQuestLogTitle = cLog.GetQuestLogTitle or _G.GetQuestLogTitle
local GetNumQuestLeaderBoards = _G.GetNumQuestLeaderBoards
local GetQuestObjectives = cLog.GetQuestObjectives or function() return {} end
if isCacheGood then
DestroyEventFrame()
return
end
local isQuestLogGood = true
local goodQuestsCount = 0 -- for debug stats
for i = 1, MAX_QUEST_LOG_INDEX do
local title, level, questTag, isHeader, isCollapsed, isComplete, isDaily, questId = GetQuestLogTitle(i)
if title and questId and (not isHeader) then
if (not HaveQuestData(questId)) then
isQuestLogGood = false
else
local hasInvalidObjective -- for debug stats
local objectiveList = GetQuestObjectives(questId, i)
if type(objectiveList) ~= "table" then
-- On WotLK private servers, GetQuestObjectives can return nil for quests with
-- no trackable objectives. This is not a broken cache state; treat it as an
-- empty (valid) objective list so goodQuestsCount increments correctly.
Questie:Debug(Questie.DEBUG_DEVELOP,
"[QuestieValidateGameCache] GetQuestObjectives returned non-table for questId:", questId,
"- treating as empty objectives")
objectiveList = {}
if numberOfQuestLogUpdatesToSkip > 0 then
numberOfQuestLogUpdatesToSkip = numberOfQuestLogUpdatesToSkip - 1
return
end
for _, objective in pairs(objectiveList) do -- objectiveList may be {}, which is also a valid cached quest in quest log
if (not objective.text) or (stringByte(objective.text, 1) == 32) then -- if (text starts with a space " ") then
-- Game hasn't cached the quest fully yet
local isQuestLogGood = true
local numQuests = select(1, GetNumQuestLogEntries()) or 0
local goodQuestsCount = 0
for i = 1, numQuests do
local status, err = pcall(function()
local title, _, _, _, isHeader, _, _, _, questId = GetQuestLogTitle(i)
if title and (not isHeader) and questId and questId > 0 then
local numObjectives = GetNumQuestLeaderBoards(i) or 0
if numObjectives > 0 then
local objectiveList = GetQuestObjectives(questId, i)
if objectiveList and objectiveList[1] then
local hasInvalidObjective = false
for _, objective in pairs(objectiveList) do
if (not objective.text) or (stringByte(objective.text, 1) == 32) then
isQuestLogGood = false
hasInvalidObjective = true
-- No early "return false" here to force iterate whole quest log and speed up caching
break
end
end
if not hasInvalidObjective then
goodQuestsCount = goodQuestsCount + 1
end
else
isQuestLogGood = false
end
else
goodQuestsCount = goodQuestsCount + 1
end
end
end)
end
if not isQuestLogGood then
Questie:Debug(Questie.DEBUG_INFO, "[QuestieValidateGameCache] Quest log is NOT yet okey. Good quest:",
@@ -122,53 +105,76 @@ local function OnQuestLogUpdate()
return
end
if goodQuestsCount ~= numQuests then
-- This count mismatch can occur on WotLK private servers where GetNumQuestLogEntries
-- returns a different value than objectives-loop counted. The cache is valid because
-- isQuestLogGood already passed above. Log at debug level only.
Questie:Debug(Questie.DEBUG_INFO,
"[QuestieValidateGameCache] Quest count mismatch (expected " ..
tostring(numQuests) .. ", validated " .. tostring(goodQuestsCount) .. "). Cache is still valid.")
end
DestroyEventFrame()
Questie:Debug(Questie.DEBUG_CRITICAL, "[QuestieValidateGameCache] Quest log is ok. Good quest:",
goodQuestsCount .. "/" .. numQuests)
isCacheGood = true
-- Call all callbacks
while (#callbacks > 0) do
local callback = tremove(callbacks, 1)
local func, args = callback[1], callback[2]
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieValidateGameCache] Calling a callback.")
func(tunpack(args))
end
end
local function OnPlayerEnteringWorld(_, _, isInitialLogin, isReloadingUi)
-- 335 Cant find a way to distinguish between 'first login' and 'UI reload'
if QuestieCompat.Is335 then
isInitialLogin, isReloadingUi = false, true -- 335 Not skipping for now
end
assert(isInitialLogin or isReloadingUi) -- We should get to here only at login or at /reload.
if isInitialLogin == nil then isInitialLogin = true end
if isReloadingUi == nil then isReloadingUi = false end
if QuestieCompat.Is335 then
isInitialLogin, isReloadingUi = false, true
end
-- Game's quest log has still old cached data on the first QUEST_LOG_UPDATE after PLAYER_ENTERING_WORLD during login.
-- So we need to skip that event.
numberOfQuestLogUpdatesToSkip = isInitialLogin and 1 or 0
if not eventFrame then eventFrame = CreateFrame("Frame") end
eventFrame:UnregisterAllEvents()
eventFrame:SetScript("OnEvent", OnQuestLogUpdate)
eventFrame:RegisterEvent("QUEST_LOG_UPDATE")
end
-- MUST be started very early to count number of events firing.
function QuestieValidateGameCache.StartCheck()
assert(not checkStarted) -- to avoid bugging the module by wrong usage
if checkStarted then return end
checkStarted = true
eventFrame = CreateFrame("Frame")
eventFrame:SetScript("OnEvent", OnPlayerEnteringWorld)
if not eventFrame then eventFrame = CreateFrame("Frame") end
eventFrame:RegisterEvent("PLAYER_ENTERING_WORLD")
eventFrame:SetScript("OnEvent", OnPlayerEnteringWorld)
if IsLoggedIn() then
OnPlayerEnteringWorld(eventFrame, "PLAYER_ENTERING_WORLD", true, false)
end
local function backupCheck()
if isCacheGood then return end
OnQuestLogUpdate()
if not isCacheGood then
local qCompat = QuestieCompat or _G.QuestieCompat
local timer = (qCompat and qCompat.C_QuestLog and qCompat.C_Timer) or _G.C_Timer
if timer and timer.After then
timer.After(2.0, backupCheck)
end
end
end
local qCompat = QuestieCompat or _G.QuestieCompat
local timer = (qCompat and qCompat.C_QuestLog and qCompat.C_Timer) or _G.C_Timer
if timer and timer.After then
timer.After(2.0, backupCheck)
end
end
function QuestieValidateGameCache.IsCacheGood()
return isCacheGood
end
function QuestieValidateGameCache.RegisterCallback(func, ...)
if isCacheGood then
func(...)
else
table.insert(callbacks, { func, tpack(...) })
end
end
+19 -34
View File
@@ -12,45 +12,30 @@ local WOW_PROJECT_ID = QuestieCompat.WOW_PROJECT_ID
local C_Seasons = QuestieCompat.C_Seasons
-- Check addon is not renamed to avoid conflicts in global name space.
if (not QuestieCompat.Is335) and addonName ~= "Questie" then
local msg = { "You have renamed Questie addon.", "This is restricted to avoid issues.", "Please remove '"..addonName.."'", "and reinstall the original version."}
StaticPopupDialogs["QUESTIE_ADDON_NAME_ERROR"] = {
text = "|cffff0000ERROR|r\n"..msg[1].."\n"..msg[2].."\n\n"..msg[3].."\n"..msg[4],
button2 = "OK",
hasEditBox = false,
whileDead = true,
timeout = 0 -- 335
}
-- (Removed because Questie-X is meant to be run universally and its folder name is Questie-X)
C_Timer.After(4, function()
DEFAULT_CHAT_FRAME:AddMessage("---------------------------------")
DEFAULT_CHAT_FRAME:AddMessage("|cffff0000ERROR|r: |cff42f5ad"..msg[1].."|r")
DEFAULT_CHAT_FRAME:AddMessage("|cffff0000ERROR|r: |cff42f5ad"..msg[2].."|r")
DEFAULT_CHAT_FRAME:AddMessage("|cffff0000ERROR|r: |cff42f5ad"..msg[3].."|r")
DEFAULT_CHAT_FRAME:AddMessage("|cffff0000ERROR|r: |cff42f5ad"..msg[4].."|r")
DEFAULT_CHAT_FRAME:AddMessage("---------------------------------")
error("ERROR: "..msg[1].." "..msg[2].." "..msg[3])
end)
StaticPopup_Show("QUESTIE_ADDON_NAME_ERROR")
return
end
if Questie then
C_Timer.After(4, function()
error("ERROR!! -> Questie already loaded! Please only have one Questie installed!")
for _=1, 10 do
DEFAULT_CHAT_FRAME:AddMessage("|cFFFF0000ERROR!!|r -> Questie already loaded! Please only have one Questie installed!")
end
end);
error("ERROR!! -> Questie already loaded! Please only have one Questie installed!")
DEFAULT_CHAT_FRAME:AddMessage("|cFFFF0000ERROR!!|r -> Questie already loaded! Please only have one Questie installed!")
Questie = {}
return
end
--Initialized below
---@class Questie : AceAddon, AceConsole-3.0, AceEvent-3.0, AceTimer-3.0, AceComm-3.0, AceBucket-3.0
Questie = LibStub("AceAddon-3.0"):NewAddon("Questie", "AceConsole-3.0", "AceEvent-3.0", "AceTimer-3.0", "AceComm-3.0", "AceBucket-3.0")
-- In Questie-X, the Questie object is created early by QuestieLoader.
-- We use that existing object here to ensure all modules share the same instance.
local function InitializeQuestie()
local existingQuestie = QuestieLoader:ImportModule("Questie")
local ok, err = pcall(function()
LibStub("AceAddon-3.0"):NewAddon(existingQuestie, addonName, "AceConsole-3.0", "AceEvent-3.0", "AceTimer-3.0", "AceComm-3.0", "AceBucket-3.0")
end)
if not ok then
Questie:Error("ERROR inside NewAddon: " .. tostring(err))
end
-- Ensure the global reference points to our unified object
_G.Questie = existingQuestie
return existingQuestie
end
Questie = InitializeQuestie()
-- preinit placeholder to stop tukui crashing from literally force-removing one of our features no matter what users select in the config ui
Questie.db = {profile={minimap={hide=false}}}
+2 -40
View File
@@ -5,43 +5,34 @@
## Notes-esES: Ayundante de misión
## Notes-ptBR: Ajudante de missão
## Notes-frFR: Assistant de quête
## Version: 1.4.5
## RequiredDeps:
## Version: 1.4.6
## OptionalDeps: Ace3, CallbackHandler-1.0, HereBeDragons, LibDataBroker-1.1, LibDBIcon-1.0, LibSharedMedia-3.0, LibStub, LibUIDropDownMenu
## SavedVariables: QuestieConfig
## SavedVariables: QuestieConfig, QuestieLearnerDB, QuestieCacheDB
## SavedVariablesPerCharacter: QuestieConfigCharacter
## X-Curse-Project-ID: 334372
## X-Wago-ID: qv634BKb
## X-WOW_PROJECT_ID: 2
# Loader module
Modules\Libs\QuestieLoader.lua
# COMPATIBILITY
Modules\QuestieCompat.lua
Modules\WorldMapTaintWorkaround.lua
Modules\GameVersionError.lua
Compat\embeds.xml
Libs\XXH_Lua_Lib\XXH_Lua_Lib.lua
Modules\VersionCheck.lua
# Thread Manager
Modules\Libs\ThreadLib.lua
#Message Handler
Modules\Libs\MessageHandler.lua
#Quest XP
Database\QuestXP\QuestieXP.lua
Database\QuestXP\DB\xpDB-classic.lua
# stream module (used by DB)
Modules\QuestieStream.lua
# Zones
Database\Zones\zoneTables.lua
Database\Zones\zoneDB.lua
# Databases
Database\Classic\classicItemDB.lua
Database\Classic\classicNpcDB.lua
@@ -54,7 +45,6 @@ Database\npcDB.lua
Database\itemDB.lua
Database\Constants.lua
Database\MeetingStones.lua
# Corrections
Database\Corrections\AutoTableUpdates.lua
Database\Corrections\QuestieCorrections.lua
@@ -65,49 +55,40 @@ Database\Corrections\QuestieQuestBlacklist.lua
#Database\Corrections\SeasonOfDiscovery.lua
#Database\Corrections\SoMPhases.lua
Database\Corrections\QuestieEvent.lua
# Automatic General Corrections
Database\Corrections\Automatic\itemStartFixes.lua
Database\Corrections\Automatic\classicQuestReputationFixes.lua
# SoD base entries - the data in there is generated
#Database\Corrections\Automatic\sodBaseItems.lua
#Database\Corrections\Automatic\sodBaseNPCs.lua
#Database\Corrections\Automatic\sodBaseObjects.lua
#Database\Corrections\Automatic\sodBaseQuests.lua
# Classic Corrections
Database\Corrections\classicQuestFixes.lua
Database\Corrections\classicNPCFixes.lua
Database\Corrections\classicItemFixes.lua
Database\Corrections\classicObjectFixes.lua
# SoD Corrections
#Database\Corrections\sodQuestFixes.lua
#Database\Corrections\sodNPCFixes.lua
#Database\Corrections\sodItemFixes.lua
#Database\Corrections\sodObjectFixes.lua
# Compiler
Database\compiler.lua
# Localization
Localization\l10n.lua
Localization\Translations\Translations.xml
Localization\lookups\lookupQuestCategories.lua
Localization\lookups\lookupZones.lua
Localization\lookups\Classic\lookupItems\lookupItems.xml
Localization\lookups\Classic\lookupNpcs\lookupNpcs.xml
Localization\lookups\Classic\lookupObjects\lookupObjects.xml
Localization\lookups\Classic\lookupQuests\lookupQuests.xml
# Libs
Modules\Libs\QuestieLib.lua
Modules\Libs\QuestieSerializer.lua
Modules\Libs\QuestieCombatQueue.lua
Modules\Libs\RamerDouglasPeucker.lua
# Modules
Modules\QuestieValidateGameCache.lua
Modules\Arrow\QuestieArrow.lua
@@ -131,33 +112,26 @@ Modules\QuestiePlayer.lua
#Modules\QuestieDebugOffer.lua
Modules\WorldMapButton\WorldMapButton.lua
#Modules\WorldMapButton\QuestieWorldMapButtonTemplate.xml
# QuestLinks
Modules\QuestLinks\ChatFilter.lua
Modules\QuestLinks\Hooks.lua
Modules\QuestLinks\Link.lua
# Tooltips
Modules\Tooltips\Tooltip.lua
Modules\Tooltips\MapIconTooltip.lua
Modules\Tooltips\TooltipHandler.lua
# Auto
Modules\Auto\QuestieAuto.lua
Modules\Auto\Privates.lua
Modules\Auto\DisallowedIDs.lua
# FramePool
Modules\FramePool\QuestieFramePool.lua
Modules\FramePool\QuestieFrame.lua
# Map
Modules\Map\QuestieMap.lua
Modules\Map\QuestieMapUtils.lua
Modules\Map\HBDHooks.lua
Modules\Map\WeaponMasterSkills.lua
# Quest
Modules\Quest\AvailableQuests.lua
Modules\Quest\QuestLogCache.lua
@@ -167,14 +141,11 @@ Modules\Quest\QuestEventHandler.lua
Modules\Quest\QuestgiverFrame.lua
Modules\Quest\QuestieQuest.lua
Modules\Quest\QuestieQuestPrivates.lua
Modules\QuestieNameplate.lua
Modules\QuestieCoordinates.lua
# Network
Modules\Network\QuestieComms.lua
Modules\Network\QuestieCommsData.lua
# Journey
Modules\Journey\QuestieJourney.lua
Modules\Journey\QuestieJourneyPrivates.lua
@@ -190,7 +161,6 @@ Modules\Journey\tabs\QuestsByZone\QuestsByZoneTab.lua
#Modules\Journey\tabs\Search\SearchTab.lua
Modules\Journey\QuestieSearch.lua
Modules\Journey\QuestieSearchResults.lua
# Tracker
Modules\Tracker\QuestieTracker.lua
Modules\Tracker\TrackerUtils.lua
@@ -201,15 +171,12 @@ Modules\Tracker\TrackerHeaderFrame.lua
Modules\Tracker\TrackerQuestFrame.lua
Modules\Tracker\TrackerQuestTimers.lua
Modules\Tracker\TrackerLinePool.lua
# Tutorial
#Modules\Tutorial\ShowRunes.lua
Modules\Tutorial\ChooseObjectiveType.lua
Modules\Tutorial\Tutorial.lua
#Modules\QuestieDBMIntegration.lua
Modules\QuestieSlash.lua
# Options
Modules\Options\QuestieOptions.lua
Modules\Options\QuestieOptionsDefaults.lua
@@ -223,14 +190,9 @@ Modules\Options\GeneralTab\QuestieOptionsGeneral.lua
Modules\Options\IconsTab\QuestieOptionsIcons.lua
Modules\Options\NameplateTab\QuestieOptionsNameplate.lua
Modules\Options\TrackerTab\QuestieOptionsTracker.lua
# Cleanup
Modules\QuestieCleanup.lua
# Profiler
Modules\QuestieProfiler.lua
# Main
Questie.lua
+2 -39
View File
@@ -5,43 +5,34 @@
## Notes-esES: Ayundante de misión
## Notes-ptBR: Ajudante de missão
## Notes-frFR: Assistant de quête
## Version: 1.4.5
## RequiredDeps:
## Version: 1.4.6
## OptionalDeps: Ace3, CallbackHandler-1.0, HereBeDragons, LibDataBroker-1.1, LibDBIcon-1.0, LibSharedMedia-3.0, LibStub, LibUIDropDownMenu
## SavedVariables: QuestieConfig
## SavedVariables: QuestieConfig, QuestieLearnerDB, QuestieCacheDB
## SavedVariablesPerCharacter: QuestieConfigCharacter
## X-Curse-Project-ID: 334372
## X-Wago-ID: qv634BKb
## X-WOW_PROJECT_ID: 5
# Loader module
Modules\Libs\QuestieLoader.lua
# COMPATIBILITY
Modules\QuestieCompat.lua
Modules\WorldMapTaintWorkaround.lua
Modules\GameVersionError.lua
Compat\embeds.xml
Libs\XXH_Lua_Lib\XXH_Lua_Lib.lua
Modules\VersionCheck.lua
# Thread Manager
Modules\Libs\ThreadLib.lua
#Message Handler
Modules\Libs\MessageHandler.lua
#Quest XP
Database\QuestXP\QuestieXP.lua
Database\QuestXP\DB\xpDB-tbc.lua
# stream module (used by DB)
Modules\QuestieStream.lua
# Zones
Database\Zones\zoneTables.lua
Database\Zones\zoneDB.lua
# Databases
Database\TBC\tbcItemDB.lua
Database\TBC\tbcNpcDB.lua
@@ -54,7 +45,6 @@ Database\npcDB.lua
Database\itemDB.lua
Database\Constants.lua
Database\MeetingStones.lua
# Corrections
Database\Corrections\AutoTableUpdates.lua
Database\Corrections\QuestieCorrections.lua
@@ -63,43 +53,35 @@ Database\Corrections\QuestieNPCBlacklist.lua
Database\Corrections\QuestieQuestBlacklist.lua
#Database\Corrections\SoMPhases.lua
Database\Corrections\QuestieEvent.lua
# Automatic General Corrections
Database\Corrections\Automatic\itemStartFixes.lua
Database\Corrections\Automatic\classicQuestReputationFixes.lua
# Classic Corrections
Database\Corrections\classicQuestFixes.lua
Database\Corrections\classicNPCFixes.lua
Database\Corrections\classicItemFixes.lua
Database\Corrections\classicObjectFixes.lua
# TBC Corrections
Database\Corrections\tbcQuestFixes.lua
Database\Corrections\tbcNPCFixes.lua
Database\Corrections\tbcItemFixes.lua
Database\Corrections\tbcObjectFixes.lua
# Compiler
Database\compiler.lua
# Localization
Localization\l10n.lua
Localization\Translations\Translations.xml
Localization\lookups\lookupQuestCategories.lua
Localization\lookups\lookupZones.lua
Localization\lookups\TBC\lookupItems\lookupItems.xml
Localization\lookups\TBC\lookupNpcs\lookupNpcs.xml
Localization\lookups\TBC\lookupObjects\lookupObjects.xml
Localization\lookups\TBC\lookupQuests\lookupQuests.xml
# Libs
Modules\Libs\QuestieLib.lua
Modules\Libs\QuestieSerializer.lua
Modules\Libs\QuestieCombatQueue.lua
Modules\Libs\RamerDouglasPeucker.lua
# Modules
Modules\QuestieValidateGameCache.lua
Modules\Arrow\QuestieArrow.lua
@@ -123,33 +105,26 @@ Modules\QuestiePlayer.lua
#Modules\QuestieDebugOffer.lua
Modules\WorldMapButton\WorldMapButton.lua
#Modules\WorldMapButton\QuestieWorldMapButtonTemplate.xml
# QuestLinks
Modules\QuestLinks\ChatFilter.lua
Modules\QuestLinks\Hooks.lua
Modules\QuestLinks\Link.lua
# Tooltips
Modules\Tooltips\Tooltip.lua
Modules\Tooltips\MapIconTooltip.lua
Modules\Tooltips\TooltipHandler.lua
# Auto
Modules\Auto\QuestieAuto.lua
Modules\Auto\Privates.lua
Modules\Auto\DisallowedIDs.lua
# FramePool
Modules\FramePool\QuestieFramePool.lua
Modules\FramePool\QuestieFrame.lua
# Map
Modules\Map\QuestieMap.lua
Modules\Map\QuestieMapUtils.lua
Modules\Map\HBDHooks.lua
Modules\Map\WeaponMasterSkills.lua
# Quest
Modules\Quest\AvailableQuests.lua
Modules\Quest\QuestLogCache.lua
@@ -159,14 +134,11 @@ Modules\Quest\QuestEventHandler.lua
Modules\Quest\QuestgiverFrame.lua
Modules\Quest\QuestieQuest.lua
Modules\Quest\QuestieQuestPrivates.lua
Modules\QuestieNameplate.lua
Modules\QuestieCoordinates.lua
# Network
Modules\Network\QuestieComms.lua
Modules\Network\QuestieCommsData.lua
# Journey
Modules\Journey\QuestieJourney.lua
Modules\Journey\QuestieJourneyPrivates.lua
@@ -182,7 +154,6 @@ Modules\Journey\tabs\QuestsByZone\QuestsByZoneTab.lua
#Modules\Journey\tabs\Search\SearchTab.lua
Modules\Journey\QuestieSearch.lua
Modules\Journey\QuestieSearchResults.lua
# Tracker
Modules\Tracker\QuestieTracker.lua
Modules\Tracker\TrackerUtils.lua
@@ -193,14 +164,11 @@ Modules\Tracker\TrackerHeaderFrame.lua
Modules\Tracker\TrackerQuestFrame.lua
Modules\Tracker\TrackerQuestTimers.lua
Modules\Tracker\TrackerLinePool.lua
# Tutorial
Modules\Tutorial\ChooseObjectiveType.lua
Modules\Tutorial\Tutorial.lua
#Modules\QuestieDBMIntegration.lua
Modules\QuestieSlash.lua
# Options
Modules\Options\QuestieOptions.lua
Modules\Options\QuestieOptionsDefaults.lua
@@ -214,14 +182,9 @@ Modules\Options\GeneralTab\QuestieOptionsGeneral.lua
Modules\Options\IconsTab\QuestieOptionsIcons.lua
Modules\Options\NameplateTab\QuestieOptionsNameplate.lua
Modules\Options\TrackerTab\QuestieOptionsTracker.lua
# Cleanup
Modules\QuestieCleanup.lua
# Profiler
Modules\QuestieProfiler.lua
# Main
Questie.lua
+2 -42
View File
@@ -5,18 +5,15 @@
## Notes-esES: Ayundante de misiones
## Notes-ptBR: Ajudante de misiones
## Notes-frFR: Assistant de quêtes
## Version: 1.4.5
## RequiredDeps:
## Version: 1.4.6
## OptionalDeps: Ace3, CallbackHandler-1.0, HereBeDragons, LibDataBroker-1.1, LibDBIcon-1.0, LibSharedMedia-3.0, LibStub, LibUIDropDownMenu, Questie-X-TurtleDB
## SavedVariables: QuestieConfig
## SavedVariables: QuestieConfig, QuestieLearnerDB, QuestieCacheDB
## SavedVariablesPerCharacter: QuestieConfigCharacter
## X-Curse-Project-ID: 334372
## X-Wago-ID: qv634BKb
## X-WOW_PROJECT_ID: 1
# Loader module
Modules\Libs\QuestieLoader.lua
# COMPATIBILITY
Modules\QuestieCompat.lua
Modules\WorldMapTaintWorkaround.lua
@@ -27,23 +24,17 @@ Libs\XXH_Lua_Lib\XXH_Lua_Lib.lua
Libs\LibDataBroker-1.1\LibDataBroker-1.1.lua
Libs\LibDBIcon-1.0\LibDBIcon-1.0.lua
Libs\Krowi_WorldMapButtons\Krowi_WorldMapButtons-1.4.lua
Modules\VersionCheck.lua
# Thread Manager
Modules\Libs\ThreadLib.lua
#Quest XP
Database\QuestXP\QuestieXP.lua
Database\QuestXP\DB\xpDB-classic.lua
# stream module (used by DB)
Modules\QuestieStream.lua
# Zones
Database\Zones\zoneTables.lua
Database\Zones\zoneDB.lua
# Databases
Database\Classic\classicItemDB.lua
Database\Classic\classicNpcDB.lua
@@ -56,7 +47,6 @@ Database\npcDB.lua
Database\itemDB.lua
Database\Constants.lua
Database\MeetingStones.lua
# Corrections
Database\Corrections\QuestieCorrections.lua
Database\Corrections\QuestieItemBlacklist.lua
@@ -66,52 +56,42 @@ Database\Corrections\QuestieQuestBlacklist.lua
#Database\Corrections\SeasonOfDiscovery.lua
#Database\Corrections\SoMPhases.lua
Database\Corrections\QuestieEvent.lua
# Auto Table Updates - must load after QuestieDB is fully set up
Database\Corrections\AutoTableUpdates.lua
# Automatic General Corrections
Database\Corrections\Automatic\itemStartFixes.lua
Database\Corrections\Automatic\classicQuestReputationFixes.lua
# SoD base entries - the data in there is generated
#Database\Corrections\Automatic\sodBaseItems.lua
#Database\Corrections\Automatic\sodBaseNPCs.lua
#Database\Corrections\Automatic\sodBaseObjects.lua
#Database\Corrections\Automatic\sodBaseQuests.lua
# Classic Corrections
Database\Corrections\classicQuestFixes.lua
Database\Corrections\classicNPCFixes.lua
Database\Corrections\classicItemFixes.lua
Database\Corrections\classicObjectFixes.lua
# SoD Corrections
#Database\Corrections\sodQuestFixes.lua
#Database\Corrections\sodNPCFixes.lua
#Database\Corrections\sodItemFixes.lua
#Database\Corrections\sodObjectFixes.lua
# Compiler
Database\compiler.lua
# Localization
Localization\l10n.lua
Localization\Translations\Translations.xml
Localization\lookups\lookupQuestCategories.lua
Localization\lookups\lookupZones.lua
Localization\lookups\Classic\lookupItems\lookupItems.xml
Localization\lookups\Classic\lookupNpcs\lookupNpcs.xml
Localization\lookups\Classic\lookupObjects\lookupObjects.xml
Localization\lookups\Classic\lookupQuests\lookupQuests.xml
# Libs
Modules\Libs\QuestieLib.lua
Modules\Libs\QuestieSerializer.lua
Modules\Libs\QuestieCombatQueue.lua
Modules\Libs\RamerDouglasPeucker.lua
# Core Modules (before QuestieMenu - these don't depend on Questie global)
Modules\QuestieValidateGameCache.lua
Modules\Arrow\QuestieArrow.lua
@@ -129,33 +109,26 @@ Modules\QuestiePlayer.lua
#Modules\QuestieDebugOffer.lua
Modules\WorldMapButton\WorldMapButton.lua
#Modules\WorldMapButton\QuestieWorldMapButtonTemplate.xml
# QuestLinks
Modules\QuestLinks\ChatFilter.lua
Modules\QuestLinks\Hooks.lua
Modules\QuestLinks\Link.lua
# Tooltips
Modules\Tooltips\Tooltip.lua
Modules\Tooltips\MapIconTooltip.lua
Modules\Tooltips\TooltipHandler.lua
# Auto
Modules\Auto\QuestieAuto.lua
Modules\Auto\Privates.lua
Modules\Auto\DisallowedIDs.lua
# FramePool
Modules\FramePool\QuestieFramePool.lua
Modules\FramePool\QuestieFrame.lua
# Map
Modules\Map\QuestieMap.lua
Modules\Map\QuestieMapUtils.lua
Modules\Map\HBDHooks.lua
Modules\Map\WeaponMasterSkills.lua
# Quest
Modules\Quest\AvailableQuests.lua
Modules\Quest\QuestLogCache.lua
@@ -165,14 +138,11 @@ Modules\Quest\QuestEventHandler.lua
Modules\Quest\QuestgiverFrame.lua
Modules\Quest\QuestieQuest.lua
Modules\Quest\QuestieQuestPrivates.lua
Modules\QuestieNameplate.lua
Modules\QuestieCoordinates.lua
# Network
Modules\Network\QuestieComms.lua
Modules\Network\QuestieCommsData.lua
# Journey
Modules\Journey\QuestieJourney.lua
Modules\Journey\QuestieJourneyPrivates.lua
@@ -188,7 +158,6 @@ Modules\Journey\tabs\QuestsByZone\QuestsByZoneTab.lua
#Modules\Journey\tabs\Search\SearchTab.lua
Modules\Journey\QuestieSearch.lua
Modules\Journey\QuestieSearchResults.lua
# Tracker
Modules\Tracker\QuestieTracker.lua
Modules\Tracker\TrackerUtils.lua
@@ -199,15 +168,12 @@ Modules\Tracker\TrackerHeaderFrame.lua
Modules\Tracker\TrackerQuestFrame.lua
Modules\Tracker\TrackerQuestTimers.lua
Modules\Tracker\TrackerLinePool.lua
# Tutorial
#Modules\Tutorial\ShowRunes.lua
Modules\Tutorial\ChooseObjectiveType.lua
Modules\Tutorial\Tutorial.lua
#Modules\QuestieDBMIntegration.lua
Modules\QuestieSlash.lua
# Options
Modules\Options\QuestieOptions.lua
Modules\Options\QuestieOptionsDefaults.lua
@@ -221,16 +187,12 @@ Modules\Options\GeneralTab\QuestieOptionsGeneral.lua
Modules\Options\IconsTab\QuestieOptionsIcons.lua
Modules\Options\NameplateTab\QuestieOptionsNameplate.lua
Modules\Options\TrackerTab\QuestieOptionsTracker.lua
# Cleanup
Modules\QuestieCleanup.lua
# Profiler
Modules\QuestieProfiler.lua
# Main
Questie.lua
# QuestieMenu - must load after Questie is initialized
Modules\QuestieMenu\Townsfolk.lua
Modules\QuestieMenu\ClassTrainers.lua
@@ -238,5 +200,3 @@ Modules\QuestieMenu\Mailboxes.lua
Modules\QuestieMenu\MeetingStones.lua
Modules\QuestieMenu\ProfessionTrainers.lua
Modules\QuestieMenu\QuestieMenu.lua
+2 -40
View File
@@ -11,21 +11,17 @@
## Notes-esES: Ayundante de misión
## Notes-ptBR: Ajudante de missão
## Notes-frFR: Assistant de quête
## Version: 1.4.5
## RequiredDeps:
## Version: 1.4.6
## 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
## SavedVariables: QuestieConfig, QuestieLearnerDB, QuestieCacheDB, QuestieJourneyDB
## SavedVariablesPerCharacter: QuestieConfigCharacter
## X-Curse-Project-ID: 334372
## X-Wago-ID: qv634BKb
## X-WOW_PROJECT_ID: 11
# Loader module
Modules\Libs\QuestieLoader.lua
# Plugin API
Modules\Libs\QuestiePluginAPI.lua
# COMPATIBILITY
Modules\QuestieCompat.lua
Modules\WorldMapTaintWorkaround.lua
@@ -33,27 +29,20 @@ Modules\GameVersionError.lua
Libs\LibStub\LibStub.lua
Compat\embeds.xml
Libs\XXH_Lua_Lib\XXH_Lua_Lib.lua
Modules\VersionCheck.lua
# SERVER ENVIRONMENT DETECTION
Modules\QuestieServer.lua
# Thread Manager
Modules\Libs\ThreadLib.lua
#Message Handler
Modules\Libs\MessageHandler.lua
#Quest XP
Database\QuestXP\QuestieXP.lua
# stream module (used by DB)
Modules\QuestieStream.lua
# Zones
Database\Zones\zoneTables.lua
Database\Zones\zoneDB.lua
# Core Database schema (data injected by DB plugins)
Database\QuestieDB.lua
Database\questDB.lua
@@ -62,7 +51,6 @@ Database\npcDB.lua
Database\itemDB.lua
Database\Constants.lua
Database\MeetingStones.lua
# Corrections framework (expansion-specific fixes loaded by DB plugins)
Database\Corrections\AutoTableUpdates.lua
Database\Corrections\QuestieCorrections.lua
@@ -70,45 +58,36 @@ Database\Corrections\QuestieItemBlacklist.lua
Database\Corrections\QuestieNPCBlacklist.lua
Database\Corrections\QuestieQuestBlacklist.lua
Database\Corrections\QuestieEvent.lua
# Classic corrections (always loaded; _LoadCorrections skips missing IDs gracefully)
Database\Corrections\classicQuestFixes.lua
Database\Corrections\classicNPCFixes.lua
Database\Corrections\classicItemFixes.lua
Database\Corrections\classicObjectFixes.lua
# TBC corrections (gated by Questie.IsTBC / Questie.IsWotLK inside QuestieCorrections)
Database\Corrections\tbcQuestFixes.lua
Database\Corrections\tbcNPCFixes.lua
Database\Corrections\tbcItemFixes.lua
Database\Corrections\tbcObjectFixes.lua
# WotLK corrections (gated by Questie.IsWotLK inside QuestieCorrections)
Database\Corrections\wotlkQuestFixes.lua
Database\Corrections\wotlkNPCFixes.lua
Database\Corrections\wotlkItemFixes.lua
Database\Corrections\wotlkObjectFixes.lua
# Automatic General Corrections
Database\Corrections\Automatic\itemStartFixes.lua
Database\Corrections\Automatic\classicQuestReputationFixes.lua
# Compiler
Database\compiler.lua
# Localization
Localization\l10n.lua
Localization\Translations\Translations.xml
Localization\lookups\lookupQuestCategories.lua
Localization\lookups\lookupZones.lua
# Libs
Modules\Libs\QuestieLib.lua
Modules\Libs\QuestieSerializer.lua
Modules\Libs\QuestieCombatQueue.lua
Modules\Libs\RamerDouglasPeucker.lua
# Modules
Modules\QuestieValidateGameCache.lua
Modules\Arrow\QuestieArrow.lua
@@ -133,32 +112,26 @@ Modules\QuestiePlayer.lua
#Modules\QuestieDebugOffer.lua
Modules\WorldMapButton\WorldMapButton.lua
#Modules\WorldMapButton\QuestieWorldMapButtonTemplate.xml
# QuestLinks
Modules\QuestLinks\ChatFilter.lua
Modules\QuestLinks\Hooks.lua
Modules\QuestLinks\Link.lua
# Tooltips
Modules\Tooltips\Tooltip.lua
Modules\Tooltips\MapIconTooltip.lua
Modules\Tooltips\TooltipHandler.lua
# Auto
Modules\Auto\QuestieAuto.lua
Modules\Auto\Privates.lua
Modules\Auto\DisallowedIDs.lua
# FramePool
Modules\FramePool\QuestieFramePool.lua
Modules\FramePool\QuestieFrame.lua
# Map
Modules\Map\QuestieMap.lua
Modules\Map\QuestieMapUtils.lua
Modules\Map\HBDHooks.lua
Modules\Map\WeaponMasterSkills.lua
# Quest
Modules\Quest\AvailableQuests.lua
Modules\Quest\QuestLogCache.lua
@@ -168,16 +141,13 @@ Modules\Quest\QuestEventHandler.lua
Modules\Quest\QuestgiverFrame.lua
Modules\Quest\QuestieQuest.lua
Modules\Quest\QuestieQuestPrivates.lua
Modules\QuestieNameplate.lua
Modules\QuestieCoordinates.lua
# Network
Modules\Network\QuestieComms.lua
Modules\Network\QuestieCommsData.lua
Modules\Network\QuestieLearnerComms.lua
Modules\QuestieLearnerExport.lua
# Journey
Modules\Journey\QuestieJourney.lua
Modules\Journey\QuestieJourneyPrivates.lua
@@ -193,7 +163,6 @@ Modules\Journey\tabs\QuestsByZone\QuestsByZoneTab.lua
#Modules\Journey\tabs\Search\SearchTab.lua
Modules\Journey\QuestieSearch.lua
Modules\Journey\QuestieSearchResults.lua
# Tracker
Modules\Tracker\QuestieTracker.lua
Modules\Tracker\TrackerUtils.lua
@@ -204,14 +173,11 @@ Modules\Tracker\TrackerHeaderFrame.lua
Modules\Tracker\TrackerQuestFrame.lua
Modules\Tracker\TrackerQuestTimers.lua
Modules\Tracker\TrackerLinePool.lua
# Tutorial
Modules\Tutorial\ChooseObjectiveType.lua
Modules\Tutorial\Tutorial.lua
#Modules\QuestieDBMIntegration.lua
Modules\QuestieSlash.lua
# Options
Modules\Options\QuestieOptions.lua
Modules\Options\QuestieOptionsDefaults.lua
@@ -225,13 +191,9 @@ Modules\Options\GeneralTab\QuestieOptionsGeneral.lua
Modules\Options\IconsTab\QuestieOptionsIcons.lua
Modules\Options\NameplateTab\QuestieOptionsNameplate.lua
Modules\Options\TrackerTab\QuestieOptionsTracker.lua
# Cleanup
Modules\QuestieCleanup.lua
# Profiler
Modules\QuestieProfiler.lua
# Main
Questie.lua
+46
View File
@@ -15,17 +15,32 @@ local TrackerBaseFrame = QuestieLoader:ImportModule("TrackerBaseFrame")
local QuestieValidateGameCache = QuestieLoader:ImportModule("QuestieValidateGameCache")
---@type QuestieLib
local QuestieLib = QuestieLoader:ImportModule("QuestieLib");
---@class Questie
function Questie:OnInitialize()
if Questie.initialized then return end
Questie.initialized = true
-- This has to happen OnInitialize to be available asap
Questie.db = LibStub("AceDB-3.0"):New("QuestieConfig", QuestieOptionsDefaults:Load(), true)
Questie.dbLearner = LibStub("AceDB-3.0"):New("QuestieLearnerDB", {}, true)
Questie.dbCache = LibStub("AceDB-3.0"):New("QuestieCacheDB", {}, true)
Questie.dbJourney = LibStub("AceDB-3.0"):New("QuestieJourneyDB", { char = { journey = {} } }, true)
-- These events basically all mean the same: The active profile changed.
Questie.db.RegisterCallback(Questie, "OnProfileChanged", "RefreshConfig")
Questie.db.RegisterCallback(Questie, "OnProfileCopied", "RefreshConfig")
Questie.db.RegisterCallback(Questie, "OnProfileReset", "RefreshConfig")
QuestieEventHandler:RegisterEarlyEvents()
local ok, res = pcall(function()
local QuestieInit = QuestieLoader:ImportModule("QuestieInit")
if QuestieInit and QuestieInit.OnInitialize then
QuestieInit:OnInitialize()
end
end)
end
function Questie:OnEnable()
@@ -167,7 +182,9 @@ function Questie:Debug(msgDebugLevel, ...)
end
end
-- Global debug levels
Questie.icons = {
["slay"] = QuestieLib.AddonPath .. "Icons\\slay.blp",
["loot"] = QuestieLib.AddonPath .. "Icons\\loot.blp",
["event"] = QuestieLib.AddonPath .. "Icons\\event.blp",
@@ -206,6 +223,7 @@ Questie.icons = {
["tracker_settings"] = QuestieLib.AddonPath .. "Icons\\tracker_settings.tga",
}
Questie.usedIcons = {}
Questie.ICON_TYPE_SLAY = 1
@@ -266,3 +284,31 @@ Questie.LOWLEVEL_RANGE = 4
-- Start checking the game's cache.
QuestieValidateGameCache.StartCheck()
-- AceAddon-3.0 will automatically call Questie:OnInitialize() during the ADDON_LOADED event
-- for the addonName registered in VersionCheck.lua.
-- This ensures SavedVariables (QuestieConfig) are fully injected before we use them.
-- Robust check for login state to ensure PlayerLogin is always triggered
-- If the engine somehow missed the AceAddon lifecycle, this will catch it safely.
local function checkLogin()
if IsLoggedIn() then
if not Questie.initialized then
Questie:OnInitialize()
end
if Questie.OnEnable and not Questie.enabled then
Questie:OnEnable()
Questie.enabled = true
end
else
-- Re-check in 0.2s if not yet logged in
local timer = C_Timer or QuestieCompat.C_Timer
if timer and timer.After then
timer.After(0.2, checkLogin)
end
end
end
checkLogin()
-1
View File
@@ -4,5 +4,4 @@
## Interface: 00000
## Title: Questie|cFFFF0000 game client not supported|r
## Notes: Questie only supports Classic TBC and Classic Era/SoM.
Modules\GameVersionError.lua
+11
View File
@@ -348,6 +348,17 @@
</div>
<div class="container">
<h2 id="v146">v1.4.6 &mdash; Saved Variables &amp; Texture Fixes</h2>
<ul>
<li><strong>[Fix]</strong> Resolved issue where Questie would not save options or show the Welcome screen repeatedly.</li>
<li><strong>[Fix]</strong> Synchronized AceAddon registration name to "Questie-X" to match folder structure.</li>
<li><strong>[Fix]</strong> Patched AceGUI-3.0 widgets to use string texture paths instead of FileDataIDs for WotLK 3.3.5a.</li>
<li><strong>[Cleanup]</strong> Removed all QX debug print statements.</li>
<li><strong>[Version]</strong> Bumped version to 1.4.6 across the codebase.</li>
</ul>
<hr>
<h2 id="v145">v1.4.5 &mdash; Network &amp; Taint Stability Update</h2>
<ul>
<li><strong>[Network Fix]</strong> Resolved a critical crash ("<code>Usage: AceSerializer:Deserialize(str): str must be a string, got table</code>") occurring in QuestieLearnerComms and Export functions. This was caused by a lightweight, customized <code>AceSerializer-3.0.lua</code> implementation in Questie-X that lacked proper <code>self</code> parameter handling for standard colon-syntax method calls (<code>:</code>). As a result, method calls were serializing/deserializing the library table itself instead of the intended payload string. We patched <code>AceSerializer</code> natively to dynamically support both dot (<code>.</code>) and colon (<code>:</code>) syntax seamlessly without dropping arguments, while ensuring <code>Deserialize</code> correctly yields <code>(success, result)</code> tuples expected by the calling functions.</li>
+6 -2
View File
@@ -1,3 +1,7 @@
## v1.4.4r6 — Questie-X Network Deserialization Fix
## v1.4.5 — Network & Taint Stability Update
- **[Network Fix]** Resolved a critical crash (Usage: AceSerializer:Deserialize(str): str must be a string, got table) occurring in QuestieLearnerComms and Export functions. This was caused by a lightweight, customized AceSerializer-3.0.lua implementation in Questie-X that lacked proper self parameter handling for standard colon-syntax method calls (:). As a result, method calls were serializing/deserializing the library table itself instead of the intended payload string. We patched AceSerializer natively to dynamically support both dot (.) and colon (:) syntax seamlessly without dropping arguments, while ensuring Deserialize correctly yields (success, result) tuples expected by the calling functions.
- **[Network Fix]** Patched AceSerializer natively to dynamically support both dot and colon syntax seamlessly without dropping arguments, while ensuring Deserialize correctly yields (success, result) tuples.
- **[Network Fix]** Purged 71 unsafe table.getn replacements in LibDeflate.
- **[Init Fix]** Bulletproof tocversion range check for legacy client engines.
- **[QuestieLearner Fix]** Module import scoping error resolved.
- **[Taint Fix]** Resolved ADDON_ACTION_BLOCKED errors caused by cached loading and QuestieInit._pullGlobal.