fix: suppress duplicate native quest POIs
This commit is contained in:
+145
-5
@@ -587,18 +587,158 @@ function QuestieCompat.GetQuestIDFromLogIndex(questLogIndex)
|
||||
return select(8, QuestieCompat.GetQuestLogTitle(questLogIndex))
|
||||
end
|
||||
|
||||
---Keeps Blizzard/server objective POIs from drawing over Questie's objective icons.
|
||||
---@param useQuestieObjectives boolean
|
||||
function QuestieCompat.SyncBlizzardObjectivePOIs(useQuestieObjectives)
|
||||
local QUESTIE_DUPLICATE_POI_ICON_TYPES = {
|
||||
complete = true,
|
||||
monster = true,
|
||||
object = true,
|
||||
item = true,
|
||||
event = true,
|
||||
}
|
||||
|
||||
local BLIZZARD_POI_QUEST_ID_FIELDS = {
|
||||
"questID",
|
||||
"questId",
|
||||
"questIDNumber",
|
||||
"questIDNum",
|
||||
"questLogID",
|
||||
"id",
|
||||
}
|
||||
|
||||
local BLIZZARD_POI_QUEST_LOG_INDEX_FIELDS = {
|
||||
"questLogIndex",
|
||||
"questIndex",
|
||||
"logIndex",
|
||||
}
|
||||
|
||||
local function _ToPositiveNumber(value)
|
||||
if type(value) == "number" or type(value) == "string" then
|
||||
local number = tonumber(value)
|
||||
if number and number > 0 then
|
||||
return number
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
---Enables Blizzard/server objective POIs without globally disabling them when Questie objectives are on.
|
||||
function QuestieCompat.EnableBlizzardObjectivePOIs()
|
||||
if GetCVar and GetCVar("questPOI") ~= nil and SetCVar then
|
||||
SetCVar("questPOI", useQuestieObjectives and "0" or "1")
|
||||
SetCVar("questPOI", "1")
|
||||
end
|
||||
|
||||
if WorldMapQuestShowObjectives and WorldMapQuestShowObjectives.SetChecked then
|
||||
WorldMapQuestShowObjectives:SetChecked(not useQuestieObjectives)
|
||||
WorldMapQuestShowObjectives:SetChecked(true)
|
||||
end
|
||||
end
|
||||
|
||||
---@param frame table
|
||||
---@return boolean
|
||||
local function _IsVisibleQuestiePOIFrame(frame)
|
||||
if (not frame) or (not frame.data) or (not QUESTIE_DUPLICATE_POI_ICON_TYPES[frame.data.Type]) then
|
||||
return false
|
||||
end
|
||||
|
||||
if frame.ShouldBeHidden then
|
||||
return not frame:ShouldBeHidden()
|
||||
end
|
||||
|
||||
return not frame.hidden
|
||||
end
|
||||
|
||||
---@param questId number
|
||||
---@return boolean
|
||||
function QuestieCompat.HasVisibleQuestiePOIForQuest(questId)
|
||||
if (not questId) or questId <= 0 then
|
||||
return false
|
||||
end
|
||||
|
||||
local QuestieMap = QuestieLoader:ImportModule("QuestieMap")
|
||||
local questFrames = QuestieMap.questIdFrames and QuestieMap.questIdFrames[questId]
|
||||
if not questFrames then
|
||||
return false
|
||||
end
|
||||
|
||||
for _, frameName in pairs(questFrames) do
|
||||
if _IsVisibleQuestiePOIFrame(_G[frameName]) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
---@param poiButton table
|
||||
---@return number|nil
|
||||
function QuestieCompat.GetQuestIDFromBlizzardPOIButton(poiButton)
|
||||
if not poiButton then
|
||||
return nil
|
||||
end
|
||||
|
||||
for _, field in ipairs(BLIZZARD_POI_QUEST_ID_FIELDS) do
|
||||
local questId = _ToPositiveNumber(poiButton[field])
|
||||
if questId then
|
||||
return questId
|
||||
end
|
||||
end
|
||||
|
||||
for _, field in ipairs(BLIZZARD_POI_QUEST_LOG_INDEX_FIELDS) do
|
||||
local questLogIndex = _ToPositiveNumber(poiButton[field])
|
||||
if questLogIndex then
|
||||
local questId = QuestieCompat.GetQuestIDFromLogIndex(questLogIndex)
|
||||
if questId and questId > 0 then
|
||||
return questId
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
---@param poiButton table
|
||||
function QuestieCompat.SuppressDuplicateBlizzardPOIButton(poiButton)
|
||||
local questId = QuestieCompat.GetQuestIDFromBlizzardPOIButton(poiButton)
|
||||
if questId and QuestieCompat.HasVisibleQuestiePOIForQuest(questId) then
|
||||
poiButton.questieDuplicateSuppressed = true
|
||||
poiButton:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
function QuestieCompat.SuppressDuplicateBlizzardPOI(parentName, buttonType, buttonIndex)
|
||||
local poiButton = _G[string.format(
|
||||
"poi%s%s_%d",
|
||||
tostring(parentName or ""),
|
||||
tostring(buttonType or ""),
|
||||
_ToPositiveNumber(buttonIndex) or 0
|
||||
)]
|
||||
if poiButton then
|
||||
QuestieCompat.SuppressDuplicateBlizzardPOIButton(poiButton)
|
||||
end
|
||||
end
|
||||
|
||||
function QuestieCompat.InitializeBlizzardPOISuppression()
|
||||
if QuestieCompat._blizzardPOISuppressionHooked then
|
||||
return
|
||||
end
|
||||
|
||||
local hooked = false
|
||||
if QuestPOI_DisplayButton then
|
||||
hooksecurefunc("QuestPOI_DisplayButton", function(parentName, buttonType, buttonIndex)
|
||||
QuestieCompat.SuppressDuplicateBlizzardPOI(parentName, buttonType, buttonIndex)
|
||||
end)
|
||||
hooked = true
|
||||
end
|
||||
|
||||
if QuestPOI_SelectButton then
|
||||
hooksecurefunc("QuestPOI_SelectButton", function(poiButton)
|
||||
QuestieCompat.SuppressDuplicateBlizzardPOIButton(poiButton)
|
||||
end)
|
||||
hooked = true
|
||||
end
|
||||
|
||||
QuestieCompat._blizzardPOISuppressionHooked = hooked
|
||||
end
|
||||
|
||||
-- https://wowpedia.fandom.com/wiki/API_GetQuestLink
|
||||
-- Returns a QuestLink for a quest.
|
||||
-- Between patches 6.2 and 7.3.2 argument was changed to take a QuestID instead of a quest log index.
|
||||
|
||||
@@ -266,7 +266,6 @@ function QuestieOptions.tabs.icons:Initialize()
|
||||
get = function() return Questie.db.profile.enableObjectives; end,
|
||||
set = function(info, value)
|
||||
Questie.db.profile.enableObjectives = value
|
||||
QuestieCompat.SyncBlizzardObjectivePOIs(value)
|
||||
QuestieQuest:ToggleNotes(value)
|
||||
QuestieOptionsUtils.DetermineTheme()
|
||||
end,
|
||||
@@ -1335,7 +1334,6 @@ end
|
||||
function QuestieOptionsUtils.ExecuteTheme(info, value)
|
||||
Questie.db.profile.iconTheme = value
|
||||
if value == 'questie' then
|
||||
QuestieCompat.SyncBlizzardObjectivePOIs(true)
|
||||
Questie.db.profile.enableObjectives = true
|
||||
Questie.db.profile.ICON_SLAY = Questie.icons["slay"]
|
||||
Questie.db.profile.ICON_LOOT = Questie.icons["loot"]
|
||||
@@ -1348,7 +1346,6 @@ function QuestieOptionsUtils.ExecuteTheme(info, value)
|
||||
Questie.db.profile.alwaysGlowMinimap = optionsDefaults.profile.alwaysGlowMinimap
|
||||
Questie.db.profile.clusterLevelHotzone = optionsDefaults.profile.clusterLevelHotzone
|
||||
elseif value == 'pfquest' then
|
||||
QuestieCompat.SyncBlizzardObjectivePOIs(true)
|
||||
Questie.db.profile.enableObjectives = true
|
||||
Questie.db.profile.ICON_SLAY = Questie.icons["node"]
|
||||
Questie.db.profile.ICON_LOOT = Questie.icons["node"]
|
||||
@@ -1361,7 +1358,7 @@ function QuestieOptionsUtils.ExecuteTheme(info, value)
|
||||
Questie.db.profile.alwaysGlowMinimap = false
|
||||
Questie.db.profile.clusterLevelHotzone = 1
|
||||
elseif value == 'blizzard' then
|
||||
QuestieCompat.SyncBlizzardObjectivePOIs(false)
|
||||
QuestieCompat.EnableBlizzardObjectivePOIs()
|
||||
Questie.db.profile.enableObjectives = false
|
||||
Questie.db.profile.ICON_SLAY = Questie.icons["slay"]
|
||||
Questie.db.profile.ICON_LOOT = Questie.icons["loot"]
|
||||
|
||||
@@ -226,7 +226,7 @@ QuestieInit.Stages[1] = function() -- run as a coroutine
|
||||
end
|
||||
|
||||
Questie:SetIcons()
|
||||
QuestieCompat.SyncBlizzardObjectivePOIs(Questie.db.profile.enableObjectives)
|
||||
QuestieCompat.InitializeBlizzardPOISuppression()
|
||||
|
||||
if QUESTIE_LOCALES_OVERRIDE ~= nil then
|
||||
l10n:InitializeLocaleOverride()
|
||||
|
||||
@@ -302,7 +302,6 @@ function QuestieMenu:Show(hideDelay)
|
||||
tinsert(menuTable, { text= l10n("Objective"), func = function()
|
||||
local value = not Questie.db.profile.enableObjectives
|
||||
Questie.db.profile.enableObjectives = value
|
||||
QuestieCompat.SyncBlizzardObjectivePOIs(value)
|
||||
QuestieQuest:ToggleNotes(value)
|
||||
QuestieQuest:SmoothReset()
|
||||
end, icon=QuestieLib.AddonPath.."Icons\\event.blp", notCheckable=false, checked=Questie.db.profile.enableObjectives, isNotRadio=true, keepShownOnClick=true})
|
||||
|
||||
@@ -9,26 +9,42 @@ local function has(content, needle)
|
||||
return content:find(needle, 1, true) ~= nil
|
||||
end
|
||||
|
||||
describe("Blizzard objective POI sync", function()
|
||||
describe("Blizzard objective POI suppression", function()
|
||||
local compat = read("Compat/Compat.lua")
|
||||
local init = read("Modules/QuestieInit.lua")
|
||||
local iconOptions = read("Modules/Options/IconsTab/QuestieOptionsIcons.lua")
|
||||
local questieMenu = read("Modules/QuestieMenu/QuestieMenu.lua")
|
||||
|
||||
it("disables native quest POIs when Questie objective icons are enabled", function()
|
||||
local helperStart = assert(compat:find("function QuestieCompat.SyncBlizzardObjectivePOIs", 1, true))
|
||||
it("suppresses only native POI buttons that duplicate visible Questie quest icons", function()
|
||||
local helperStart = assert(compat:find("function QuestieCompat.HasVisibleQuestiePOIForQuest", 1, true))
|
||||
local helperEnd = assert(compat:find("-- https://wowpedia.fandom.com/wiki/API_GetQuestLink", helperStart, true))
|
||||
local helper = compat:sub(helperStart, helperEnd)
|
||||
|
||||
assert.is_true(has(helper, "SetCVar(\"questPOI\", useQuestieObjectives and \"0\" or \"1\")"))
|
||||
assert.is_true(has(helper, "WorldMapQuestShowObjectives:SetChecked(not useQuestieObjectives)"))
|
||||
assert.is_true(has(compat, "complete = true"))
|
||||
assert.is_true(has(compat, "monster = true"))
|
||||
assert.is_true(has(compat, "object = true"))
|
||||
assert.is_true(has(compat, "item = true"))
|
||||
assert.is_true(has(compat, "event = true"))
|
||||
assert.is_true(has(compat, "frame:ShouldBeHidden()"))
|
||||
assert.is_true(has(helper, "QuestieMap.questIdFrames and QuestieMap.questIdFrames[questId]"))
|
||||
assert.is_true(has(helper, "poiButton:Hide()"))
|
||||
end)
|
||||
|
||||
it("syncs native POIs on startup and objective ownership changes", function()
|
||||
assert.is_true(has(init, "QuestieCompat.SyncBlizzardObjectivePOIs(Questie.db.profile.enableObjectives)"))
|
||||
assert.is_true(has(iconOptions, "QuestieCompat.SyncBlizzardObjectivePOIs(value)"))
|
||||
assert.is_true(has(iconOptions, "QuestieCompat.SyncBlizzardObjectivePOIs(true)"))
|
||||
assert.is_true(has(iconOptions, "QuestieCompat.SyncBlizzardObjectivePOIs(false)"))
|
||||
assert.is_true(has(questieMenu, "QuestieCompat.SyncBlizzardObjectivePOIs(value)"))
|
||||
it("hooks Blizzard POI display without globally disabling native POIs", function()
|
||||
local helperStart = assert(compat:find("function QuestieCompat.InitializeBlizzardPOISuppression", 1, true))
|
||||
local helperEnd = assert(compat:find("-- https://wowpedia.fandom.com/wiki/API_GetQuestLink", helperStart, true))
|
||||
local helper = compat:sub(helperStart, helperEnd)
|
||||
|
||||
assert.is_true(has(helper, "hooksecurefunc(\"QuestPOI_DisplayButton\""))
|
||||
assert.is_true(has(helper, "hooksecurefunc(\"QuestPOI_SelectButton\""))
|
||||
assert.is_true(has(compat, "\"poi%s%s_%d\""))
|
||||
assert.is_false(has(compat, "SetCVar(\"questPOI\", useQuestieObjectives and \"0\" or \"1\")"))
|
||||
end)
|
||||
|
||||
it("initializes duplicate suppression but leaves objective toggles in control of Questie icons only", function()
|
||||
assert.is_true(has(init, "QuestieCompat.InitializeBlizzardPOISuppression()"))
|
||||
assert.is_false(has(iconOptions, "QuestieCompat.SyncBlizzardObjectivePOIs"))
|
||||
assert.is_true(has(iconOptions, "QuestieCompat.EnableBlizzardObjectivePOIs()"))
|
||||
assert.is_false(has(questieMenu, "QuestieCompat.SyncBlizzardObjectivePOIs"))
|
||||
end)
|
||||
end)
|
||||
|
||||
Reference in New Issue
Block a user