feat: add learner/static data source mode
This commit is contained in:
@@ -819,7 +819,9 @@ end
|
|||||||
function QuestieDB.GetSuppressedNPCs(zoneId)
|
function QuestieDB.GetSuppressedNPCs(zoneId)
|
||||||
local suppressed = {}
|
local suppressed = {}
|
||||||
local ld = Questie.dbLearner.global
|
local ld = Questie.dbLearner.global
|
||||||
if ld and ld.settings and ld.settings.enabled and ld.settings.prioritizeMyData and ld.npcs then
|
local mode = ld and ld.settings and ld.settings.dataSourceMode or "auto"
|
||||||
|
if mode == "auto" or mode == "learner" then
|
||||||
|
if ld and ld.settings and ld.settings.enabled and ld.npcs then
|
||||||
local threshold = ld.settings.minConfidencePins or 2
|
local threshold = ld.settings.minConfidencePins or 2
|
||||||
local npcId, entry = next(ld.npcs)
|
local npcId, entry = next(ld.npcs)
|
||||||
while npcId do
|
while npcId do
|
||||||
@@ -830,6 +832,7 @@ function QuestieDB.GetSuppressedNPCs(zoneId)
|
|||||||
npcId, entry = next(ld.npcs, npcId)
|
npcId, entry = next(ld.npcs, npcId)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
return suppressed
|
return suppressed
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -840,7 +843,9 @@ end
|
|||||||
function QuestieDB.GetSuppressedObjects(zoneId)
|
function QuestieDB.GetSuppressedObjects(zoneId)
|
||||||
local suppressed = {}
|
local suppressed = {}
|
||||||
local ld = Questie.dbLearner.global
|
local ld = Questie.dbLearner.global
|
||||||
if ld and ld.settings and ld.settings.enabled and ld.settings.prioritizeMyData and ld.objects then
|
local mode = ld and ld.settings and ld.settings.dataSourceMode or "auto"
|
||||||
|
if mode == "auto" or mode == "learner" then
|
||||||
|
if ld and ld.settings and ld.settings.enabled and ld.objects then
|
||||||
local threshold = ld.settings.minConfidencePins or 2
|
local threshold = ld.settings.minConfidencePins or 2
|
||||||
local objId, entry = next(ld.objects)
|
local objId, entry = next(ld.objects)
|
||||||
while objId do
|
while objId do
|
||||||
@@ -851,6 +856,7 @@ function QuestieDB.GetSuppressedObjects(zoneId)
|
|||||||
objId, entry = next(ld.objects, objId)
|
objId, entry = next(ld.objects, objId)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
return suppressed
|
return suppressed
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -46,6 +46,23 @@ local function GetLearnedCounts()
|
|||||||
return s
|
return s
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function ApplyLearnerMode()
|
||||||
|
local QuestieLearner = QuestieLoader:ImportModule("QuestieLearner")
|
||||||
|
if QuestieLearner and QuestieLearner.ApplyDataSourceMode then
|
||||||
|
QuestieLearner:ApplyDataSourceMode()
|
||||||
|
end
|
||||||
|
|
||||||
|
local QuestieEventHandler = QuestieLoader:ImportModule("QuestieEventHandler")
|
||||||
|
if QuestieEventHandler and QuestieEventHandler.UpdateAllQuests then
|
||||||
|
QuestieEventHandler:UpdateAllQuests()
|
||||||
|
end
|
||||||
|
|
||||||
|
local QuestieTracker = QuestieLoader:ImportModule("QuestieTracker")
|
||||||
|
if QuestieTracker and QuestieTracker.Update then
|
||||||
|
QuestieTracker:Update()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-----------------------------------------------------------------------
|
-----------------------------------------------------------------------
|
||||||
-- Export Dialog
|
-- Export Dialog
|
||||||
-----------------------------------------------------------------------
|
-----------------------------------------------------------------------
|
||||||
@@ -204,6 +221,43 @@ function QuestieOptions.tabs.database:Initialize()
|
|||||||
name = function() return l10n("What To Learn") end,
|
name = function() return l10n("What To Learn") end,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
learner_enabled = {
|
||||||
|
type = "toggle",
|
||||||
|
order = 2.05,
|
||||||
|
name = function() return l10n("Enable Learner Recording") end,
|
||||||
|
desc = function() return l10n("Record live learner data. Disable this to stop recording and live learner injection.") end,
|
||||||
|
get = function() return Questie.dbLearner.global and Questie.dbLearner.global.settings and Questie.dbLearner.global.settings.enabled end,
|
||||||
|
set = function(_, v)
|
||||||
|
if Questie.dbLearner.global and Questie.dbLearner.global.settings then
|
||||||
|
Questie.dbLearner.global.settings.enabled = v
|
||||||
|
ApplyLearnerMode()
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
|
||||||
|
data_source_mode = {
|
||||||
|
type = "select",
|
||||||
|
order = 2.06,
|
||||||
|
name = function() return l10n("Data Source Mode") end,
|
||||||
|
desc = function() return l10n("Choose whether Questie should display learner data, static database data, both, or neither. Learner recording can stay enabled independently.") end,
|
||||||
|
values = {
|
||||||
|
auto = l10n("Auto (current behavior)"),
|
||||||
|
learner = l10n("Learner Only"),
|
||||||
|
static = l10n("Static Only"),
|
||||||
|
none = l10n("Neither (base DB only)"),
|
||||||
|
},
|
||||||
|
get = function()
|
||||||
|
return (Questie.dbLearner.global and Questie.dbLearner.global.settings and Questie.dbLearner.global.settings.dataSourceMode) or "auto"
|
||||||
|
end,
|
||||||
|
set = function(_, v)
|
||||||
|
if Questie.dbLearner.global and Questie.dbLearner.global.settings then
|
||||||
|
Questie.dbLearner.global.settings.dataSourceMode = v
|
||||||
|
Questie.dbLearner.global.settings.prioritizeMyData = (v ~= "static" and v ~= "none")
|
||||||
|
ApplyLearnerMode()
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
|
||||||
learn_npcs = {
|
learn_npcs = {
|
||||||
type = "toggle",
|
type = "toggle",
|
||||||
order = 2.1,
|
order = 2.1,
|
||||||
|
|||||||
@@ -87,6 +87,9 @@ function QuestieOptionsDefaults:Load()
|
|||||||
learnerBroadcast = true,
|
learnerBroadcast = true,
|
||||||
enableMapIcons = true,
|
enableMapIcons = true,
|
||||||
enableMiniMapIcons = true,
|
enableMiniMapIcons = true,
|
||||||
|
-- Learner source preference (Database tab)
|
||||||
|
-- auto = current behavior, learner = learner only, static = static only, none = base DB only
|
||||||
|
dataSourceMode = "auto",
|
||||||
questieShutUp = false,
|
questieShutUp = false,
|
||||||
bugWorkarounds = true,
|
bugWorkarounds = true,
|
||||||
hideIconsOnContinents = false,
|
hideIconsOnContinents = false,
|
||||||
|
|||||||
@@ -1581,8 +1581,13 @@ function QuestieQuest:PopulateObjective(quest, objectiveIndex, objective, blockI
|
|||||||
objectiveCenter = { x = x, y = y }
|
objectiveCenter = { x = x, y = y }
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Filter static spawns if prioritizeMyData is enabled and we have high-confidence learned data
|
-- Filter static spawns only when the learner is allowed to influence display.
|
||||||
if Questie.dbLearner and Questie.dbLearner.global and Questie.dbLearner.global.settings and Questie.dbLearner.global.settings.enabled and Questie.dbLearner.global.settings.prioritizeMyData then
|
local dataSourceMode = Questie.dbLearner
|
||||||
|
and Questie.dbLearner.global
|
||||||
|
and Questie.dbLearner.global.settings
|
||||||
|
and Questie.dbLearner.global.settings.dataSourceMode or "auto"
|
||||||
|
if Questie.dbLearner and Questie.dbLearner.global and Questie.dbLearner.global.settings and Questie.dbLearner.global.settings.enabled
|
||||||
|
and (dataSourceMode == "auto" or dataSourceMode == "learner") then
|
||||||
local zone, _ = next(zones)
|
local zone, _ = next(zones)
|
||||||
while zone do
|
while zone do
|
||||||
local suppressed = (objectiveData.Type == "monster" and QuestieDB.GetSuppressedNPCs(zone)) or (objectiveData.Type == "object" and QuestieDB.GetSuppressedObjects(zone))
|
local suppressed = (objectiveData.Type == "monster" and QuestieDB.GetSuppressedNPCs(zone)) or (objectiveData.Type == "object" and QuestieDB.GetSuppressedObjects(zone))
|
||||||
|
|||||||
@@ -172,14 +172,23 @@ monster = function(npcId, objective)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local isLearned = false
|
local isLearned = false
|
||||||
|
local dataSourceMode = Questie.dbLearner
|
||||||
|
and Questie.dbLearner.global
|
||||||
|
and Questie.dbLearner.global.settings
|
||||||
|
and Questie.dbLearner.global.settings.dataSourceMode or "auto"
|
||||||
|
|
||||||
|
if dataSourceMode == "none" or dataSourceMode == "learner" then
|
||||||
|
spawns = {}
|
||||||
|
end
|
||||||
|
|
||||||
-- Learner safety net: when prioritizeMyData is enabled and the Learner has
|
-- Learner safety net: when prioritizeMyData is enabled and the Learner has
|
||||||
-- verified spawn data for this NPC, prefer it over compiled DB spawns.
|
-- verified spawn data for this NPC, prefer it over compiled DB spawns.
|
||||||
-- This catches edge cases where the npcDataOverrides chain doesn't fully
|
-- This catches edge cases where the npcDataOverrides chain doesn't fully
|
||||||
-- replace retail positions (e.g. format migration gaps, timing issues).
|
-- replace retail positions (e.g. format migration gaps, timing issues).
|
||||||
if Questie.IsAscension and Questie.dbLearner and Questie.dbLearner.global then
|
if Questie.IsAscension and Questie.dbLearner and Questie.dbLearner.global
|
||||||
|
and (dataSourceMode == "auto" or dataSourceMode == "learner") then
|
||||||
local ld = Questie.dbLearner.global
|
local ld = Questie.dbLearner.global
|
||||||
if ld.settings and ld.settings.enabled and ld.settings.prioritizeMyData then
|
if ld.settings and ld.settings.enabled then
|
||||||
local learnedNpc = ld.npcs and ld.npcs[npcId]
|
local learnedNpc = ld.npcs and ld.npcs[npcId]
|
||||||
if learnedNpc then
|
if learnedNpc then
|
||||||
local learnedSpawns = learnedNpc[7]
|
local learnedSpawns = learnedNpc[7]
|
||||||
@@ -253,6 +262,30 @@ object = function(objectId, objective)
|
|||||||
spawns = {}
|
spawns = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local dataSourceMode = Questie.dbLearner
|
||||||
|
and Questie.dbLearner.global
|
||||||
|
and Questie.dbLearner.global.settings
|
||||||
|
and Questie.dbLearner.global.settings.dataSourceMode or "auto"
|
||||||
|
local isLearned = false
|
||||||
|
if dataSourceMode == "none" or dataSourceMode == "learner" then
|
||||||
|
spawns = {}
|
||||||
|
end
|
||||||
|
|
||||||
|
if Questie.IsAscension and Questie.dbLearner and Questie.dbLearner.global
|
||||||
|
and (dataSourceMode == "auto" or dataSourceMode == "learner") then
|
||||||
|
local ld = Questie.dbLearner.global
|
||||||
|
if ld.settings and ld.settings.enabled then
|
||||||
|
local learnedObj = ld.objects and ld.objects[objectId]
|
||||||
|
if learnedObj and learnedObj[4] and next(learnedObj[4]) then
|
||||||
|
local threshold = ld.settings.minConfidencePins or 1
|
||||||
|
if learnedObj.mc and learnedObj.mc >= threshold then
|
||||||
|
spawns = learnedObj[4]
|
||||||
|
isLearned = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
---@type SpawnListObject
|
---@type SpawnListObject
|
||||||
local retObject = {
|
local retObject = {
|
||||||
@@ -263,6 +296,7 @@ object = function(objectId, objective)
|
|||||||
GetIconScale = _GetIconScaleForObject,
|
GetIconScale = _GetIconScaleForObject,
|
||||||
IconScale = _GetIconScaleForObject(),
|
IconScale = _GetIconScaleForObject(),
|
||||||
TooltipKey = "o_" .. objectId,
|
TooltipKey = "o_" .. objectId,
|
||||||
|
isLearned = isLearned,
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
+177
-22
@@ -16,6 +16,9 @@ local ZoneDB = QuestieLoader:ImportModule("ZoneDB")
|
|||||||
|
|
||||||
local _Learner = QuestieLearner.private or {}
|
local _Learner = QuestieLearner.private or {}
|
||||||
|
|
||||||
|
local GetDataSourceMode
|
||||||
|
local DeepCopy
|
||||||
|
|
||||||
local floor = math.floor
|
local floor = math.floor
|
||||||
local abs = math.abs
|
local abs = math.abs
|
||||||
local time = time
|
local time = time
|
||||||
@@ -32,6 +35,10 @@ local string_len = string.len
|
|||||||
local string_upper = string.upper
|
local string_upper = string.upper
|
||||||
|
|
||||||
local function IsAscensionProtected(dbType, id, key)
|
local function IsAscensionProtected(dbType, id, key)
|
||||||
|
local mode = GetDataSourceMode and GetDataSourceMode() or "auto"
|
||||||
|
if mode == "learner" or mode == "none" then
|
||||||
|
return false
|
||||||
|
end
|
||||||
local protected = QuestieDB
|
local protected = QuestieDB
|
||||||
and QuestieDB.ascensionOverrideKeys
|
and QuestieDB.ascensionOverrideKeys
|
||||||
and QuestieDB.ascensionOverrideKeys[dbType]
|
and QuestieDB.ascensionOverrideKeys[dbType]
|
||||||
@@ -44,6 +51,42 @@ local function HasAscensionQuestObjectiveData(questId)
|
|||||||
return IsAscensionProtected("QUEST", questId, 10)
|
return IsAscensionProtected("QUEST", questId, 10)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function GetDataSourceMode()
|
||||||
|
local settings = Questie
|
||||||
|
and Questie.dbLearner
|
||||||
|
and Questie.dbLearner.global
|
||||||
|
and Questie.dbLearner.global.settings
|
||||||
|
if not settings then
|
||||||
|
return "auto"
|
||||||
|
end
|
||||||
|
|
||||||
|
local mode = settings.dataSourceMode
|
||||||
|
if mode == "auto" or mode == "learner" or mode == "static" or mode == "none" then
|
||||||
|
return mode
|
||||||
|
end
|
||||||
|
|
||||||
|
if settings.prioritizeMyData == false then
|
||||||
|
return "static"
|
||||||
|
end
|
||||||
|
|
||||||
|
return "auto"
|
||||||
|
end
|
||||||
|
|
||||||
|
local function WipeTable(tbl)
|
||||||
|
if type(tbl) ~= "table" then return end
|
||||||
|
for key in pairs(tbl) do
|
||||||
|
tbl[key] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function CopyTable(dst, src)
|
||||||
|
WipeTable(dst)
|
||||||
|
if type(src) ~= "table" then return end
|
||||||
|
for key, value in pairs(src) do
|
||||||
|
dst[key] = DeepCopy(value)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
local function NormalizeSpawnZoneKey(zoneKey)
|
local function NormalizeSpawnZoneKey(zoneKey)
|
||||||
-- Convert raw area IDs (e.g. 3431 from GetAreaID()) to the canonical map IDs
|
-- Convert raw area IDs (e.g. 3431 from GetAreaID()) to the canonical map IDs
|
||||||
-- used by AscensionDB and the rendering system (e.g. 1241 for Sunstrider Isle).
|
-- used by AscensionDB and the rendering system (e.g. 1241 for Sunstrider Isle).
|
||||||
@@ -226,6 +269,39 @@ local function DeepCopy(value)
|
|||||||
return copy
|
return copy
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function CaptureStaticOverrideSnapshot()
|
||||||
|
if _Learner.staticOverrideSnapshot then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
_Learner.staticOverrideSnapshot = {
|
||||||
|
npcs = DeepCopy(QuestieDB.npcDataOverrides or {}),
|
||||||
|
quests = DeepCopy(QuestieDB.questDataOverrides or {}),
|
||||||
|
items = DeepCopy(QuestieDB.itemDataOverrides or {}),
|
||||||
|
objects = DeepCopy(QuestieDB.objectDataOverrides or {}),
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
local function RestoreStaticOverridesForMode()
|
||||||
|
local snapshot = _Learner.staticOverrideSnapshot
|
||||||
|
local mode = GetDataSourceMode()
|
||||||
|
|
||||||
|
if mode == "learner" or mode == "none" then
|
||||||
|
WipeTable(QuestieDB.npcDataOverrides)
|
||||||
|
WipeTable(QuestieDB.questDataOverrides)
|
||||||
|
WipeTable(QuestieDB.itemDataOverrides)
|
||||||
|
WipeTable(QuestieDB.objectDataOverrides)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if not snapshot then return end
|
||||||
|
|
||||||
|
CopyTable(QuestieDB.npcDataOverrides, snapshot.npcs)
|
||||||
|
CopyTable(QuestieDB.questDataOverrides, snapshot.quests)
|
||||||
|
CopyTable(QuestieDB.itemDataOverrides, snapshot.items)
|
||||||
|
CopyTable(QuestieDB.objectDataOverrides, snapshot.objects)
|
||||||
|
end
|
||||||
|
|
||||||
-- Returns the grid-bucket key for a coordinate so nearby points share the same slot
|
-- Returns the grid-bucket key for a coordinate so nearby points share the same slot
|
||||||
local function CoordBucket(x, y)
|
local function CoordBucket(x, y)
|
||||||
return floor(x / COORD_GRID) * COORD_GRID, floor(y / COORD_GRID) * COORD_GRID
|
return floor(x / COORD_GRID) * COORD_GRID, floor(y / COORD_GRID) * COORD_GRID
|
||||||
@@ -323,6 +399,7 @@ local function EnsureLearnedData()
|
|||||||
learnObjects = true,
|
learnObjects = true,
|
||||||
minConfidencePins = 1,
|
minConfidencePins = 1,
|
||||||
prioritizeMyData = true,
|
prioritizeMyData = true,
|
||||||
|
dataSourceMode = "auto",
|
||||||
staleThreshold = 90, -- days
|
staleThreshold = 90, -- days
|
||||||
pruneVerified = false, -- protect verified data by default
|
pruneVerified = false, -- protect verified data by default
|
||||||
performanceMode = "balanced",
|
performanceMode = "balanced",
|
||||||
@@ -347,6 +424,18 @@ local function EnsureLearnedData()
|
|||||||
if s.learnObjects == nil then s.learnObjects = true end
|
if s.learnObjects == nil then s.learnObjects = true end
|
||||||
if s.minConfidencePins == nil then s.minConfidencePins = 1 end
|
if s.minConfidencePins == nil then s.minConfidencePins = 1 end
|
||||||
if s.prioritizeMyData == nil then s.prioritizeMyData = true end
|
if s.prioritizeMyData == nil then s.prioritizeMyData = true end
|
||||||
|
if s.dataSourceMode == nil then
|
||||||
|
if s.prioritizeMyData == false then
|
||||||
|
s.dataSourceMode = "static"
|
||||||
|
else
|
||||||
|
s.dataSourceMode = "auto"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if s.dataSourceMode == "static" or s.dataSourceMode == "none" then
|
||||||
|
s.prioritizeMyData = false
|
||||||
|
else
|
||||||
|
s.prioritizeMyData = true
|
||||||
|
end
|
||||||
if s.staleThreshold == nil then
|
if s.staleThreshold == nil then
|
||||||
s.staleThreshold = 90
|
s.staleThreshold = 90
|
||||||
end
|
end
|
||||||
@@ -389,6 +478,30 @@ function QuestieLearner:GetSettings()
|
|||||||
return Questie.dbLearner.global.settings
|
return Questie.dbLearner.global.settings
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function QuestieLearner:GetDataSourceMode()
|
||||||
|
if not EnsureLearnedData() then return "auto" end
|
||||||
|
return GetDataSourceMode()
|
||||||
|
end
|
||||||
|
|
||||||
|
function QuestieLearner:IsLearnerLiveEnabled()
|
||||||
|
local mode = self:GetDataSourceMode()
|
||||||
|
return mode == "auto" or mode == "learner"
|
||||||
|
end
|
||||||
|
|
||||||
|
function QuestieLearner:ApplyDataSourceMode()
|
||||||
|
if not EnsureLearnedData() then return end
|
||||||
|
CaptureStaticOverrideSnapshot()
|
||||||
|
RestoreStaticOverridesForMode()
|
||||||
|
self:InjectLearnedData()
|
||||||
|
if QuestieDB and QuestieDB.private then
|
||||||
|
QuestieDB.private.questCache = {}
|
||||||
|
QuestieDB.private.itemCache = {}
|
||||||
|
QuestieDB.private.npcCache = {}
|
||||||
|
QuestieDB.private.objectCache = {}
|
||||||
|
end
|
||||||
|
QuestieLearner.data = Questie.dbLearner.global
|
||||||
|
end
|
||||||
|
|
||||||
local function GetLearnerSetting(key, defaultValue)
|
local function GetLearnerSetting(key, defaultValue)
|
||||||
if Questie and Questie.dbLearner and Questie.dbLearner.global and Questie.dbLearner.global.settings then
|
if Questie and Questie.dbLearner and Questie.dbLearner.global and Questie.dbLearner.global.settings then
|
||||||
local value = Questie.dbLearner.global.settings[key]
|
local value = Questie.dbLearner.global.settings[key]
|
||||||
@@ -787,6 +900,9 @@ local function _FlushNpcLiveUpdates()
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function _QueueNpcLiveUpdate(npcId)
|
local function _QueueNpcLiveUpdate(npcId)
|
||||||
|
if not (QuestieLearner and QuestieLearner.IsLearnerLiveEnabled and QuestieLearner:IsLearnerLiveEnabled()) then
|
||||||
|
return
|
||||||
|
end
|
||||||
_Learner.pendingNpcLiveUpdates = _Learner.pendingNpcLiveUpdates or {}
|
_Learner.pendingNpcLiveUpdates = _Learner.pendingNpcLiveUpdates or {}
|
||||||
_Learner.pendingNpcLiveUpdates[npcId] = true
|
_Learner.pendingNpcLiveUpdates[npcId] = true
|
||||||
|
|
||||||
@@ -861,10 +977,11 @@ local function CrossLinkAfterNPC(npcId)
|
|||||||
local learned = _GetDB()
|
local learned = _GetDB()
|
||||||
local npcData = learned.npcs[npcId]
|
local npcData = learned.npcs[npcId]
|
||||||
if not npcData then return end
|
if not npcData then return end
|
||||||
local npcOvr = QuestieDB and QuestieDB.npcDataOverrides
|
local liveEnabled = QuestieLearner and QuestieLearner.IsLearnerLiveEnabled and QuestieLearner:IsLearnerLiveEnabled()
|
||||||
|
local npcOvr = liveEnabled and QuestieDB and QuestieDB.npcDataOverrides or nil
|
||||||
|
|
||||||
for questId, qData in pairs(learned.quests) do
|
for questId, qData in pairs(learned.quests) do
|
||||||
local qOvr = QuestieDB and QuestieDB.questDataOverrides
|
local qOvr = liveEnabled and QuestieDB and QuestieDB.questDataOverrides or nil
|
||||||
|
|
||||||
-- Quest starters: quest[2][1] lists NPCs that start this quest
|
-- Quest starters: quest[2][1] lists NPCs that start this quest
|
||||||
if qData[2] and qData[2][1] then
|
if qData[2] and qData[2][1] then
|
||||||
@@ -931,9 +1048,10 @@ local function CrossLinkAfterQuest(questId)
|
|||||||
local learned = _GetDB()
|
local learned = _GetDB()
|
||||||
local qData = learned.quests[questId]
|
local qData = learned.quests[questId]
|
||||||
if not qData then return end
|
if not qData then return end
|
||||||
local qOvr = QuestieDB and QuestieDB.questDataOverrides
|
local liveEnabled = QuestieLearner and QuestieLearner.IsLearnerLiveEnabled and QuestieLearner:IsLearnerLiveEnabled()
|
||||||
local npcOvr = QuestieDB and QuestieDB.npcDataOverrides
|
local qOvr = liveEnabled and QuestieDB and QuestieDB.questDataOverrides or nil
|
||||||
local objOvr = QuestieDB and QuestieDB.objectDataOverrides
|
local npcOvr = liveEnabled and QuestieDB and QuestieDB.npcDataOverrides or nil
|
||||||
|
local objOvr = liveEnabled and QuestieDB and QuestieDB.objectDataOverrides or nil
|
||||||
|
|
||||||
-- Starter NPCs: quest[2][1] → npc[10]
|
-- Starter NPCs: quest[2][1] → npc[10]
|
||||||
if qData[2] and qData[2][1] then
|
if qData[2] and qData[2][1] then
|
||||||
@@ -973,7 +1091,7 @@ local function CrossLinkAfterQuest(questId)
|
|||||||
if iData then
|
if iData then
|
||||||
if not iData[5] then
|
if not iData[5] then
|
||||||
iData[5] = questId
|
iData[5] = questId
|
||||||
if QuestieDB and QuestieDB.itemDataOverrides then
|
if liveEnabled and QuestieDB and QuestieDB.itemDataOverrides then
|
||||||
local ovr = QuestieDB.itemDataOverrides[qData[11]] or {}
|
local ovr = QuestieDB.itemDataOverrides[qData[11]] or {}
|
||||||
QuestieDB.itemDataOverrides[qData[11]] = ovr
|
QuestieDB.itemDataOverrides[qData[11]] = ovr
|
||||||
if not ovr[5] then ovr[5] = questId end
|
if not ovr[5] then ovr[5] = questId end
|
||||||
@@ -1003,8 +1121,9 @@ local function CrossLinkAfterObject(objectId)
|
|||||||
local learned = _GetDB()
|
local learned = _GetDB()
|
||||||
local objData = learned.objects[objectId]
|
local objData = learned.objects[objectId]
|
||||||
if not objData then return end
|
if not objData then return end
|
||||||
local objOvr = QuestieDB and QuestieDB.objectDataOverrides
|
local liveEnabled = QuestieLearner and QuestieLearner.IsLearnerLiveEnabled and QuestieLearner:IsLearnerLiveEnabled()
|
||||||
local qOvr = QuestieDB and QuestieDB.questDataOverrides
|
local objOvr = liveEnabled and QuestieDB and QuestieDB.objectDataOverrides or nil
|
||||||
|
local qOvr = liveEnabled and QuestieDB and QuestieDB.questDataOverrides or nil
|
||||||
|
|
||||||
for questId, qData in pairs(learned.quests) do
|
for questId, qData in pairs(learned.quests) do
|
||||||
-- Object starters: quest[2][2]
|
-- Object starters: quest[2][2]
|
||||||
@@ -1054,7 +1173,8 @@ local function CrossLinkAfterItem(itemId)
|
|||||||
local learned = _GetDB()
|
local learned = _GetDB()
|
||||||
local iData = learned.items[itemId]
|
local iData = learned.items[itemId]
|
||||||
if not iData then return end
|
if not iData then return end
|
||||||
local qOvr = QuestieDB and QuestieDB.questDataOverrides
|
local liveEnabled = QuestieLearner and QuestieLearner.IsLearnerLiveEnabled and QuestieLearner:IsLearnerLiveEnabled()
|
||||||
|
local qOvr = liveEnabled and QuestieDB and QuestieDB.questDataOverrides or nil
|
||||||
|
|
||||||
-- If this item starts a quest (item[5]=startQuest), ensure that quest knows
|
-- If this item starts a quest (item[5]=startQuest), ensure that quest knows
|
||||||
-- about it via quest[2][3] (starter items slot)
|
-- about it via quest[2][3] (starter items slot)
|
||||||
@@ -1062,7 +1182,7 @@ local function CrossLinkAfterItem(itemId)
|
|||||||
if qData[11] == itemId then
|
if qData[11] == itemId then
|
||||||
if not iData[5] then
|
if not iData[5] then
|
||||||
iData[5] = questId
|
iData[5] = questId
|
||||||
if QuestieDB and QuestieDB.itemDataOverrides then
|
if liveEnabled and QuestieDB and QuestieDB.itemDataOverrides then
|
||||||
local ovr = QuestieDB.itemDataOverrides[itemId] or {}
|
local ovr = QuestieDB.itemDataOverrides[itemId] or {}
|
||||||
QuestieDB.itemDataOverrides[itemId] = ovr
|
QuestieDB.itemDataOverrides[itemId] = ovr
|
||||||
if not ovr[5] then ovr[5] = questId end
|
if not ovr[5] then ovr[5] = questId end
|
||||||
@@ -1090,9 +1210,10 @@ end
|
|||||||
local function CrossLinkAfterQuestGiver(questId, entityId, typeSlot, isStart)
|
local function CrossLinkAfterQuestGiver(questId, entityId, typeSlot, isStart)
|
||||||
local learned = _GetDB()
|
local learned = _GetDB()
|
||||||
local qData = learned.quests[questId]
|
local qData = learned.quests[questId]
|
||||||
local npcOvr = QuestieDB and QuestieDB.npcDataOverrides
|
local liveEnabled = QuestieLearner and QuestieLearner.IsLearnerLiveEnabled and QuestieLearner:IsLearnerLiveEnabled()
|
||||||
local objOvr = QuestieDB and QuestieDB.objectDataOverrides
|
local npcOvr = liveEnabled and QuestieDB and QuestieDB.npcDataOverrides or nil
|
||||||
local qOvr = QuestieDB and QuestieDB.questDataOverrides
|
local objOvr = liveEnabled and QuestieDB and QuestieDB.objectDataOverrides or nil
|
||||||
|
local qOvr = liveEnabled and QuestieDB and QuestieDB.questDataOverrides or nil
|
||||||
|
|
||||||
if typeSlot == 1 then
|
if typeSlot == 1 then
|
||||||
-- NPC ↔ quest
|
-- NPC ↔ quest
|
||||||
@@ -1180,7 +1301,9 @@ function QuestieLearner:LearnNPC(npcId, name, level, subName, npcFlags, factionS
|
|||||||
|
|
||||||
-- Live injection is intentionally batched: repeated kill/log/loot events for
|
-- Live injection is intentionally batched: repeated kill/log/loot events for
|
||||||
-- the same NPC update saved evidence immediately, then flush QuestieDB once.
|
-- the same NPC update saved evidence immediately, then flush QuestieDB once.
|
||||||
|
if self:IsLearnerLiveEnabled() then
|
||||||
_QueueNpcLiveUpdate(npcId)
|
_QueueNpcLiveUpdate(npcId)
|
||||||
|
end
|
||||||
|
|
||||||
if isNew then
|
if isNew then
|
||||||
Questie:Debug(Questie.DEBUG_LEARNER, "[QuestieLearner] New NPC learned:", npcId, name or "?")
|
Questie:Debug(Questie.DEBUG_LEARNER, "[QuestieLearner] New NPC learned:", npcId, name or "?")
|
||||||
@@ -1589,7 +1712,7 @@ function QuestieLearner:LearnQuest(questId, data)
|
|||||||
existing.mc = (existing.mc or 0) + 1
|
existing.mc = (existing.mc or 0) + 1
|
||||||
|
|
||||||
-- Live injection into questDataOverrides so GetQuest works without reload
|
-- Live injection into questDataOverrides so GetQuest works without reload
|
||||||
if QuestieDB and QuestieDB.questDataOverrides then
|
if self:IsLearnerLiveEnabled() and QuestieDB and QuestieDB.questDataOverrides then
|
||||||
local ovr = QuestieDB.questDataOverrides[questId]
|
local ovr = QuestieDB.questDataOverrides[questId]
|
||||||
if not ovr then
|
if not ovr then
|
||||||
QuestieDB.questDataOverrides[questId] = existing
|
QuestieDB.questDataOverrides[questId] = existing
|
||||||
@@ -1633,7 +1756,7 @@ function QuestieLearner:LearnQuestGiver(questId, entityId, entityType, isStart)
|
|||||||
table.insert(list, entityId)
|
table.insert(list, entityId)
|
||||||
|
|
||||||
-- Live injection into questDataOverrides so starters/finishers take effect without reload
|
-- Live injection into questDataOverrides so starters/finishers take effect without reload
|
||||||
if QuestieDB and QuestieDB.questDataOverrides and not IsAscensionProtected("QUEST", questId, field) then
|
if self:IsLearnerLiveEnabled() and QuestieDB and QuestieDB.questDataOverrides and not IsAscensionProtected("QUEST", questId, field) then
|
||||||
local ovr = QuestieDB.questDataOverrides[questId] or {}
|
local ovr = QuestieDB.questDataOverrides[questId] or {}
|
||||||
QuestieDB.questDataOverrides[questId] = ovr
|
QuestieDB.questDataOverrides[questId] = ovr
|
||||||
ovr[field] = ovr[field] or {}
|
ovr[field] = ovr[field] or {}
|
||||||
@@ -1699,7 +1822,7 @@ function QuestieLearner:LearnQuestObjectiveNPC(questId, npcId, objText, objectiv
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- 2. Apply to live questDataOverrides immediately (no reload needed)
|
-- 2. Apply to live questDataOverrides immediately (no reload needed)
|
||||||
if QuestieDB and QuestieDB.questDataOverrides and not IsAscensionProtected("QUEST", questId, 10) then
|
if self:IsLearnerLiveEnabled() and QuestieDB and QuestieDB.questDataOverrides and not IsAscensionProtected("QUEST", questId, 10) then
|
||||||
local ovr = QuestieDB.questDataOverrides[questId] or {}
|
local ovr = QuestieDB.questDataOverrides[questId] or {}
|
||||||
QuestieDB.questDataOverrides[questId] = ovr
|
QuestieDB.questDataOverrides[questId] = ovr
|
||||||
ovr[10] = ovr[10] or {}
|
ovr[10] = ovr[10] or {}
|
||||||
@@ -1720,12 +1843,14 @@ function QuestieLearner:LearnQuestObjectiveNPC(questId, npcId, objText, objectiv
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- 3. Re-process the quest so PopulateObjective registers tooltips & map pins
|
-- 3. Re-process the quest so PopulateObjective registers tooltips & map pins
|
||||||
|
if self:IsLearnerLiveEnabled() then
|
||||||
_RefreshActiveQuestPins({ [questId] = true })
|
_RefreshActiveQuestPins({ [questId] = true })
|
||||||
|
end
|
||||||
|
|
||||||
-- 3. Register with tooltip system immediately. Preserve the objective icon so
|
-- 3. Register with tooltip system immediately. Preserve the objective icon so
|
||||||
-- nameplates can render the correct learned slay/loot/talk marker.
|
-- nameplates can render the correct learned slay/loot/talk marker.
|
||||||
local QuestieTooltips = QuestieLoader:ImportModule("QuestieTooltips")
|
local QuestieTooltips = QuestieLoader:ImportModule("QuestieTooltips")
|
||||||
if QuestieTooltips and QuestieTooltips.RegisterObjectiveTooltip and not HasAscensionQuestObjectiveData(questId) then
|
if self:IsLearnerLiveEnabled() and QuestieTooltips and QuestieTooltips.RegisterObjectiveTooltip and not HasAscensionQuestObjectiveData(questId) then
|
||||||
local objectiveIcon
|
local objectiveIcon
|
||||||
local QuestLogCache = QuestieLoader:ImportModule("QuestLogCache")
|
local QuestLogCache = QuestieLoader:ImportModule("QuestLogCache")
|
||||||
local objectives = QuestLogCache and QuestLogCache.GetQuestObjectives and QuestLogCache.GetQuestObjectives(questId)
|
local objectives = QuestLogCache and QuestLogCache.GetQuestObjectives and QuestLogCache.GetQuestObjectives(questId)
|
||||||
@@ -1776,7 +1901,7 @@ function QuestieLearner:LearnItem(itemId, name, itemLevel, requiredLevel, itemCl
|
|||||||
existing.mc = (existing.mc or 0) + 1
|
existing.mc = (existing.mc or 0) + 1
|
||||||
|
|
||||||
-- Live injection into itemDataOverrides so QueryItemSingle works without reload
|
-- Live injection into itemDataOverrides so QueryItemSingle works without reload
|
||||||
if QuestieDB and QuestieDB.itemDataOverrides then
|
if self:IsLearnerLiveEnabled() and QuestieDB and QuestieDB.itemDataOverrides then
|
||||||
local ovr = QuestieDB.itemDataOverrides[itemId]
|
local ovr = QuestieDB.itemDataOverrides[itemId]
|
||||||
if not ovr then
|
if not ovr then
|
||||||
QuestieDB.itemDataOverrides[itemId] = existing
|
QuestieDB.itemDataOverrides[itemId] = existing
|
||||||
@@ -1815,7 +1940,7 @@ function QuestieLearner:LearnItemDrop(itemId, npcId)
|
|||||||
table.insert(existing[2], npcId)
|
table.insert(existing[2], npcId)
|
||||||
|
|
||||||
-- Live injection: sync drop list to itemDataOverrides
|
-- Live injection: sync drop list to itemDataOverrides
|
||||||
if QuestieDB and QuestieDB.itemDataOverrides and not IsAscensionProtected("ITEM", itemId, 2) then
|
if self:IsLearnerLiveEnabled() and QuestieDB and QuestieDB.itemDataOverrides and not IsAscensionProtected("ITEM", itemId, 2) then
|
||||||
local ovr = QuestieDB.itemDataOverrides[itemId] or {}
|
local ovr = QuestieDB.itemDataOverrides[itemId] or {}
|
||||||
QuestieDB.itemDataOverrides[itemId] = ovr
|
QuestieDB.itemDataOverrides[itemId] = ovr
|
||||||
ovr[2] = ovr[2] or {}
|
ovr[2] = ovr[2] or {}
|
||||||
@@ -1863,7 +1988,7 @@ function QuestieLearner:LearnObject(objectId, name)
|
|||||||
existing.mc = (existing.mc or 0) + 1
|
existing.mc = (existing.mc or 0) + 1
|
||||||
|
|
||||||
-- Live injection into objectDataOverrides so QueryObjectSingle works without reload
|
-- Live injection into objectDataOverrides so QueryObjectSingle works without reload
|
||||||
if QuestieDB and QuestieDB.objectDataOverrides then
|
if self:IsLearnerLiveEnabled() and QuestieDB and QuestieDB.objectDataOverrides then
|
||||||
local ovr = QuestieDB.objectDataOverrides[objectId]
|
local ovr = QuestieDB.objectDataOverrides[objectId]
|
||||||
if not ovr then
|
if not ovr then
|
||||||
QuestieDB.objectDataOverrides[objectId] = existing
|
QuestieDB.objectDataOverrides[objectId] = existing
|
||||||
@@ -1938,6 +2063,13 @@ function QuestieLearner:InjectLearnedData()
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local mode = self:GetDataSourceMode()
|
||||||
|
if mode == "static" or mode == "none" then
|
||||||
|
QuestieLearner.data = Questie.dbLearner.global
|
||||||
|
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieLearner] InjectLearnedData skipped because data source mode is", mode)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
local learned = Questie.dbLearner.global
|
local learned = Questie.dbLearner.global
|
||||||
-- Normalize malformed saved variables before any migration or injection.
|
-- Normalize malformed saved variables before any migration or injection.
|
||||||
-- This prevents old learner rows from carrying numeric spawn fields
|
-- This prevents old learner rows from carrying numeric spawn fields
|
||||||
@@ -2444,6 +2576,7 @@ function QuestieLearner:ClearAllData()
|
|||||||
Questie.dbLearner.global.quests = {}
|
Questie.dbLearner.global.quests = {}
|
||||||
Questie.dbLearner.global.items = {}
|
Questie.dbLearner.global.items = {}
|
||||||
Questie.dbLearner.global.objects = {}
|
Questie.dbLearner.global.objects = {}
|
||||||
|
self:ApplyDataSourceMode()
|
||||||
Questie:Print("Cleared all learned data.")
|
Questie:Print("Cleared all learned data.")
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -3000,6 +3133,20 @@ function QuestieLearner:OnLootOpened()
|
|||||||
for j = 1, sourceCount, 2 do
|
for j = 1, sourceCount, 2 do
|
||||||
local sourceGuid = sources[j]
|
local sourceGuid = sources[j]
|
||||||
local sourceQty = sources[j + 1]
|
local sourceQty = sources[j + 1]
|
||||||
|
Questie:Debug(
|
||||||
|
Questie.DEBUG_DEVELOP,
|
||||||
|
"[QuestieLearner:LootSourceTrace]",
|
||||||
|
"slot=",
|
||||||
|
i,
|
||||||
|
"sourceIndex=",
|
||||||
|
j,
|
||||||
|
"guid=",
|
||||||
|
tostring(sourceGuid),
|
||||||
|
"qty=",
|
||||||
|
tostring(sourceQty),
|
||||||
|
"lootName=",
|
||||||
|
tostring(lootName)
|
||||||
|
)
|
||||||
TraceLearnerEntity("loot_source", sourceGuid, nil, sourceQty, lootName)
|
TraceLearnerEntity("loot_source", sourceGuid, nil, sourceQty, lootName)
|
||||||
if type(sourceGuid) == "string" then
|
if type(sourceGuid) == "string" then
|
||||||
local sourceId, sourceType = GetIdAndTypeFromGUID(sourceGuid)
|
local sourceId, sourceType = GetIdAndTypeFromGUID(sourceGuid)
|
||||||
@@ -3037,6 +3184,14 @@ function QuestieLearner:OnGameObjectUsed(objectId)
|
|||||||
if not objectId or objectId <= 0 then return end
|
if not objectId or objectId <= 0 then return end
|
||||||
|
|
||||||
local objectName = ResolveObjectName(objectId)
|
local objectName = ResolveObjectName(objectId)
|
||||||
|
Questie:Debug(
|
||||||
|
Questie.DEBUG_DEVELOP,
|
||||||
|
"[QuestieLearner:GameObjectUsedTrace]",
|
||||||
|
"id=",
|
||||||
|
tostring(objectId),
|
||||||
|
"name=",
|
||||||
|
tostring(objectName)
|
||||||
|
)
|
||||||
TraceLearnerEntity("gameobject_used", nil, "GameObject", objectId, objectName)
|
TraceLearnerEntity("gameobject_used", nil, "GameObject", objectId, objectName)
|
||||||
self:LearnObject(objectId, objectName)
|
self:LearnObject(objectId, objectName)
|
||||||
end
|
end
|
||||||
@@ -3345,7 +3500,7 @@ function QuestieLearner:OnCombatLogEvent(timestamp, eventType, srcGUID, srcName,
|
|||||||
if guidSpawns then
|
if guidSpawns then
|
||||||
local count = 0
|
local count = 0
|
||||||
for _ in pairs(guidSpawns) do count = count + 1 end
|
for _ in pairs(guidSpawns) do count = count + 1 end
|
||||||
if count >= 1 then
|
if self:IsLearnerLiveEnabled() and count >= 1 then
|
||||||
_MergeSpawnEvidence(npcId)
|
_MergeSpawnEvidence(npcId)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -3824,7 +3979,7 @@ function QuestieLearner:Initialize()
|
|||||||
EnsureLearnedData()
|
EnsureLearnedData()
|
||||||
QuestieLearner.data = Questie.dbLearner.global
|
QuestieLearner.data = Questie.dbLearner.global
|
||||||
self:RegisterEvents()
|
self:RegisterEvents()
|
||||||
self:InjectLearnedData()
|
self:ApplyDataSourceMode()
|
||||||
_RegisterLearnedSpawnTooltipHook()
|
_RegisterLearnedSpawnTooltipHook()
|
||||||
|
|
||||||
local QuestieLearnerComms = QuestieLoader:ImportModule("QuestieLearnerComms")
|
local QuestieLearnerComms = QuestieLoader:ImportModule("QuestieLearnerComms")
|
||||||
|
|||||||
@@ -253,7 +253,8 @@ function QuestieTooltips:GetTooltip(key)
|
|||||||
if (not QuestieTooltips.lookupByKey[key]) then
|
if (not QuestieTooltips.lookupByKey[key]) then
|
||||||
local QuestieLearner = QuestieLoader:ImportModule("QuestieLearner")
|
local QuestieLearner = QuestieLoader:ImportModule("QuestieLearner")
|
||||||
local QuestLogCache = QuestieLoader:ImportModule("QuestLogCache")
|
local QuestLogCache = QuestieLoader:ImportModule("QuestLogCache")
|
||||||
if QuestieLearner and QuestieLearner.data then
|
local mode = QuestieLearner and QuestieLearner.GetDataSourceMode and QuestieLearner:GetDataSourceMode() or "auto"
|
||||||
|
if QuestieLearner and QuestieLearner.data and mode ~= "static" and mode ~= "none" then
|
||||||
-- Try to find in learned NPCs or objects
|
-- Try to find in learned NPCs or objects
|
||||||
local id = tonumber(key:sub(3))
|
local id = tonumber(key:sub(3))
|
||||||
if id then
|
if id then
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
local function read(path)
|
||||||
|
local f = assert(io.open(path, "r"), "cannot open " .. path)
|
||||||
|
local c = f:read("*a")
|
||||||
|
f:close()
|
||||||
|
return c
|
||||||
|
end
|
||||||
|
|
||||||
|
local function has(content, needle)
|
||||||
|
return string.find(content, needle, 1, true) ~= nil
|
||||||
|
end
|
||||||
|
|
||||||
|
describe("QuestieLearner data source mode", function()
|
||||||
|
it("adds a mode selector and explicit fallback options in the database tab", function()
|
||||||
|
local dbOptions = read("Modules/Options/DatabaseTab/QuestieOptionsDatabase.lua")
|
||||||
|
assert.is_true(has(dbOptions, "Data Source Mode"))
|
||||||
|
assert.is_true(has(dbOptions, "auto = l10n(\"Auto (current behavior)\")"))
|
||||||
|
assert.is_true(has(dbOptions, "learner = l10n(\"Learner Only\")"))
|
||||||
|
assert.is_true(has(dbOptions, "static = l10n(\"Static Only\")"))
|
||||||
|
assert.is_true(has(dbOptions, "none = l10n(\"Neither (base DB only)\")"))
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("defaults the learner mode to auto and exposes the live refresh hook", function()
|
||||||
|
local learner = read("Modules/QuestieLearner.lua")
|
||||||
|
local defaults = read("Modules/Options/QuestieOptionsDefaults.lua")
|
||||||
|
assert.is_true(has(defaults, "dataSourceMode = \"auto\""))
|
||||||
|
assert.is_true(has(learner, "function QuestieLearner:GetDataSourceMode()"))
|
||||||
|
assert.is_true(has(learner, "function QuestieLearner:IsLearnerLiveEnabled()"))
|
||||||
|
assert.is_true(has(learner, "function QuestieLearner:ApplyDataSourceMode()"))
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("gates static suppression and tooltip fallback on the selected mode", function()
|
||||||
|
local quest = read("Modules/Quest/QuestieQuest.lua")
|
||||||
|
local priv = read("Modules/Quest/QuestieQuestPrivates.lua")
|
||||||
|
local tip = read("Modules/Tooltips/Tooltip.lua")
|
||||||
|
assert.is_true(has(quest, "dataSourceMode == \"auto\" or dataSourceMode == \"learner\""))
|
||||||
|
assert.is_true(has(priv, "dataSourceMode == \"none\" or dataSourceMode == \"learner\""))
|
||||||
|
assert.is_true(has(tip, "mode ~= \"static\" and mode ~= \"none\""))
|
||||||
|
end)
|
||||||
|
end)
|
||||||
Reference in New Issue
Block a user