feat(tracker): add objective marker button to quest lines
Ascension's client backports retail's floating objective marker. This adds a button to each tracker quest line that points the marker at that quest, mirroring the quest pin the world map draws for it. Supertracking is a slave of the map's quest selection: both the map and the Blizzard watch frame funnel through SelectQuestLogEntry, and calling C_SuperTrack.SetSuperTrackedQuestID directly only moves the marker until the next map interaction stomps it. So the button clicks the same POI frame the client clicks -- the watch frame button when one exists, otherwise the map's quest frame. The client dropped GetSuperTrackedQuestID, so the current quest is read by hooking SetSuperTrackedQuestID instead. Every path ends up there, including the automatic re-pick on zone change, so the highlight cannot fall out of sync with tracking changed outside the addon. Caching what we last set would have gone stale the moment the player used the map. The button mirrors the pin's own textures rather than picking atlas cells, so the digit, the "?" completed quests use and the selected variant all follow whatever the client draws. Quests with no pin get no button, and the map's POI frames are built on demand so buttons appear without opening the map. Adds trackerShowSuperTrackButton and trackerSuperTrackButtonSize.
This commit is contained in:
@@ -102,6 +102,24 @@ local trackerOptionsLocales = {
|
|||||||
["frFR"] = "Affiche le niveau des quêtes avec le titre des quêtes.",
|
["frFR"] = "Affiche le niveau des quêtes avec le titre des quêtes.",
|
||||||
},
|
},
|
||||||
---------------------------------------------------------
|
---------------------------------------------------------
|
||||||
|
["Show Objective Marker Button"] = {
|
||||||
|
["enUS"] = true,
|
||||||
|
},
|
||||||
|
["When this is checked, quests that can be reached by the floating objective marker get a button in the Questie Tracker that points the marker at them."] = {
|
||||||
|
["enUS"] = true,
|
||||||
|
},
|
||||||
|
---------------------------------------------------------
|
||||||
|
["Objective Marker Button Size"] = {
|
||||||
|
["enUS"] = true,
|
||||||
|
},
|
||||||
|
["The size of the objective marker button shown next to each quest in the Questie Tracker."] = {
|
||||||
|
["enUS"] = true,
|
||||||
|
},
|
||||||
|
---------------------------------------------------------
|
||||||
|
["Point the objective marker at this quest"] = {
|
||||||
|
["enUS"] = true,
|
||||||
|
},
|
||||||
|
---------------------------------------------------------
|
||||||
["Auto Minimize Completed Quests"] = {
|
["Auto Minimize Completed Quests"] = {
|
||||||
["ptBR"] = "Minimizar missões concluídas",
|
["ptBR"] = "Minimizar missões concluídas",
|
||||||
["ruRU"] = "Свернуть выполненные",
|
["ruRU"] = "Свернуть выполненные",
|
||||||
|
|||||||
@@ -113,6 +113,8 @@ function QuestieOptionsDefaults:Load()
|
|||||||
autoTrackQuests = true,
|
autoTrackQuests = true,
|
||||||
trackerShowCompleteQuests = true,
|
trackerShowCompleteQuests = true,
|
||||||
trackerShowQuestLevel = true,
|
trackerShowQuestLevel = true,
|
||||||
|
trackerShowSuperTrackButton = true,
|
||||||
|
trackerSuperTrackButtonSize = 25,
|
||||||
collapseCompletedQuests = false,
|
collapseCompletedQuests = false,
|
||||||
hideCompletedQuestObjectives = false,
|
hideCompletedQuestObjectives = false,
|
||||||
hideBlizzardCompletionText = false,
|
hideBlizzardCompletionText = false,
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ local TrackerBaseFrame = QuestieLoader:ImportModule("TrackerBaseFrame")
|
|||||||
local TrackerLinePool = QuestieLoader:ImportModule("TrackerLinePool")
|
local TrackerLinePool = QuestieLoader:ImportModule("TrackerLinePool")
|
||||||
---@type TrackerQuestTimers
|
---@type TrackerQuestTimers
|
||||||
local TrackerQuestTimers = QuestieLoader:ImportModule("TrackerQuestTimers")
|
local TrackerQuestTimers = QuestieLoader:ImportModule("TrackerQuestTimers")
|
||||||
|
---@type TrackerUtils
|
||||||
|
local TrackerUtils = QuestieLoader:ImportModule("TrackerUtils")
|
||||||
---@type QuestieArrow
|
---@type QuestieArrow
|
||||||
local QuestieArrow = QuestieLoader:ImportModule("QuestieArrow")
|
local QuestieArrow = QuestieLoader:ImportModule("QuestieArrow")
|
||||||
|
|
||||||
@@ -175,6 +177,37 @@ function QuestieOptions.tabs.tracker:Initialize()
|
|||||||
QuestieTracker:Update()
|
QuestieTracker:Update()
|
||||||
end
|
end
|
||||||
},
|
},
|
||||||
|
showSuperTrackButton = {
|
||||||
|
type = "toggle",
|
||||||
|
order = 5,
|
||||||
|
width = 1.5,
|
||||||
|
name = function() return l10n('Show Objective Marker Button') end,
|
||||||
|
desc = function() return l10n('When this is checked, quests that can be reached by the floating objective marker get a button in the Questie Tracker that points the marker at them.') end,
|
||||||
|
hidden = function() return not TrackerUtils:IsSuperTrackAvailable() end,
|
||||||
|
disabled = function() return not Questie.db.profile.trackerEnabled end,
|
||||||
|
get = function() return Questie.db.profile.trackerShowSuperTrackButton end,
|
||||||
|
set = function(_, value)
|
||||||
|
Questie.db.profile.trackerShowSuperTrackButton = value
|
||||||
|
QuestieTracker:Update()
|
||||||
|
end
|
||||||
|
},
|
||||||
|
superTrackButtonSize = {
|
||||||
|
type = "range",
|
||||||
|
order = 6,
|
||||||
|
width = 1.5,
|
||||||
|
name = function() return l10n('Objective Marker Button Size') end,
|
||||||
|
desc = function() return l10n('The size of the objective marker button shown next to each quest in the Questie Tracker.') end,
|
||||||
|
hidden = function() return not TrackerUtils:IsSuperTrackAvailable() end,
|
||||||
|
disabled = function() return (not Questie.db.profile.trackerEnabled) or (not Questie.db.profile.trackerShowSuperTrackButton) end,
|
||||||
|
min = 8,
|
||||||
|
max = 32,
|
||||||
|
step = 1,
|
||||||
|
get = function() return Questie.db.profile.trackerSuperTrackButtonSize end,
|
||||||
|
set = function(_, value)
|
||||||
|
Questie.db.profile.trackerSuperTrackButtonSize = value
|
||||||
|
QuestieTracker:Update()
|
||||||
|
end
|
||||||
|
},
|
||||||
showQuestTimer = {
|
showQuestTimer = {
|
||||||
type = "toggle",
|
type = "toggle",
|
||||||
order = 3,
|
order = 3,
|
||||||
|
|||||||
@@ -335,6 +335,10 @@ function QuestieTracker.Initialize()
|
|||||||
Questie.db.profile.trackerSetpoint = "TOPLEFT"
|
Questie.db.profile.trackerSetpoint = "TOPLEFT"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Tracks what the client considers supertracked. Permanent by design: hooksecurefunc cannot be
|
||||||
|
-- undone, and the value has to stay correct even while the Questie tracker is disabled.
|
||||||
|
TrackerUtils:InitSuperTrackHook()
|
||||||
|
|
||||||
if (not Questie.db.profile.trackerEnabled) then
|
if (not Questie.db.profile.trackerEnabled) then
|
||||||
-- The Tracker is disabled, no need to continue
|
-- The Tracker is disabled, no need to continue
|
||||||
return
|
return
|
||||||
@@ -1093,6 +1097,10 @@ function QuestieTracker:Update()
|
|||||||
-- Adds the AI_VoiceOver Play Buttons
|
-- Adds the AI_VoiceOver Play Buttons
|
||||||
line.playButton:SetPlayButton(questId)
|
line.playButton:SetPlayButton(questId)
|
||||||
|
|
||||||
|
-- Adds the button that points the floating objective marker at this quest.
|
||||||
|
-- Must run after SetPlayButton, since it anchors around the play button.
|
||||||
|
line.superTrackButton:SetSuperTrackButton(questId)
|
||||||
|
|
||||||
local usableQIB = false
|
local usableQIB = false
|
||||||
local sourceItemId = QuestieDB.QueryQuestSingle(quest.Id, "sourceItemId")
|
local sourceItemId = QuestieDB.QueryQuestSingle(quest.Id, "sourceItemId")
|
||||||
local isLiveSourceItem = false
|
local isLiveSourceItem = false
|
||||||
|
|||||||
@@ -35,6 +35,33 @@ local l10n = QuestieLoader:ImportModule("l10n")
|
|||||||
local C_Timer = QuestieCompat.C_Timer
|
local C_Timer = QuestieCompat.C_Timer
|
||||||
local C_QuestLog = QuestieCompat.C_QuestLog
|
local C_QuestLog = QuestieCompat.C_QuestLog
|
||||||
local GetQuestLogIndexByID = QuestieCompat.GetQuestLogIndexByID
|
local GetQuestLogIndexByID = QuestieCompat.GetQuestLogIndexByID
|
||||||
|
-- Copies one texture region of a quest pin onto our button. The texture file travels with the
|
||||||
|
-- coordinates because the client swaps files between states, and the region is only shown when the
|
||||||
|
-- pin itself shows it -- the pin uses "number" for in-progress quests and "turnin" for completed
|
||||||
|
-- ones, never both.
|
||||||
|
local function MirrorPinRegion(destination, source, size, pinSize)
|
||||||
|
if (not source) or (not source:IsShown()) or (not source:GetTexture()) then
|
||||||
|
destination:Hide()
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Regions are not all the size of the pin -- the "?" is drawn larger than a digit -- so scale
|
||||||
|
-- them by how the pin itself was scaled instead of stretching each one to the button.
|
||||||
|
local scale = (pinSize and pinSize > 0) and (size / pinSize) or 1
|
||||||
|
local width = (source:GetWidth() or 0) * scale
|
||||||
|
local height = (source:GetHeight() or 0) * scale
|
||||||
|
if width <= 0 or height <= 0 then
|
||||||
|
width = size
|
||||||
|
height = size
|
||||||
|
end
|
||||||
|
|
||||||
|
destination:SetWidth(width)
|
||||||
|
destination:SetHeight(height)
|
||||||
|
destination:SetTexture(source:GetTexture())
|
||||||
|
destination:SetTexCoord(source:GetTexCoord())
|
||||||
|
destination:Show()
|
||||||
|
end
|
||||||
|
|
||||||
local function GetNumLines(label)
|
local function GetNumLines(label)
|
||||||
if label.GetNumLines then
|
if label.GetNumLines then
|
||||||
return label:GetNumLines()
|
return label:GetNumLines()
|
||||||
@@ -404,6 +431,122 @@ function TrackerLinePool.Initialize(questFrame)
|
|||||||
|
|
||||||
line.playButton = playButton
|
line.playButton = playButton
|
||||||
|
|
||||||
|
-- create supertrack buttons for the Ascension floating objective marker
|
||||||
|
local superTrackButton = CreateFrame("Button", "linePool.superTrackButton" .. i, line)
|
||||||
|
superTrackButton:SetWidth(25)
|
||||||
|
superTrackButton:SetHeight(25)
|
||||||
|
superTrackButton:SetHitRectInsets(1, 1, 1, 1)
|
||||||
|
superTrackButton:SetHighlightTexture("Interface\\BUTTONS\\UI-Panel-MinimizeButton-Highlight")
|
||||||
|
|
||||||
|
-- Same texture and atlas sub-rect the client's own quest POI pins use, so the tracker button
|
||||||
|
-- reads as native rather than as an addon icon.
|
||||||
|
superTrackButton:SetNormalTexture("Interface\\WorldMap\\UI-QuestPoi-NumberIcons")
|
||||||
|
superTrackButton:GetNormalTexture():SetTexCoord(0.5, 0.625, 0.875, 1)
|
||||||
|
|
||||||
|
-- The client marks the selected pin with this glow rather than by swapping the icon, so the
|
||||||
|
-- tracker button highlights the same way the map pin does.
|
||||||
|
superTrackButton.glow = superTrackButton:CreateTexture(nil, "BACKGROUND")
|
||||||
|
superTrackButton.glow:SetTexture("Interface\\WorldMap\\UI-QuestPoi-IconGlow")
|
||||||
|
superTrackButton.glow:SetBlendMode("ADD")
|
||||||
|
superTrackButton.glow:SetPoint("CENTER", superTrackButton, "CENTER", 0, 0)
|
||||||
|
superTrackButton.glow:Hide()
|
||||||
|
|
||||||
|
-- The digit printed inside the pin is another cell of the same atlas, drawn over the icon.
|
||||||
|
superTrackButton.number = superTrackButton:CreateTexture(nil, "OVERLAY")
|
||||||
|
superTrackButton.number:SetPoint("CENTER", superTrackButton, "CENTER", 0, 0)
|
||||||
|
superTrackButton.number:Hide()
|
||||||
|
|
||||||
|
-- Completed quests draw a "?" from this separate region instead of a digit.
|
||||||
|
superTrackButton.turnin = superTrackButton:CreateTexture(nil, "OVERLAY")
|
||||||
|
superTrackButton.turnin:SetPoint("CENTER", superTrackButton, "CENTER", 0, 0)
|
||||||
|
superTrackButton.turnin:Hide()
|
||||||
|
|
||||||
|
-- The quest id is remembered even while the button is hidden. POI frames only exist once the
|
||||||
|
-- world map has built them, so a quest that looks unreachable while the tracker is drawing
|
||||||
|
-- can become reachable later -- without the id we would have nothing left to re-check.
|
||||||
|
superTrackButton.SetSuperTrackButton = function(self, questId)
|
||||||
|
self.questId = questId
|
||||||
|
self:RefreshSuperTrackButton()
|
||||||
|
end
|
||||||
|
|
||||||
|
superTrackButton.RefreshSuperTrackButton = function(self)
|
||||||
|
-- No map pin means the client has nothing to point the marker at (quest in another zone,
|
||||||
|
-- or a quest without map coordinates), so there is nothing to offer.
|
||||||
|
local pin = self.questId and TrackerUtils:GetSuperTrackPin(self.questId)
|
||||||
|
if (not pin) or (not Questie.db.profile.trackerShowSuperTrackButton) then
|
||||||
|
self:Hide()
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local buttonSize = Questie.db.profile.trackerSuperTrackButtonSize or 25
|
||||||
|
self:SetWidth(buttonSize)
|
||||||
|
self:SetHeight(buttonSize)
|
||||||
|
self.glow:SetWidth(buttonSize * 1.4)
|
||||||
|
self.glow:SetHeight(buttonSize * 1.4)
|
||||||
|
|
||||||
|
-- Mirror the pin rather than picking atlas cells ourselves, so whatever the client
|
||||||
|
-- decides to draw -- digit, "?", selected variant -- shows up here unchanged. The
|
||||||
|
-- texture file has to be copied along with the coordinates: completed quests swap in a
|
||||||
|
-- different file for these slots, and coordinates from one file applied to another
|
||||||
|
-- sample nonsense.
|
||||||
|
local pinTexture = pin.GetNormalTexture and pin:GetNormalTexture()
|
||||||
|
if pinTexture then
|
||||||
|
local ownTexture = self:GetNormalTexture()
|
||||||
|
ownTexture:SetTexture(pinTexture:GetTexture())
|
||||||
|
ownTexture:SetTexCoord(pinTexture:GetTexCoord())
|
||||||
|
end
|
||||||
|
|
||||||
|
local pinSize = pin:GetWidth()
|
||||||
|
MirrorPinRegion(self.number, pin.number, buttonSize, pinSize)
|
||||||
|
MirrorPinRegion(self.turnin, pin.turnin, buttonSize, pinSize)
|
||||||
|
|
||||||
|
-- Sit to the left of whatever already occupies the gutter: the AI_VoiceOver play button
|
||||||
|
-- when that addon is loaded, otherwise the quest collapse button.
|
||||||
|
self:ClearAllPoints()
|
||||||
|
if playButton:IsShown() then
|
||||||
|
self:SetPoint("RIGHT", playButton, "LEFT", -2, 0)
|
||||||
|
elseif line.expandQuest then
|
||||||
|
self:SetPoint("RIGHT", line.expandQuest, "LEFT", -2, 0)
|
||||||
|
else
|
||||||
|
self:SetPoint("RIGHT", line.label, "LEFT", -4, 0)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- The icon itself already shows the selected variant, copied from the pin above; the
|
||||||
|
-- glow is the one part the pin draws as a separate texture.
|
||||||
|
if TrackerUtils:GetSuperTrackedQuestId() == self.questId then
|
||||||
|
self.glow:Show()
|
||||||
|
else
|
||||||
|
self.glow:Hide()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Has to sit above the tracker backdrop, which is what swallows a frame left at level 0.
|
||||||
|
self:SetFrameLevel(line:GetFrameLevel() + 10)
|
||||||
|
self:Show()
|
||||||
|
end
|
||||||
|
|
||||||
|
superTrackButton:EnableMouse(true)
|
||||||
|
superTrackButton:RegisterForClicks("LeftButtonUp")
|
||||||
|
|
||||||
|
superTrackButton:SetScript("OnClick", function(self)
|
||||||
|
if self.questId then
|
||||||
|
TrackerUtils:SetSuperTrackedQuest(self.questId)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
superTrackButton:SetScript("OnEnter", function(self)
|
||||||
|
GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
|
||||||
|
GameTooltip:SetText(l10n("Point the objective marker at this quest"), 1, 1, 1)
|
||||||
|
GameTooltip:Show()
|
||||||
|
end)
|
||||||
|
|
||||||
|
superTrackButton:SetScript("OnLeave", function()
|
||||||
|
GameTooltip:Hide()
|
||||||
|
end)
|
||||||
|
|
||||||
|
superTrackButton:Hide()
|
||||||
|
|
||||||
|
line.superTrackButton = superTrackButton
|
||||||
|
|
||||||
-- create expanding buttons for quests with objectives
|
-- create expanding buttons for quests with objectives
|
||||||
local expandQuest = CreateFrame("Button", "linePool.expandQuest" .. i, line)
|
local expandQuest = CreateFrame("Button", "linePool.expandQuest" .. i, line)
|
||||||
expandQuest.texture = expandQuest:CreateTexture(nil, "OVERLAY", nil, 0)
|
expandQuest.texture = expandQuest:CreateTexture(nil, "OVERLAY", nil, 0)
|
||||||
@@ -731,11 +874,29 @@ function TrackerLinePool.ResetLinesForChange()
|
|||||||
line.playButton:SetAlpha(0)
|
line.playButton:SetAlpha(0)
|
||||||
line.playButton:Hide()
|
line.playButton:Hide()
|
||||||
end
|
end
|
||||||
|
if line.superTrackButton then
|
||||||
|
line.superTrackButton.questId = nil
|
||||||
|
line.superTrackButton:Hide()
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
lineIndex = 0
|
lineIndex = 0
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Re-evaluates the supertrack buttons without rebuilding the tracker. Driven by the
|
||||||
|
-- SetSuperTrackedQuestID hook, which also fires on map open/close -- that is what makes buttons
|
||||||
|
-- appear once the world map has built its POI frames, since the tracker itself does not redraw then.
|
||||||
|
function TrackerLinePool.UpdateSuperTrackButtons()
|
||||||
|
-- Rebuild the map's POI frames first so a zone change is picked up even with the map closed.
|
||||||
|
TrackerUtils:PrimeSuperTrackFrames()
|
||||||
|
|
||||||
|
for _, line in pairs(linePool) do
|
||||||
|
if line.superTrackButton and line.superTrackButton.questId then
|
||||||
|
line.superTrackButton:RefreshSuperTrackButton()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function TrackerLinePool.ResetButtonsForChange()
|
function TrackerLinePool.ResetButtonsForChange()
|
||||||
if TrackerBaseFrame.isSizing == true or TrackerBaseFrame.isMoving == true then
|
if TrackerBaseFrame.isSizing == true or TrackerBaseFrame.isMoving == true then
|
||||||
Questie:Debug(Questie.DEBUG_SPAM, "[TrackerLinePool:ResetButtonsForChange]")
|
Questie:Debug(Questie.DEBUG_SPAM, "[TrackerLinePool:ResetButtonsForChange]")
|
||||||
@@ -1098,6 +1259,12 @@ end
|
|||||||
TrackerLinePool.SetMode = function(self, mode)
|
TrackerLinePool.SetMode = function(self, mode)
|
||||||
if mode ~= self.mode then
|
if mode ~= self.mode then
|
||||||
self.mode = mode
|
self.mode = mode
|
||||||
|
-- Lines are recycled between zone headers, quest titles and objectives. Only quest title
|
||||||
|
-- lines own a supertrack button, so drop it whenever a line takes on another role.
|
||||||
|
if mode ~= "quest" and self.superTrackButton then
|
||||||
|
self.superTrackButton.questId = nil
|
||||||
|
self.superTrackButton:Hide()
|
||||||
|
end
|
||||||
if mode == "zone" then
|
if mode == "zone" then
|
||||||
local trackerFontSizeZone = Questie.db.profile.trackerFontSizeZone
|
local trackerFontSizeZone = Questie.db.profile.trackerFontSizeZone
|
||||||
self.label:SetFont((LSM30 and LSM30.Fetch and LSM30:Fetch("font", Questie.db.profile.trackerFontZone)) or Questie.db.profile.trackerFontZone, trackerFontSizeZone, Questie.db.profile.trackerFontOutline)
|
self.label:SetFont((LSM30 and LSM30.Fetch and LSM30:Fetch("font", Questie.db.profile.trackerFontZone)) or Questie.db.profile.trackerFontZone, trackerFontSizeZone, Questie.db.profile.trackerFontOutline)
|
||||||
|
|||||||
@@ -1265,6 +1265,158 @@ function TrackerUtils:GetSortedQuestIds()
|
|||||||
return sortedQuestIds, questDetails
|
return sortedQuestIds, questDetails
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Ascension's 3.3.5 client backports the retail floating objective marker ("SuperTracker").
|
||||||
|
-- Supertracking is a slave of the quest log selection: the world map and the Blizzard watch frame
|
||||||
|
-- both funnel through SelectQuestLogEntry -> SuperTrackerUtil.SetToBestSuperTrackingType. Calling
|
||||||
|
-- C_SuperTrack.SetSuperTrackedQuestID directly only moves the marker until the next map interaction
|
||||||
|
-- stomps it, so we click the same POI frames the client itself clicks.
|
||||||
|
local superTrackedQuestId
|
||||||
|
local superTrackHooked
|
||||||
|
|
||||||
|
function TrackerUtils:IsSuperTrackAvailable()
|
||||||
|
return (C_SuperTrack ~= nil) and ((WorldMapFrame_SelectQuestFrame ~= nil) or (WatchFrameQuestPOI_OnClick ~= nil))
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Every path that changes the supertracked quest ends up in SetSuperTrackedQuestID -- our own
|
||||||
|
-- button, world map pins, the map quest list, the Blizzard tracker, and the automatic re-pick that
|
||||||
|
-- happens when the map switches zone. Hooking it is the only way to know what is supertracked,
|
||||||
|
-- since this client dropped the GetSuperTrackedQuestID getter. Caching what we last set would go
|
||||||
|
-- stale the moment the player changed it by any other means.
|
||||||
|
function TrackerUtils:InitSuperTrackHook()
|
||||||
|
if superTrackHooked or (not C_SuperTrack) then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
superTrackHooked = true
|
||||||
|
|
||||||
|
hooksecurefunc(C_SuperTrack, "SetSuperTrackedQuestID", function(questId)
|
||||||
|
superTrackedQuestId = questId
|
||||||
|
TrackerLinePool.UpdateSuperTrackButtons()
|
||||||
|
end)
|
||||||
|
|
||||||
|
if C_SuperTrack.ClearSuperTracker then
|
||||||
|
hooksecurefunc(C_SuperTrack, "ClearSuperTracker", function()
|
||||||
|
superTrackedQuestId = nil
|
||||||
|
TrackerLinePool.UpdateSuperTrackButtons()
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function TrackerUtils:GetSuperTrackedQuestId()
|
||||||
|
return superTrackedQuestId
|
||||||
|
end
|
||||||
|
|
||||||
|
-- The world map builds its quest POI frames lazily, so right after login -- or after a zone change
|
||||||
|
-- with the map still closed -- there is nothing to match a quest against and every button would
|
||||||
|
-- hide itself. The client can build them without the map being shown, and doing so does not disturb
|
||||||
|
-- which quest is currently supertracked. Skipped while the map is open so we never fight the player.
|
||||||
|
function TrackerUtils:PrimeSuperTrackFrames()
|
||||||
|
if WorldMapFrame and WorldMapFrame:IsShown() then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if WorldMapFrame_UpdateQuests then
|
||||||
|
WorldMapFrame_UpdateQuests()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
---@return table|nil frame, function|nil clickHandler
|
||||||
|
local function GetSuperTrackFrame(questId)
|
||||||
|
if (not questId) or questId == 0 then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Blizzard watch frame POI buttons carry the quest id directly. Questie empties the Blizzard
|
||||||
|
-- watch list (see QuestieTracker:AQW_Insert) so only a handful of quests ever have one. Both
|
||||||
|
-- scans below stop at the first gap: these frames are created in order, so a missing index
|
||||||
|
-- means there are no further ones and this runs once per quest line per redraw.
|
||||||
|
if WatchFrameQuestPOI_OnClick then
|
||||||
|
for i = 1, 30 do
|
||||||
|
local firstInRow = _G["poiWatchFrameLines" .. i .. "_1"]
|
||||||
|
if not firstInRow then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
for j = 1, 5 do
|
||||||
|
local poiButton = (j == 1) and firstInRow or _G["poiWatchFrameLines" .. i .. "_" .. j]
|
||||||
|
if not poiButton then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
if poiButton.questId == questId then
|
||||||
|
return poiButton, WatchFrameQuestPOI_OnClick
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- World map quest frames cover every quest with a POI on the currently viewed map, which is the
|
||||||
|
-- wider net of the two. Pass the WorldMapQuestFrame itself and never its poiIcon --
|
||||||
|
-- WorldMapFrame_SelectQuestFrame indexes questFrame.poiIcon and errors on the POI frame.
|
||||||
|
if WorldMapFrame_SelectQuestFrame then
|
||||||
|
if not _G["WorldMapQuestFrame1"] then
|
||||||
|
TrackerUtils:PrimeSuperTrackFrames()
|
||||||
|
end
|
||||||
|
|
||||||
|
for i = 1, 25 do
|
||||||
|
local questFrame = _G["WorldMapQuestFrame" .. i]
|
||||||
|
if not questFrame then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
if questFrame.questId == questId then
|
||||||
|
return questFrame, WorldMapFrame_SelectQuestFrame
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- A quest can only be supertracked while it has a POI frame, so quests in another zone or without
|
||||||
|
-- map coordinates simply have no button.
|
||||||
|
function TrackerUtils:CanSuperTrackQuest(questId)
|
||||||
|
return GetSuperTrackFrame(questId) ~= nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- The map pin the client draws for this quest. Copying its texture coordinates is what keeps the
|
||||||
|
-- tracker button identical to the pin: the number, the "?" shown for completed quests and the
|
||||||
|
-- black-on-yellow selected variant all follow along without us mapping atlas cells by hand. The
|
||||||
|
-- number is also the pin's position among quests that actually have a POI, which is not the same as
|
||||||
|
-- the quest frame index -- another reason to read it from the client instead of deriving it.
|
||||||
|
---@return table|nil
|
||||||
|
function TrackerUtils:GetSuperTrackPin(questId)
|
||||||
|
if (not questId) or questId == 0 or (not WorldMapFrame_SelectQuestFrame) then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
if not _G["WorldMapQuestFrame1"] then
|
||||||
|
TrackerUtils:PrimeSuperTrackFrames()
|
||||||
|
end
|
||||||
|
|
||||||
|
for i = 1, 25 do
|
||||||
|
local questFrame = _G["WorldMapQuestFrame" .. i]
|
||||||
|
if not questFrame then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
if questFrame.questId == questId then
|
||||||
|
-- ownPOI is the pin drawn in the map's quest list, poiIcon the one on the map itself.
|
||||||
|
-- The list version is the one we mirror: it keeps the circular background on completed
|
||||||
|
-- quests, where the map version draws a bare "?".
|
||||||
|
return questFrame.ownPOI or questFrame.poiIcon
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
function TrackerUtils:SetSuperTrackedQuest(questId)
|
||||||
|
local frame, clickHandler = GetSuperTrackFrame(questId)
|
||||||
|
if not frame then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
clickHandler(frame)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
function TrackerUtils:IsVoiceOverLoaded()
|
function TrackerUtils:IsVoiceOverLoaded()
|
||||||
-- Require not just that the VoiceOver addons are loaded, but that the runtime
|
-- Require not just that the VoiceOver addons are loaded, but that the runtime
|
||||||
-- structure we index actually exists. Some VoiceOver builds (e.g. on Elune) expose
|
-- structure we index actually exists. Some VoiceOver builds (e.g. on Elune) expose
|
||||||
|
|||||||
Reference in New Issue
Block a user