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))
|
return select(8, QuestieCompat.GetQuestLogTitle(questLogIndex))
|
||||||
end
|
end
|
||||||
|
|
||||||
---Keeps Blizzard/server objective POIs from drawing over Questie's objective icons.
|
local QUESTIE_DUPLICATE_POI_ICON_TYPES = {
|
||||||
---@param useQuestieObjectives boolean
|
complete = true,
|
||||||
function QuestieCompat.SyncBlizzardObjectivePOIs(useQuestieObjectives)
|
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
|
if GetCVar and GetCVar("questPOI") ~= nil and SetCVar then
|
||||||
SetCVar("questPOI", useQuestieObjectives and "0" or "1")
|
SetCVar("questPOI", "1")
|
||||||
end
|
end
|
||||||
|
|
||||||
if WorldMapQuestShowObjectives and WorldMapQuestShowObjectives.SetChecked then
|
if WorldMapQuestShowObjectives and WorldMapQuestShowObjectives.SetChecked then
|
||||||
WorldMapQuestShowObjectives:SetChecked(not useQuestieObjectives)
|
WorldMapQuestShowObjectives:SetChecked(true)
|
||||||
end
|
end
|
||||||
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
|
-- https://wowpedia.fandom.com/wiki/API_GetQuestLink
|
||||||
-- Returns a QuestLink for a quest.
|
-- 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.
|
-- 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,
|
get = function() return Questie.db.profile.enableObjectives; end,
|
||||||
set = function(info, value)
|
set = function(info, value)
|
||||||
Questie.db.profile.enableObjectives = value
|
Questie.db.profile.enableObjectives = value
|
||||||
QuestieCompat.SyncBlizzardObjectivePOIs(value)
|
|
||||||
QuestieQuest:ToggleNotes(value)
|
QuestieQuest:ToggleNotes(value)
|
||||||
QuestieOptionsUtils.DetermineTheme()
|
QuestieOptionsUtils.DetermineTheme()
|
||||||
end,
|
end,
|
||||||
@@ -1335,7 +1334,6 @@ end
|
|||||||
function QuestieOptionsUtils.ExecuteTheme(info, value)
|
function QuestieOptionsUtils.ExecuteTheme(info, value)
|
||||||
Questie.db.profile.iconTheme = value
|
Questie.db.profile.iconTheme = value
|
||||||
if value == 'questie' then
|
if value == 'questie' then
|
||||||
QuestieCompat.SyncBlizzardObjectivePOIs(true)
|
|
||||||
Questie.db.profile.enableObjectives = true
|
Questie.db.profile.enableObjectives = true
|
||||||
Questie.db.profile.ICON_SLAY = Questie.icons["slay"]
|
Questie.db.profile.ICON_SLAY = Questie.icons["slay"]
|
||||||
Questie.db.profile.ICON_LOOT = Questie.icons["loot"]
|
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.alwaysGlowMinimap = optionsDefaults.profile.alwaysGlowMinimap
|
||||||
Questie.db.profile.clusterLevelHotzone = optionsDefaults.profile.clusterLevelHotzone
|
Questie.db.profile.clusterLevelHotzone = optionsDefaults.profile.clusterLevelHotzone
|
||||||
elseif value == 'pfquest' then
|
elseif value == 'pfquest' then
|
||||||
QuestieCompat.SyncBlizzardObjectivePOIs(true)
|
|
||||||
Questie.db.profile.enableObjectives = true
|
Questie.db.profile.enableObjectives = true
|
||||||
Questie.db.profile.ICON_SLAY = Questie.icons["node"]
|
Questie.db.profile.ICON_SLAY = Questie.icons["node"]
|
||||||
Questie.db.profile.ICON_LOOT = 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.alwaysGlowMinimap = false
|
||||||
Questie.db.profile.clusterLevelHotzone = 1
|
Questie.db.profile.clusterLevelHotzone = 1
|
||||||
elseif value == 'blizzard' then
|
elseif value == 'blizzard' then
|
||||||
QuestieCompat.SyncBlizzardObjectivePOIs(false)
|
QuestieCompat.EnableBlizzardObjectivePOIs()
|
||||||
Questie.db.profile.enableObjectives = false
|
Questie.db.profile.enableObjectives = false
|
||||||
Questie.db.profile.ICON_SLAY = Questie.icons["slay"]
|
Questie.db.profile.ICON_SLAY = Questie.icons["slay"]
|
||||||
Questie.db.profile.ICON_LOOT = Questie.icons["loot"]
|
Questie.db.profile.ICON_LOOT = Questie.icons["loot"]
|
||||||
|
|||||||
@@ -226,7 +226,7 @@ QuestieInit.Stages[1] = function() -- run as a coroutine
|
|||||||
end
|
end
|
||||||
|
|
||||||
Questie:SetIcons()
|
Questie:SetIcons()
|
||||||
QuestieCompat.SyncBlizzardObjectivePOIs(Questie.db.profile.enableObjectives)
|
QuestieCompat.InitializeBlizzardPOISuppression()
|
||||||
|
|
||||||
if QUESTIE_LOCALES_OVERRIDE ~= nil then
|
if QUESTIE_LOCALES_OVERRIDE ~= nil then
|
||||||
l10n:InitializeLocaleOverride()
|
l10n:InitializeLocaleOverride()
|
||||||
|
|||||||
@@ -302,7 +302,6 @@ function QuestieMenu:Show(hideDelay)
|
|||||||
tinsert(menuTable, { text= l10n("Objective"), func = function()
|
tinsert(menuTable, { text= l10n("Objective"), func = function()
|
||||||
local value = not Questie.db.profile.enableObjectives
|
local value = not Questie.db.profile.enableObjectives
|
||||||
Questie.db.profile.enableObjectives = value
|
Questie.db.profile.enableObjectives = value
|
||||||
QuestieCompat.SyncBlizzardObjectivePOIs(value)
|
|
||||||
QuestieQuest:ToggleNotes(value)
|
QuestieQuest:ToggleNotes(value)
|
||||||
QuestieQuest:SmoothReset()
|
QuestieQuest:SmoothReset()
|
||||||
end, icon=QuestieLib.AddonPath.."Icons\\event.blp", notCheckable=false, checked=Questie.db.profile.enableObjectives, isNotRadio=true, keepShownOnClick=true})
|
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
|
return content:find(needle, 1, true) ~= nil
|
||||||
end
|
end
|
||||||
|
|
||||||
describe("Blizzard objective POI sync", function()
|
describe("Blizzard objective POI suppression", function()
|
||||||
local compat = read("Compat/Compat.lua")
|
local compat = read("Compat/Compat.lua")
|
||||||
local init = read("Modules/QuestieInit.lua")
|
local init = read("Modules/QuestieInit.lua")
|
||||||
local iconOptions = read("Modules/Options/IconsTab/QuestieOptionsIcons.lua")
|
local iconOptions = read("Modules/Options/IconsTab/QuestieOptionsIcons.lua")
|
||||||
local questieMenu = read("Modules/QuestieMenu/QuestieMenu.lua")
|
local questieMenu = read("Modules/QuestieMenu/QuestieMenu.lua")
|
||||||
|
|
||||||
it("disables native quest POIs when Questie objective icons are enabled", function()
|
it("suppresses only native POI buttons that duplicate visible Questie quest icons", function()
|
||||||
local helperStart = assert(compat:find("function QuestieCompat.SyncBlizzardObjectivePOIs", 1, true))
|
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 helperEnd = assert(compat:find("-- https://wowpedia.fandom.com/wiki/API_GetQuestLink", helperStart, true))
|
||||||
local helper = compat:sub(helperStart, helperEnd)
|
local helper = compat:sub(helperStart, helperEnd)
|
||||||
|
|
||||||
assert.is_true(has(helper, "SetCVar(\"questPOI\", useQuestieObjectives and \"0\" or \"1\")"))
|
assert.is_true(has(compat, "complete = true"))
|
||||||
assert.is_true(has(helper, "WorldMapQuestShowObjectives:SetChecked(not useQuestieObjectives)"))
|
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)
|
end)
|
||||||
|
|
||||||
it("syncs native POIs on startup and objective ownership changes", function()
|
it("hooks Blizzard POI display without globally disabling native POIs", function()
|
||||||
assert.is_true(has(init, "QuestieCompat.SyncBlizzardObjectivePOIs(Questie.db.profile.enableObjectives)"))
|
local helperStart = assert(compat:find("function QuestieCompat.InitializeBlizzardPOISuppression", 1, true))
|
||||||
assert.is_true(has(iconOptions, "QuestieCompat.SyncBlizzardObjectivePOIs(value)"))
|
local helperEnd = assert(compat:find("-- https://wowpedia.fandom.com/wiki/API_GetQuestLink", helperStart, true))
|
||||||
assert.is_true(has(iconOptions, "QuestieCompat.SyncBlizzardObjectivePOIs(true)"))
|
local helper = compat:sub(helperStart, helperEnd)
|
||||||
assert.is_true(has(iconOptions, "QuestieCompat.SyncBlizzardObjectivePOIs(false)"))
|
|
||||||
assert.is_true(has(questieMenu, "QuestieCompat.SyncBlizzardObjectivePOIs(value)"))
|
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)
|
||||||
end)
|
end)
|
||||||
|
|||||||
Reference in New Issue
Block a user