581634d199
Use tracker wrapping helpers that fall back when Ascension font strings do not expose GetNumLines or GetWrappedWidth. (cherry picked from commit c9b7de2a636ca918c2549a13de87a688861c831f)
2689 lines
131 KiB
Lua
2689 lines
131 KiB
Lua
---@class QuestieTracker
|
|
local QuestieTracker = QuestieLoader:CreateModule("QuestieTracker")
|
|
-------------------------
|
|
--Import QuestieTracker modules.
|
|
-------------------------
|
|
---@type TrackerBaseFrame
|
|
local TrackerBaseFrame = QuestieLoader:ImportModule("TrackerBaseFrame")
|
|
---@type TrackerHeaderFrame
|
|
local TrackerHeaderFrame = QuestieLoader:ImportModule("TrackerHeaderFrame")
|
|
---@type TrackerQuestFrame
|
|
local TrackerQuestFrame = QuestieLoader:ImportModule("TrackerQuestFrame")
|
|
---@type TrackerLinePool
|
|
local TrackerLinePool = QuestieLoader:ImportModule("TrackerLinePool")
|
|
---@type TrackerFadeTicker
|
|
local TrackerFadeTicker = QuestieLoader:ImportModule("TrackerFadeTicker")
|
|
---@type TrackerQuestTimers
|
|
local TrackerQuestTimers = QuestieLoader:ImportModule("TrackerQuestTimers")
|
|
---@type TrackerUtils
|
|
local TrackerUtils = QuestieLoader:ImportModule("TrackerUtils")
|
|
-------------------------
|
|
--Import Questie modules.
|
|
-------------------------
|
|
---@type QuestieQuest
|
|
local QuestieQuest = QuestieLoader:ImportModule("QuestieQuest")
|
|
---@type QuestieMap
|
|
local QuestieMap = QuestieLoader:ImportModule("QuestieMap")
|
|
---@type QuestieTooltips
|
|
local QuestieTooltips = QuestieLoader:ImportModule("QuestieTooltips")
|
|
---@type QuestieLib
|
|
local QuestieLib = QuestieLoader:ImportModule("QuestieLib")
|
|
---@type QuestiePlayer
|
|
local QuestiePlayer = QuestieLoader:ImportModule("QuestiePlayer")
|
|
---@type QuestieCombatQueue
|
|
local QuestieCombatQueue = QuestieLoader:ImportModule("QuestieCombatQueue")
|
|
---@type QuestEventHandler
|
|
local QuestEventHandler = QuestieLoader:ImportModule("QuestEventHandler")
|
|
local _QuestEventHandler = QuestEventHandler.private
|
|
---@type QuestieDB
|
|
local QuestieDB = QuestieLoader:ImportModule("QuestieDB")
|
|
---@type l10n
|
|
local l10n = QuestieLoader:ImportModule("l10n")
|
|
---@type QuestieDebugOffer
|
|
local QuestieDebugOffer = QuestieLoader:ImportModule("QuestieDebugOffer")
|
|
|
|
--- COMPATIBILITY ---
|
|
local C_Timer = QuestieCompat.C_Timer
|
|
local GetQuestLogTitle = QuestieCompat.GetQuestLogTitle
|
|
local GetQuestLogIndexByID = QuestieCompat.GetQuestLogIndexByID
|
|
local GetItemInfo = QuestieCompat.GetItemInfo
|
|
local function GetNumLines(label)
|
|
if label.GetNumLines then
|
|
return label:GetNumLines()
|
|
end
|
|
|
|
return QuestieCompat.GetNumLines(label)
|
|
end
|
|
local function GetWrappedWidth(label)
|
|
if label.GetWrappedWidth then
|
|
return label:GetWrappedWidth()
|
|
end
|
|
|
|
return label:GetWidth()
|
|
end
|
|
|
|
local LSM30 = LibStub and LibStub("LibSharedMedia-3.0", true)
|
|
|
|
-- Local Vars
|
|
local trackerLineWidth = 0
|
|
local trackerMinLineWidth = 260
|
|
local trackerMarginRight = 30
|
|
local trackerMarginLeft = 14
|
|
local lastAQW = GetTime()
|
|
local lastTrackerUpdate = GetTime()
|
|
local lastAchieveId = GetTime()
|
|
local durabilityInitialPosition = { DurabilityFrame:GetPoint() }
|
|
|
|
local voiceOverInitialPosition
|
|
if VoiceOverFrame then
|
|
voiceOverInitialPosition = { VoiceOverFrame:GetPoint() }
|
|
end
|
|
|
|
local questsWatched = GetNumQuestWatches()
|
|
|
|
local trackedAchievements
|
|
local trackedAchievementIds
|
|
|
|
if Questie.IsWotlk or QuestieCompat.Is335 then
|
|
trackedAchievements = { GetTrackedAchievements() }
|
|
trackedAchievementIds = {}
|
|
end
|
|
|
|
local isFirstRun = true
|
|
local allowFormattingUpdate = false
|
|
local trackerBaseFrame, trackerHeaderFrame, trackerQuestFrame
|
|
local QuestLogFrame = QuestLogExFrame or ClassicQuestLog or QuestLogFrame
|
|
|
|
-- ============================================================
|
|
-- Ghost quest cleanup (quests that auto-complete / disappear)
|
|
-- Fixes:
|
|
-- • Tracker not updating when the quest vanishes from the quest log
|
|
-- • Warning spam: "QuestId doesn't exist in Game's quest log: <id>"
|
|
-- ============================================================
|
|
|
|
local function _RemoveQuestIdFromCharTables(questId)
|
|
if not questId then return end
|
|
local c = Questie and Questie.db and Questie.db.char
|
|
if not c then return end
|
|
|
|
if c.TrackedQuests then c.TrackedQuests[questId] = nil end
|
|
if c.AutoUntrackedQuests then c.AutoUntrackedQuests[questId] = nil end
|
|
if c.collapsedQuests then c.collapsedQuests[questId] = nil end
|
|
if c.TrackerHiddenQuests then c.TrackerHiddenQuests[questId] = nil end
|
|
if c.minAllQuestsInZone then c.minAllQuestsInZone[questId] = nil end
|
|
|
|
-- Remove hidden objectives for this quest (keys are "questId objectiveIndex")
|
|
if c.TrackerHiddenObjectives then
|
|
local prefix = tostring(questId) .. " "
|
|
for k in pairs(c.TrackerHiddenObjectives) do
|
|
if type(k) == "string" and strfind(k, prefix, 1, true) == 1 then
|
|
c.TrackerHiddenObjectives[k] = nil
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function QuestieTracker:PruneGhostQuests()
|
|
if not QuestiePlayer or type(QuestiePlayer.currentQuestlog) ~= "table" then
|
|
return false
|
|
end
|
|
|
|
local removedAny = false
|
|
-- Fix #8: Collect stale keys first, then delete AFTER the pairs() loop to
|
|
-- avoid iterator invalidation (undefined behaviour in all WoW Lua runtimes).
|
|
local toRemove = {}
|
|
|
|
for key, q in pairs(QuestiePlayer.currentQuestlog) do
|
|
local keyId = tonumber(key)
|
|
local questId = keyId or (type(q) == "table" and q.Id) or (type(q) == "number" and q) or nil
|
|
|
|
-- Normalize bad entries: sometimes the value is the questId instead of the quest table.
|
|
if questId and type(q) ~= "table" then
|
|
local quest = QuestieDB and QuestieDB.GetQuest and QuestieDB.GetQuest(questId) or nil
|
|
if quest then
|
|
-- Schedule the repair as a removal + reinsertion by key; done below.
|
|
toRemove[#toRemove + 1] = { key = key, questId = questId, quest = quest, repair = true }
|
|
q = quest
|
|
keyId = questId
|
|
end
|
|
end
|
|
|
|
if questId then
|
|
local idx = GetQuestLogIndexByID and GetQuestLogIndexByID(questId)
|
|
if (not idx) or idx <= 0 then
|
|
-- Fix #1: Guard the questId before accessing so we never generate
|
|
-- the "doesn't exist in Game's quest log" warning at all.
|
|
toRemove[#toRemove + 1] = { key = key, questId = questId, clean = true }
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Apply removals / repairs safely outside the iteration.
|
|
local i = 1
|
|
while i <= #toRemove do
|
|
local entry = toRemove[i]
|
|
if entry.repair then
|
|
if entry.key ~= entry.questId then
|
|
QuestiePlayer.currentQuestlog[entry.key] = nil
|
|
end
|
|
QuestiePlayer.currentQuestlog[entry.questId] = entry.quest
|
|
elseif entry.clean then
|
|
QuestiePlayer.currentQuestlog[entry.key] = nil
|
|
if entry.key ~= entry.questId then
|
|
QuestiePlayer.currentQuestlog[entry.questId] = nil
|
|
end
|
|
_RemoveQuestIdFromCharTables(entry.questId)
|
|
if QuestieTooltips and QuestieTooltips.RemoveQuest then
|
|
QuestieTooltips:RemoveQuest(entry.questId)
|
|
end
|
|
removedAny = true
|
|
end
|
|
i = i + 1
|
|
end
|
|
|
|
return removedAny
|
|
end
|
|
|
|
local KeybindFrame
|
|
|
|
local function _CreateSecureKeybindFrame()
|
|
if KeybindFrame then return end
|
|
|
|
KeybindFrame = CreateFrame("Button", "Questie_KeybindFrame", UIParent, "SecureActionButtonTemplate")
|
|
KeybindFrame:SetAttribute("type", "item")
|
|
KeybindFrame:RegisterForClicks("AnyDown")
|
|
KeybindFrame:Hide()
|
|
|
|
KeybindFrame:SetScript("PostClick", function(self, button)
|
|
if button == "OptionsButton" then
|
|
TrackerUtils:ToggleOptions()
|
|
elseif button == "TrackerButton" then
|
|
TrackerUtils:ToggleTracker()
|
|
elseif button == "JourneyButton" then
|
|
TrackerUtils:ToggleJourney()
|
|
end
|
|
end)
|
|
|
|
local lastProximityUpdate = 0
|
|
local function UpdateNearestQuestItemButton()
|
|
if InCombatLockdown() then return end
|
|
local now = GetTime()
|
|
if now - lastProximityUpdate > 5 then
|
|
lastProximityUpdate = now
|
|
local itemId = TrackerUtils:GetNearestQuestItemId()
|
|
if itemId then
|
|
KeybindFrame:SetAttribute("item", "item:" .. itemId)
|
|
else
|
|
KeybindFrame:SetAttribute("item", nil)
|
|
end
|
|
end
|
|
end
|
|
|
|
local f = CreateFrame("Frame")
|
|
f:RegisterEvent("PLAYER_REGEN_ENABLED")
|
|
f:SetScript("OnEvent", function()
|
|
UpdateNearestQuestItemButton()
|
|
end)
|
|
f:SetScript("OnUpdate", function()
|
|
UpdateNearestQuestItemButton()
|
|
end)
|
|
end
|
|
|
|
function QuestieTracker_UpdateQuestItemKeybind()
|
|
if not KeybindFrame then return end
|
|
|
|
if InCombatLockdown() then
|
|
return QuestieCombatQueue:Queue(QuestieTracker_UpdateQuestItemKeybind)
|
|
end
|
|
|
|
ClearOverrideBindings(KeybindFrame)
|
|
|
|
-- 1. Use Quest Item (Nearest)
|
|
local useItemKey = Questie.db.profile.useQuestItemKeybind
|
|
if useItemKey and useItemKey ~= "" then
|
|
SetOverrideBindingClick(KeybindFrame, true, useItemKey, "Questie_KeybindFrame", "LeftButton")
|
|
end
|
|
|
|
-- 2. Toggle Options
|
|
local optionsKey = Questie.db.profile.toggleOptionsKeybind
|
|
if optionsKey and optionsKey ~= "" then
|
|
SetOverrideBindingClick(KeybindFrame, true, optionsKey, "Questie_KeybindFrame", "OptionsButton")
|
|
end
|
|
|
|
-- 3. Toggle Tracker
|
|
local trackerKey = Questie.db.profile.toggleTrackerKeybind
|
|
if trackerKey and trackerKey ~= "" then
|
|
SetOverrideBindingClick(KeybindFrame, true, trackerKey, "Questie_KeybindFrame", "TrackerButton")
|
|
end
|
|
|
|
-- 4. Toggle My Journey
|
|
local journeyKey = Questie.db.profile.toggleMyJourneyKeybind
|
|
if journeyKey and journeyKey ~= "" then
|
|
SetOverrideBindingClick(KeybindFrame, true, journeyKey, "Questie_KeybindFrame", "JourneyButton")
|
|
end
|
|
end
|
|
|
|
|
|
|
|
local function _InstallQuestLogUpdateListener()
|
|
if QuestieTracker._questLogUpdateListenerInstalled then return end
|
|
|
|
local f = CreateFrame("Frame")
|
|
f:RegisterEvent("QUEST_LOG_UPDATE")
|
|
f:RegisterEvent("PLAYER_ENTERING_WORLD")
|
|
f:SetScript("OnEvent", function()
|
|
-- Queue to avoid taint/combat issues + collapse multiple updates
|
|
QuestieCombatQueue:Queue(function()
|
|
if not QuestieTracker.started then return end
|
|
QuestieTracker:PruneGhostQuests()
|
|
QuestieTracker:Update()
|
|
end)
|
|
end)
|
|
|
|
QuestieTracker._questLogUpdateListenerInstalled = true
|
|
end
|
|
|
|
-- Fix #1: _InstallMissingQuestLogWarningFilter is REMOVED.
|
|
-- The old implementation did `function Questie:Warning(...)` which is a raw
|
|
-- method replacement on the globally-registered Questie object, tainting it.
|
|
-- The warnings it suppressed are now prevented upstream in PruneGhostQuests
|
|
-- via the two-phase (collect then delete) pattern, so ghost-quest log index
|
|
-- warnings are never generated in the first place.
|
|
-- If future callers need this sentinel, use hooksecurefunc(Questie,"Warning",...)
|
|
-- which is safe on all clients that support it.
|
|
|
|
|
|
function QuestieTracker.Initialize()
|
|
if QuestieTracker.started then
|
|
-- The Tracker was already initialized, so we don't need to do it again.
|
|
return
|
|
end
|
|
|
|
-- These values might also be accessed by other modules, so we need to make sure they exist. Even when the Tracker is disabled
|
|
if (not Questie.db.char.TrackerHiddenQuests) then
|
|
Questie.db.char.TrackerHiddenQuests = {}
|
|
end
|
|
if (not Questie.db.char.TrackerHiddenObjectives) then
|
|
Questie.db.char.TrackerHiddenObjectives = {}
|
|
end
|
|
if (not Questie.db.char.TrackedQuests) then
|
|
Questie.db.char.TrackedQuests = {}
|
|
end
|
|
if (not Questie.db.char.AutoUntrackedQuests) then
|
|
Questie.db.char.AutoUntrackedQuests = {}
|
|
end
|
|
if (not Questie.db.char.collapsedZones) then
|
|
Questie.db.char.collapsedZones = {}
|
|
end
|
|
if (not Questie.db.char.minAllQuestsInZone) then
|
|
Questie.db.char.minAllQuestsInZone = {}
|
|
end
|
|
if (not Questie.db.char.collapsedQuests) then
|
|
Questie.db.char.collapsedQuests = {}
|
|
end
|
|
if (not Questie.db.char.trackedAchievementIds) then
|
|
Questie.db.char.trackedAchievementIds = {}
|
|
end
|
|
if (not Questie.db.profile.TrackerWidth) then
|
|
Questie.db.profile.TrackerWidth = 0
|
|
end
|
|
if (not Questie.db.profile.TrackerHeight) then
|
|
Questie.db.profile.TrackerHeight = 0
|
|
end
|
|
if (not Questie.db.profile.trackerSetpoint) then
|
|
Questie.db.profile.trackerSetpoint = "TOPLEFT"
|
|
end
|
|
|
|
if (not Questie.db.profile.trackerEnabled) then
|
|
-- The Tracker is disabled, no need to continue
|
|
return
|
|
end
|
|
|
|
-- Initialize tracker frames
|
|
trackerBaseFrame = TrackerBaseFrame.Initialize()
|
|
trackerHeaderFrame = TrackerHeaderFrame.Initialize(trackerBaseFrame)
|
|
trackerQuestFrame = TrackerQuestFrame.Initialize(trackerBaseFrame, trackerHeaderFrame)
|
|
|
|
-- Initialize tracker functions
|
|
TrackerLinePool.Initialize(trackerQuestFrame)
|
|
-- Keep tracker in sync for quests that auto-complete/disappear
|
|
_InstallQuestLogUpdateListener()
|
|
-- Note: _InstallMissingQuestLogWarningFilter was removed (fix #1).
|
|
-- Ghost quest warnings are now prevented upstream in PruneGhostQuests.
|
|
|
|
TrackerFadeTicker.Initialize(trackerBaseFrame, trackerHeaderFrame)
|
|
QuestieTracker.started = true
|
|
|
|
-- Initialize the secure keybind frame
|
|
_CreateSecureKeybindFrame()
|
|
QuestieTracker_UpdateQuestItemKeybind()
|
|
|
|
-- Initialize hooks
|
|
QuestieTracker:HookBaseTracker()
|
|
|
|
-- Insures all other data we're getting from other addons and WoW is loaded. There are edge
|
|
-- cases where Questie loads too fast before everything else is available.
|
|
C_Timer.After(1.0, function()
|
|
-- Hide frames during startup
|
|
if QuestieTracker.alreadyHooked then
|
|
if Questie.db.profile.stickyDurabilityFrame then DurabilityFrame:Hide() end
|
|
if TrackerUtils:IsVoiceOverLoaded() then VoiceOverFrame:Hide() end
|
|
end
|
|
|
|
-- Flip some Dugi Guides options to prevent weird behavior
|
|
if IsAddOnLoaded("DugisGuideViewerZ") then
|
|
-- Turns off "Show Quest Objectives - Display quest objectives in small/anchored frame instead of the watch frame"
|
|
DugisGuideViewer:SetDB(false, 39) -- DGV_OBJECTIVECOUNTER
|
|
|
|
-- Turns off "Auto Quest Tracking - Automatically add quest to the Objective Tracker on accept or objective update"
|
|
DugisGuideViewer:SetDB(false, 78) -- DGV_AUTO_QUEST_TRACK
|
|
|
|
-- Turns on "Clear Final Waypoint - Always clear the last waypoint on reach"
|
|
DugisGuideViewer:SetDB(true, 1006) -- DGV_CLEAR_FINAL_WAYPOINT
|
|
end
|
|
|
|
-- Quest Focus Feature
|
|
if Questie.db.char.TrackerFocus then
|
|
local focusType = type(Questie.db.char.TrackerFocus)
|
|
if focusType == "number" then
|
|
TrackerUtils:FocusQuest(Questie.db.char.TrackerFocus)
|
|
QuestieQuest:ToggleNotes(false)
|
|
elseif focusType == "string" then
|
|
local questId, objectiveIndex = string.match(Questie.db.char.TrackerFocus, "(%d+) (%d+)")
|
|
TrackerUtils:FocusObjective(questId, objectiveIndex)
|
|
QuestieQuest:ToggleNotes(false)
|
|
end
|
|
end
|
|
|
|
QuestieCombatQueue:Queue(function()
|
|
-- Hides tracker during a login or reloadUI
|
|
if Questie.db.profile.hideTrackerInDungeons and IsInInstance() then
|
|
QuestieTracker:Collapse()
|
|
end
|
|
|
|
-- Sync and populate the QuestieTracker - this should only run when a player has loaded
|
|
-- Questie for the first time or when Re-enabling the QuestieTracker after it's disabled.
|
|
|
|
-- The questsWatched variable is populated by the Unhooked GetNumQuestWatches(). If Questie
|
|
-- is enabled, this is always 0 unless it's run with a true var RE:GetNumQuestWatches(true).
|
|
if questsWatched > 0 then
|
|
-- When a quest is removed from the Watch Frame, the questIndex can change so we need to snag
|
|
-- the entire list and build a temp table with QuestIDs instead to ensure we remove them all.
|
|
local tempQuestIDs = {}
|
|
for i = 1, questsWatched do
|
|
local questIndex = GetQuestIndexForWatch(i)
|
|
if questIndex then
|
|
local questId = select(8, GetQuestLogTitle(questIndex))
|
|
if questId then
|
|
tempQuestIDs[i] = questId
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Remove quest from the Blizzard Quest Watch and populate the tracker.
|
|
for _, questId in pairs(tempQuestIDs) do
|
|
local questIndex = GetQuestLogIndexByID(questId)
|
|
if questIndex then
|
|
QuestieTracker:AQW_Insert(questIndex, QUEST_WATCH_NO_EXPIRE)
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Look for any QuestID's that don't belong in the Questie.db.char.TrackedQuests or
|
|
-- the Questie.db.char.AutoUntrackedQuests tables. They can get out of sync.
|
|
if Questie.db.profile.autoTrackQuests and Questie.db.char.AutoUntrackedQuests then
|
|
for untrackedQuestId in pairs(Questie.db.char.AutoUntrackedQuests) do
|
|
if not QuestiePlayer.currentQuestlog[untrackedQuestId] then
|
|
Questie.db.char.AutoUntrackedQuests[untrackedQuestId] = nil
|
|
end
|
|
end
|
|
elseif Questie.db.char.TrackedQuests then
|
|
for trackedQuestId in pairs(Questie.db.char.TrackedQuests) do
|
|
if not QuestiePlayer.currentQuestlog[trackedQuestId] then
|
|
Questie.db.char.TrackedQuests[trackedQuestId] = nil
|
|
end
|
|
end
|
|
end
|
|
|
|
-- The trackedAchievements variable is populated by GetTrackedAchievements(). If Questie
|
|
-- is enabled, this will always return nil so we need to save it before we enable Questie.
|
|
if Questie.IsWotlk or QuestieCompat.Is335 then
|
|
if #trackedAchievements > 0 then
|
|
local tempAchieves = trackedAchievements
|
|
|
|
-- Remove achievement from the Blizzard Quest Watch and populate the tracker.
|
|
for _, achieveId in pairs(tempAchieves) do
|
|
if achieveId then
|
|
RemoveTrackedAchievement(achieveId)
|
|
Questie.db.char.trackedAchievementIds[achieveId] = true
|
|
|
|
if (not AchievementFrame) then
|
|
AchievementFrame_LoadUI()
|
|
end
|
|
|
|
AchievementFrameAchievements_ForceUpdate()
|
|
end
|
|
end
|
|
end
|
|
|
|
trackedAchievements = { GetTrackedAchievements() }
|
|
WatchFrame_Update()
|
|
|
|
-- Sync and populate QuestieTrackers achievement cache
|
|
if Questie.db.char.trackedAchievementIds ~= trackedAchievementIds then
|
|
for achieveId in pairs(Questie.db.char.trackedAchievementIds) do
|
|
if Questie.db.char.trackedAchievementIds[achieveId] == true then
|
|
trackedAchievementIds[achieveId] = true
|
|
end
|
|
end
|
|
end
|
|
else
|
|
QuestWatch_Update()
|
|
end
|
|
|
|
if QuestLogFrame:IsShown() then QuestLog_Update() end
|
|
QuestieTracker:Update()
|
|
trackerBaseFrame:Hide()
|
|
end)
|
|
end)
|
|
end
|
|
|
|
function QuestieTracker:ResetLocation()
|
|
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieTracker:ResetLocation]")
|
|
trackerHeaderFrame.trackedQuests:SetMode(1) -- maximized
|
|
Questie.db.char.isTrackerExpanded = true
|
|
Questie.db.char.AutoUntrackedQuests = {}
|
|
Questie.db.profile.TrackerLocation = nil
|
|
Questie.db.char.collapsedQuests = {}
|
|
Questie.db.char.collapsedZones = {}
|
|
Questie.db.profile.TrackerWidth = 0
|
|
Questie.db.profile.TrackerHeight = 0
|
|
|
|
trackerBaseFrame:SetSize(25, 25)
|
|
TrackerBaseFrame:SetSafePoint()
|
|
|
|
QuestieTracker:Update()
|
|
end
|
|
|
|
function QuestieTracker:ResetDurabilityFrame()
|
|
if durabilityInitialPosition then
|
|
-- Only reset if it's been moved from it's default position set by Blizzard
|
|
if durabilityInitialPosition ~= { DurabilityFrame:GetPoint() } then
|
|
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieTracker:ResetDurabilityFrame]")
|
|
|
|
-- Resets Durability Frame back to it's default position
|
|
DurabilityFrame:ClearAllPoints()
|
|
DurabilityFrame:SetPoint(unpack(durabilityInitialPosition))
|
|
|
|
local numAlerts = 0
|
|
|
|
for i = 1, #INVENTORY_ALERT_STATUS_SLOTS do
|
|
if GetInventoryAlertStatus(i) > 0 then
|
|
numAlerts = numAlerts + 1
|
|
end
|
|
end
|
|
|
|
-- Check the alert status and reset visibility
|
|
if numAlerts > 0 then
|
|
DurabilityFrame:Show()
|
|
else
|
|
if DurabilityFrame:IsShown() then
|
|
DurabilityFrame:Hide()
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function QuestieTracker:UpdateDurabilityFrame()
|
|
if QuestieTracker.started and Questie.db.profile.trackerEnabled and Questie.db.profile.stickyDurabilityFrame then
|
|
if Questie.db.char.isTrackerExpanded and QuestieTracker:HasQuest() then
|
|
local numAlerts = 0
|
|
|
|
for i = 1, #INVENTORY_ALERT_STATUS_SLOTS do
|
|
if GetInventoryAlertStatus(i) > 0 then
|
|
numAlerts = numAlerts + 1
|
|
end
|
|
end
|
|
|
|
if numAlerts > 0 then
|
|
-- screen width accounting for scale
|
|
local screenWidth = GetScreenWidth() * UIParent:GetEffectiveScale()
|
|
-- middle of the frame, first return is x value, second return is the y value
|
|
local trackerFrameX = trackerBaseFrame:GetCenter()
|
|
|
|
DurabilityFrame:ClearAllPoints()
|
|
DurabilityFrame:SetClampedToScreen(true)
|
|
DurabilityFrame:SetFrameStrata("MEDIUM")
|
|
DurabilityFrame:SetFrameLevel(0)
|
|
|
|
if trackerFrameX <= (screenWidth / 2) then
|
|
DurabilityFrame:SetPoint("LEFT", trackerBaseFrame, "TOPRIGHT", 0, -40)
|
|
else
|
|
DurabilityFrame:SetPoint("RIGHT", trackerBaseFrame, "TOPLEFT", 0, -40)
|
|
end
|
|
|
|
DurabilityFrame:Show()
|
|
else
|
|
if DurabilityFrame:IsShown() then
|
|
DurabilityFrame:Hide()
|
|
end
|
|
end
|
|
|
|
if TrackerBaseFrame.isSizing == true or TrackerBaseFrame.isMoving == true then
|
|
Questie:Debug(Questie.DEBUG_SPAM, "[QuestieTracker:UpdateDurabilityFrame]")
|
|
else
|
|
Questie:Debug(Questie.DEBUG_INFO, "[QuestieTracker:UpdateDurabilityFrame]")
|
|
end
|
|
else
|
|
QuestieTracker:ResetDurabilityFrame()
|
|
end
|
|
end
|
|
end
|
|
|
|
function QuestieTracker:ResetVoiceOverFrame()
|
|
if voiceOverInitialPosition then
|
|
if voiceOverInitialPosition ~= { VoiceOverFrame:GetPoint() } then
|
|
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieTracker:ResetVoiceOverFrame]")
|
|
|
|
VoiceOverFrame:ClearAllPoints()
|
|
VoiceOverFrame:SetPoint(unpack(voiceOverInitialPosition))
|
|
|
|
VoiceOverFrame:SetClampedToScreen(true)
|
|
VoiceOverFrame:SetFrameStrata("MEDIUM")
|
|
VoiceOverFrame:SetFrameLevel(0)
|
|
VoiceOver.Addon.db.profile.SoundQueueUI.LockFrame = false
|
|
VoiceOver.SoundQueueUI:RefreshConfig()
|
|
|
|
if VoiceOverFrame:IsShown() then
|
|
VoiceOver.SoundQueue:RemoveAllSoundsFromQueue()
|
|
VoiceOverFrame:Hide()
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function QuestieTracker:UpdateVoiceOverFrame()
|
|
if TrackerUtils:IsVoiceOverLoaded() then
|
|
if QuestieTracker.started and Questie.db.profile.trackerEnabled and Questie.db.profile.stickyVoiceOverFrame then
|
|
if Questie.db.char.isTrackerExpanded and QuestieTracker:HasQuest() then
|
|
-- screen width accounting for scale
|
|
local screenWidth = GetScreenWidth() * UIParent:GetEffectiveScale()
|
|
-- middle of the frame, first return is x value, second return is the y value
|
|
local trackerFrameX = trackerBaseFrame:GetCenter()
|
|
|
|
VoiceOverFrame:SetClampedToScreen(true)
|
|
VoiceOverFrame:SetFrameStrata("MEDIUM")
|
|
VoiceOverFrame:SetFrameLevel(0)
|
|
|
|
local verticalOffSet
|
|
|
|
if Questie.db.profile.stickyDurabilityFrame then
|
|
if DurabilityFrame:IsVisible() then
|
|
verticalOffSet = -125
|
|
else
|
|
verticalOffSet = -7
|
|
end
|
|
end
|
|
|
|
if trackerFrameX <= (screenWidth / 2) then
|
|
VoiceOverFrame:ClearAllPoints()
|
|
VoiceOverFrame:SetPoint("TOPLEFT", trackerBaseFrame, "TOPRIGHT", 15, verticalOffSet)
|
|
else
|
|
VoiceOverFrame:ClearAllPoints()
|
|
VoiceOverFrame:SetPoint("TOPRIGHT", trackerBaseFrame, "TOPLEFT", -15, verticalOffSet)
|
|
end
|
|
|
|
VoiceOverFrame:SetWidth(500)
|
|
VoiceOverFrame:SetHeight(120)
|
|
VoiceOver.Addon.db.profile.SoundQueueUI.LockFrame = true
|
|
VoiceOver.SoundQueueUI:RefreshConfig()
|
|
VoiceOver.SoundQueueUI:UpdateSoundQueueDisplay()
|
|
|
|
if TrackerBaseFrame.isSizing == true or TrackerBaseFrame.isMoving == true then
|
|
Questie:Debug(Questie.DEBUG_SPAM, "[QuestieTracker:UpdateVoiceOverFrame]")
|
|
else
|
|
Questie:Debug(Questie.DEBUG_INFO, "[QuestieTracker:UpdateVoiceOverFrame]")
|
|
end
|
|
else
|
|
QuestieTracker:ResetVoiceOverFrame()
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- If the player loots a "Quest Item" then this triggers a Tracker Update so the
|
|
-- Quest Item Button can be switched on and appear in the tracker.
|
|
---@param text string
|
|
function QuestieTracker:QuestItemLooted(text)
|
|
local playerLoot = strmatch(text, "You receive ") or strmatch(text, "You create")
|
|
local itemId = tonumber(string.match(text, "item:(%d+)"))
|
|
|
|
if playerLoot and itemId then
|
|
local _, _, _, _, _, itemType, _, _, _, _, _, classID = GetItemInfo(itemId)
|
|
local usableItem = TrackerUtils:IsQuestItemUsable(itemId)
|
|
|
|
if (itemType == "Quest" or classID == 12 or QuestieDB.QueryItemSingle(itemId, "class") == 12) and usableItem then
|
|
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieTracker] - Quest Item Detected (itemId) - ", itemId)
|
|
|
|
C_Timer.After(0.25, function()
|
|
_QuestEventHandler:UpdateAllQuests()
|
|
Questie:Debug(Questie.DEBUG_DEVELOP,
|
|
"[QuestieTracker] - Callback --> QuestEventHandler:UpdateAllQuests()")
|
|
end)
|
|
|
|
QuestieCombatQueue:Queue(function()
|
|
C_Timer.After(0.5, function()
|
|
QuestieTracker:Update()
|
|
end)
|
|
end)
|
|
end
|
|
end
|
|
end
|
|
|
|
function QuestieTracker:HasQuest()
|
|
local hasQuest
|
|
|
|
if (GetNumQuestWatches(true) == 0) then
|
|
if Questie.IsWotlk or QuestieCompat.Is335 then
|
|
if (GetNumTrackedAchievements(true) == 0) then
|
|
hasQuest = false
|
|
else
|
|
hasQuest = true
|
|
end
|
|
else
|
|
hasQuest = false
|
|
end
|
|
else
|
|
if not Questie.db.profile.trackerShowCompleteQuests then
|
|
local completedQuests = 0
|
|
-- Keep track of the number of completed quests
|
|
for questId, quest in pairs(QuestiePlayer.currentQuestlog) do
|
|
if not quest then break end
|
|
|
|
if type(quest) ~= "table" then
|
|
quest = QuestieDB and QuestieDB.GetQuest and QuestieDB.GetQuest(questId) or nil
|
|
if quest then
|
|
QuestiePlayer.currentQuestlog[questId] = quest
|
|
end
|
|
end
|
|
|
|
if quest and quest.IsComplete and quest:IsComplete() == 1 then
|
|
completedQuests = completedQuests + 1
|
|
end
|
|
end
|
|
|
|
-- This hides the Tracker when all tracked Quests are complete
|
|
if completedQuests == GetNumQuestWatches(true) then
|
|
hasQuest = false
|
|
else
|
|
hasQuest = true
|
|
end
|
|
else
|
|
hasQuest = true
|
|
end
|
|
end
|
|
|
|
Questie:Debug(Questie.DEBUG_SPAM, "[QuestieTracker:HasQuest] - ", hasQuest)
|
|
return hasQuest
|
|
end
|
|
|
|
function QuestieTracker:Enable()
|
|
-- Update the questsWatched var before we re-enable
|
|
if questsWatched == 0 then
|
|
questsWatched = GetNumQuestWatches()
|
|
end
|
|
|
|
Questie.db.profile.trackerEnabled = true
|
|
QuestieTracker.started = false
|
|
QuestieTracker.Initialize()
|
|
ReloadUI()
|
|
end
|
|
|
|
function QuestieTracker:Disable()
|
|
Questie.db.profile.trackerEnabled = false
|
|
QuestieTracker:ResetDurabilityFrame()
|
|
QuestieTracker:ResetVoiceOverFrame()
|
|
Questie.db.char.TrackedQuests = {}
|
|
Questie.db.char.AutoUntrackedQuests = {}
|
|
|
|
if Questie.IsWotlk or QuestieCompat.Is335 then
|
|
Questie.db.char.trackedAchievementIds = {}
|
|
trackedAchievementIds = {}
|
|
end
|
|
|
|
QuestieTracker:Unhook()
|
|
QuestieTracker:Update()
|
|
ReloadUI()
|
|
end
|
|
|
|
-- Function for the Slash handler
|
|
function QuestieTracker:Toggle()
|
|
if Questie.db.profile.trackerEnabled then
|
|
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieTracker:Toggle] - Tracker Disabled.")
|
|
Questie.db.profile.trackerEnabled = false
|
|
else
|
|
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieTracker:Toggle] - Tracker Enabled.")
|
|
Questie.db.profile.trackerEnabled = true
|
|
end
|
|
QuestieTracker:Update()
|
|
end
|
|
|
|
-- Minimizes the QuestieTracker
|
|
function QuestieTracker:Collapse()
|
|
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieTracker:Collapse]")
|
|
if trackerHeaderFrame and trackerHeaderFrame.trackedQuests and Questie.db.char.isTrackerExpanded then
|
|
trackerHeaderFrame.trackedQuests:Click()
|
|
QuestieTracker:Update()
|
|
end
|
|
end
|
|
|
|
-- Maximizes the QuestieTracker
|
|
function QuestieTracker:Expand()
|
|
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieTracker:Expand]")
|
|
if trackerHeaderFrame and trackerHeaderFrame.trackedQuests and (not Questie.db.char.isTrackerExpanded) then
|
|
trackerHeaderFrame.trackedQuests:Click()
|
|
QuestieTracker:Update()
|
|
end
|
|
end
|
|
|
|
function QuestieTracker:Update()
|
|
-- Prevents calling the tracker too often, especially when the QuestieCombatQueue empties after combat ends
|
|
local now = GetTime()
|
|
if (not QuestieTracker.started) then
|
|
return
|
|
end
|
|
|
|
-- Auto-complete / vanish quests can leave ghost entries around.
|
|
-- Always prune them first to prevent stale lines + warning spam.
|
|
QuestieTracker:PruneGhostQuests()
|
|
|
|
if InCombatLockdown() or (now - lastTrackerUpdate) < 0.1 then
|
|
return
|
|
end
|
|
|
|
lastTrackerUpdate = now
|
|
|
|
-- Tracker has started but not enabled, hide the frames
|
|
if (not Questie.db.profile.trackerEnabled or QuestieTracker.disableHooks == true) then
|
|
if trackerBaseFrame and trackerBaseFrame:IsShown() then
|
|
QuestieCombatQueue:Queue(function()
|
|
if Questie.db.profile.stickyDurabilityFrame then
|
|
QuestieTracker:ResetDurabilityFrame()
|
|
end
|
|
|
|
if Questie.db.profile.stickyVoiceOverFrame then
|
|
QuestieTracker:ResetVoiceOverFrame()
|
|
end
|
|
|
|
trackerBaseFrame:Hide()
|
|
end)
|
|
end
|
|
return
|
|
end
|
|
|
|
if TrackerBaseFrame.isSizing == true or TrackerBaseFrame.isMoving == true or TrackerUtils.FilterProximityTimer == true then
|
|
Questie:Debug(Questie.DEBUG_SPAM, "[QuestieTracker:Update]")
|
|
else
|
|
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieTracker:Update]")
|
|
end
|
|
|
|
TrackerHeaderFrame:Update()
|
|
TrackerQuestFrame:Update()
|
|
TrackerBaseFrame:Update()
|
|
TrackerLinePool.ResetLinesForChange()
|
|
TrackerLinePool.ResetButtonsForChange()
|
|
|
|
-- This is needed so the Tracker can also decrease its width
|
|
trackerLineWidth = 0
|
|
|
|
-- Setup local QuestieTracker:Update vars
|
|
local trackerFontSizeZone = Questie.db.profile.trackerFontSizeZone
|
|
local trackerFontSizeQuest = Questie.db.profile.trackerFontSizeQuest
|
|
local questMarginLeft = (trackerMarginLeft + trackerMarginRight) - (18 - trackerFontSizeQuest)
|
|
local objectiveMarginLeft = questMarginLeft + trackerFontSizeQuest
|
|
local questItemButtonSize = 12 + trackerFontSizeQuest
|
|
local objectiveColor = Questie.db.profile.trackerColorObjectives
|
|
|
|
local line
|
|
|
|
local sortedQuestIds, questDetails = TrackerUtils:GetSortedQuestIds()
|
|
|
|
local firstQuestInZone = false
|
|
local zoneCheck
|
|
|
|
local primaryButton = false
|
|
local secondaryButton = false
|
|
local secondaryButtonAlpha
|
|
|
|
-- Begin populating the Tracker with Quests
|
|
local _UpdateQuests = function()
|
|
for _, questId in pairs(sortedQuestIds) do
|
|
local status, result = pcall(function()
|
|
if not questId then return "BREAK" end
|
|
|
|
local quest = questDetails[questId].quest
|
|
local complete = quest:IsComplete()
|
|
local zoneName = questDetails[questId].zoneName
|
|
local remainingSeconds = TrackerQuestTimers:GetRemainingTime(quest, nil, true)
|
|
local timedQuest = (quest.trackTimedQuest or quest.timedBlizzardQuest)
|
|
|
|
if (complete ~= 1 or Questie.db.profile.trackerShowCompleteQuests or timedQuest)
|
|
and (Questie.db.profile.autoTrackQuests and not Questie.db.char.AutoUntrackedQuests[questId])
|
|
or (not Questie.db.profile.autoTrackQuests and Questie.db.char.TrackedQuests[questId]) then
|
|
-- Add Quest Zones
|
|
if zoneCheck ~= zoneName then
|
|
firstQuestInZone = true
|
|
end
|
|
|
|
if firstQuestInZone then
|
|
-- Get first line in linePool
|
|
line = TrackerLinePool.GetNextLine()
|
|
|
|
-- Safety check - make sure we didn't run over our linePool limit.
|
|
if not line then return "BREAK" end
|
|
|
|
-- Set Line Mode, Types, Clickers
|
|
line:SetMode("zone")
|
|
line:SetZone(zoneName)
|
|
line.expandQuest:Hide()
|
|
line.criteriaMark:Hide()
|
|
line.playButton:Hide()
|
|
|
|
-- Setup Zone Label
|
|
line.label:ClearAllPoints()
|
|
line.label:SetPoint("TOPLEFT", line, "TOPLEFT", 0, 0)
|
|
|
|
-- Set Zone Title and default Min/Max states
|
|
if Questie.db.char.collapsedZones[zoneName] then
|
|
line.expandZone:SetMode(0)
|
|
line.label:SetText("|cFFC0C0C0" .. l10n(zoneName) .. " +|r")
|
|
else
|
|
line.expandZone:SetMode(1)
|
|
line.label:SetText("|cFFC0C0C0" .. l10n(zoneName) .. "|r")
|
|
end
|
|
|
|
-- Checks the minAllQuestsInZone[zone] table and if empty, zero out the table.
|
|
if Questie.db.char.minAllQuestsInZone[zoneName] ~= nil and not Questie.db.char.minAllQuestsInZone[zoneName].isTrue and not Questie.db.char.collapsedZones[zoneName] then
|
|
local minQuestIdCount = 0
|
|
for minQuestId, _ in pairs(Questie.db.char.minAllQuestsInZone[zoneName]) do
|
|
if type(minQuestId) == "number" then
|
|
minQuestIdCount = minQuestIdCount + 1
|
|
end
|
|
end
|
|
|
|
if minQuestIdCount == 0 then
|
|
Questie.db.char.minAllQuestsInZone[zoneName] = nil
|
|
end
|
|
end
|
|
|
|
-- Check and measure Zone Label text width and update tracker width
|
|
QuestieTracker:UpdateWidth(line.label:GetStringWidth() + trackerMarginLeft +
|
|
trackerMarginRight)
|
|
|
|
-- Set Zone Label and Line widths
|
|
line.label:SetWidth(trackerBaseFrame:GetWidth() - trackerMarginLeft - trackerMarginRight)
|
|
line:SetWidth(line.label:GetWidth())
|
|
|
|
-- Compare largest text Label in the tracker with current Label, then save widest width
|
|
trackerLineWidth = math.max(trackerLineWidth,
|
|
line.label:GetStringWidth() + trackerMarginLeft)
|
|
|
|
-- Setup Min/Max Button
|
|
line.expandZone:ClearAllPoints()
|
|
line.expandZone:SetPoint("TOPLEFT", line, "TOPLEFT", 0, 0)
|
|
line.expandZone:SetWidth(line.label:GetWidth())
|
|
line.expandZone:SetHeight(line.label:GetHeight())
|
|
line.expandZone:Show()
|
|
|
|
-- Adds 4 pixels between Zone and first Quest Title
|
|
line:SetHeight(line.label:GetHeight() + 4)
|
|
|
|
-- Set Zone states
|
|
line:Show()
|
|
line.label:Show()
|
|
line.Quest = nil
|
|
line.Objective = nil
|
|
firstQuestInZone = false
|
|
zoneCheck = zoneName
|
|
end
|
|
|
|
-- Add quest
|
|
if (not Questie.db.char.collapsedZones[zoneName]) then
|
|
-- Get next line in linePool
|
|
line = TrackerLinePool.GetNextLine()
|
|
|
|
-- Safety check - make sure we didn't run over our linePool limit.
|
|
if not line then return "BREAK" end
|
|
|
|
-- Set Line Mode, Types, Clickers
|
|
line:SetMode("quest")
|
|
line:SetOnClick("quest")
|
|
line:SetQuest(quest)
|
|
line:SetObjective(nil)
|
|
line.expandZone:Hide()
|
|
line.criteriaMark:Hide()
|
|
|
|
-- Set Min/Max Button and default states
|
|
line.expandQuest:SetPoint("TOPRIGHT", line, "TOPLEFT", questMarginLeft - 8, 1)
|
|
line.expandQuest.zoneId = zoneName
|
|
|
|
|
|
-- Set Completion Text
|
|
local completionText = TrackerUtils:GetCompletionText(quest)
|
|
|
|
-- Clear Blizzard Completion Text
|
|
if ((Questie.db.profile.hideBlizzardCompletionText or objectiveColor == "minimal") and not timedQuest) or complete == -1 then
|
|
completionText = nil
|
|
end
|
|
|
|
-- This removes any blank lines from Completion Text
|
|
if completionText ~= nil then
|
|
if strfind(completionText, "\r\n") then
|
|
completionText = completionText:gsub("\r\n", "")
|
|
else
|
|
completionText = completionText:gsub("(.\r?\n?)\r?\n?", "%1")
|
|
end
|
|
|
|
-- Completion Text should always be green
|
|
completionText = "|cFF4CFF4C" .. completionText
|
|
end
|
|
|
|
-- Set minimizable quest flag
|
|
local isMinimizable = (complete == 1 or (#quest.Objectives == 0 and quest.isComplete == true)) and
|
|
completionText == nil
|
|
|
|
-- Handles the collapseCompletedQuests option from the Questie Config --> Tracker options.
|
|
if Questie.db.profile.collapseCompletedQuests and isMinimizable and not timedQuest then
|
|
if not Questie.db.char.collapsedQuests[quest.Id] then
|
|
Questie.db.char.collapsedQuests[quest.Id] = true
|
|
end
|
|
else
|
|
-- The minAllQuestsInZone table is always blank until a player Shift+Clicks the Zone header (MouseDown).
|
|
-- QuestieTracker:Update is triggered and the table is then filled with all Quest ID's in the same Zone.
|
|
if Questie.db.char.minAllQuestsInZone[zoneName] ~= nil and Questie.db.char.minAllQuestsInZone[zoneName].isTrue then
|
|
Questie.db.char.minAllQuestsInZone[zoneName][quest.Id] = true
|
|
end
|
|
|
|
-- Handles all the Min/Max behavior individually for each quest.
|
|
if Questie.db.char.collapsedQuests[quest.Id] then
|
|
line.expandQuest:SetMode(0)
|
|
else
|
|
line.expandQuest:SetMode(1)
|
|
end
|
|
end
|
|
|
|
-- Setup Quest Label
|
|
line.label:ClearAllPoints()
|
|
line.label:SetPoint("TOPLEFT", line, "TOPLEFT", questMarginLeft, 0)
|
|
|
|
-- Set Quest Title - This handles the "Auto Minimize Completed Quests" option but we don't auto-minimize timed quests.
|
|
local coloredQuestName
|
|
|
|
if quest.isFallback or quest._isLogFallback then
|
|
-- Quest not in DB: use the name stored on the fallback object
|
|
local questName = quest.name or tostring(quest.Id)
|
|
if Questie.db.profile.trackerShowQuestLevel and quest.level and quest.level > 0 then
|
|
questName = "[" .. quest.level .. "] " .. questName
|
|
end
|
|
if Questie.db.profile.enableTooltipsQuestID then
|
|
questName = questName .. " (" .. quest.Id .. ")"
|
|
end
|
|
coloredQuestName = "|cFFFFFF00" .. questName .. "|r"
|
|
elseif timedQuest then
|
|
coloredQuestName = QuestieLib:GetColoredQuestName(quest.Id,
|
|
Questie.db.profile.trackerShowQuestLevel, false, false)
|
|
else
|
|
coloredQuestName = QuestieLib:GetColoredQuestName(quest.Id,
|
|
Questie.db.profile.trackerShowQuestLevel,
|
|
(Questie.db.profile.collapseCompletedQuests and isMinimizable), false)
|
|
end
|
|
|
|
line.label:SetText(coloredQuestName)
|
|
|
|
-- Check and measure Quest Label text width and update tracker width
|
|
QuestieTracker:UpdateWidth(line.label:GetStringWidth() + questMarginLeft +
|
|
trackerMarginRight)
|
|
|
|
-- Set Quest Label and Line widths
|
|
line.label:SetWidth(trackerBaseFrame:GetWidth() - questMarginLeft - trackerMarginRight)
|
|
line:SetWidth(line.label:GetWidth() + questMarginLeft)
|
|
|
|
-- Compare largest text Label in the tracker with current Label, then save widest width
|
|
trackerLineWidth = math.max(trackerLineWidth,
|
|
line.label:GetStringWidth() + questMarginLeft)
|
|
|
|
-- Adds 4 pixels between Quest Title and first Objective
|
|
line:SetHeight(line.label:GetHeight() + 4)
|
|
|
|
-- Adds the AI_VoiceOver Play Buttons
|
|
line.playButton:SetPlayButton(questId)
|
|
|
|
local usableQIB = false
|
|
local sourceItemId = QuestieDB.QueryQuestSingle(quest.Id, "sourceItemId")
|
|
local sourceItem = sourceItemId and TrackerUtils:IsQuestItemUsable(sourceItemId)
|
|
local requiredItems = quest.requiredSourceItems
|
|
local requiredItem = requiredItems and TrackerUtils:IsQuestItemUsable(requiredItems[1])
|
|
local isComplete = (quest.isComplete ~= true and #quest.Objectives == 0) or
|
|
quest.isComplete == true
|
|
|
|
-- Occasionally a quest will be in a complete state and still have a usable Quest Item. Sometimes these usable
|
|
-- items spawn an NPC that is needed to finish the quest. Or an item that teleports you to the quest finisher.
|
|
if complete == 1 and isComplete and (sourceItem or requiredItem) then
|
|
-- This shows QIB's for Quest Itmes that are needed after a quest is complete with objectives
|
|
if sourceItemId > 1 and requiredItem and sourceItemId ~= requiredItems[1] then
|
|
quest.sourceItemId = 0
|
|
usableQIB = true
|
|
end
|
|
|
|
-- This shows QIB's for Quest Items that are needed after a quest is complete without objectives
|
|
if sourceItemId > 1 and not requiredItem and quest.isComplete ~= true then
|
|
usableQIB = true
|
|
end
|
|
end
|
|
|
|
-- Adds the primary Quest Item button
|
|
if complete ~= 1 and (sourceItem or (requiredItems and #requiredItems == 1 and requiredItem)) or usableQIB then
|
|
-- Get button from buttonPool
|
|
local button = TrackerLinePool.GetNextItemButton()
|
|
if not button then return "BREAK" end -- stop populating the tracker
|
|
|
|
-- Get and save Quest Title linePool to buttonPool
|
|
button.line = line
|
|
|
|
-- Setup button and set attributes
|
|
if button:SetItem(quest, "primary", questItemButtonSize) then
|
|
local height = 0
|
|
local frame = button.line
|
|
while frame and frame ~= trackerQuestFrame do
|
|
local _, parent, _, _, yOff = frame:GetPoint()
|
|
height = height - (frame:GetHeight() - yOff)
|
|
frame = parent
|
|
end
|
|
|
|
-- If the Quest is minimized show the Expand Quest button
|
|
if Questie.db.char.collapsedQuests[quest.Id] then
|
|
if Questie.db.profile.collapseCompletedQuests and isMinimizable and not timedQuest then
|
|
button.line.expandQuest:Hide()
|
|
else
|
|
button.line.expandQuest:Show()
|
|
end
|
|
else
|
|
button.line.expandQuest:Hide()
|
|
end
|
|
|
|
-- Attach button to Quest Title linePool
|
|
button:SetPoint("TOPLEFT", button.line, "TOPLEFT", 0, 0)
|
|
button:SetParent(button.line)
|
|
button:Show()
|
|
|
|
-- Set flag to allow secondary Quest Item Buttons
|
|
primaryButton = true
|
|
|
|
-- If the Quest Zone or Quest is minimized then set UIParent and hide buttons since the buttons are normally attached to the Quest frame.
|
|
-- If buttons are left attached to the Quest frame and if the Tracker frame is hidden in combat, then it would also try and hide the
|
|
-- buttons which you can't do in combat. This helps avoid violating the Blizzard SecureActionButtonTemplate restrictions relating to combat.
|
|
if Questie.db.char.collapsedZones[zoneName] or Questie.db.char.collapsedQuests[quest.Id] then
|
|
button:SetParent(UIParent)
|
|
button:Hide()
|
|
end
|
|
else
|
|
-- Button failed to get setup for some reason or the quest item is now gone. Hide it and enable the Quest Min/Max button.
|
|
-- See previous comment for details on why we're setting this button to UIParent.
|
|
button:SetParent(UIParent)
|
|
|
|
if (Questie.db.profile.collapseCompletedQuests and isMinimizable and not timedQuest) then
|
|
line.expandQuest:Hide()
|
|
else
|
|
line.expandQuest:Show()
|
|
end
|
|
|
|
button:Hide()
|
|
end
|
|
|
|
-- Save button to linePool
|
|
line.button = button
|
|
|
|
-- Hide button if quest complete or failed
|
|
elseif (Questie.db.profile.collapseCompletedQuests and isMinimizable and not timedQuest) then
|
|
line.expandQuest:Hide()
|
|
else
|
|
line.expandQuest:Show()
|
|
end
|
|
|
|
-- Adds the Secondary Quest Item Button (only if Primary is present)
|
|
if (complete ~= 1 and primaryButton and requiredItems and #requiredItems > 1 and next(quest.Objectives)) then
|
|
if type(requiredItems) == "table" then
|
|
-- Make sure it's a "secondary" button and if a quest item is "usable".
|
|
for _, itemId in pairs(requiredItems) do
|
|
-- GetItemSpell(itemId) is a bit of a work around for not having a Blizzard API for checking an items IsUsable state.
|
|
if itemId and itemId ~= sourceItemId and QuestieDB.QueryItemSingle(itemId, "class") == 12 and TrackerUtils:IsQuestItemUsable(itemId) then
|
|
-- Get button from buttonPool
|
|
local altButton = TrackerLinePool.GetNextItemButton()
|
|
if not altButton then return "BREAK" end -- stop populating the tracker
|
|
|
|
-- Set itemID
|
|
altButton.itemID = itemId
|
|
|
|
-- Get and save Quest Title linePool to buttonPool
|
|
altButton.line = line
|
|
|
|
-- Setup button and set attributes
|
|
if altButton:SetItem(quest, "secondary", questItemButtonSize) then
|
|
local height = 0
|
|
local frame = altButton.line
|
|
|
|
while frame and frame ~= trackerQuestFrame do
|
|
local _, parent, _, _, yOff = frame:GetPoint()
|
|
height = height - (frame:GetHeight() - yOff)
|
|
frame = parent
|
|
end
|
|
|
|
if not Questie.db.char.collapsedQuests[quest.Id] and altButton:GetAlpha() > 0 then
|
|
-- Set and indent Quest Title linePool
|
|
altButton.line.label:ClearAllPoints()
|
|
altButton.line.label:SetPoint("TOPLEFT", altButton.line, "TOPLEFT",
|
|
questMarginLeft + 2 + questItemButtonSize, 0)
|
|
|
|
-- Recheck and Remeasure Quest Label text width and update tracker width
|
|
QuestieTracker:UpdateWidth(altButton.line.label:GetStringWidth() +
|
|
questMarginLeft + trackerMarginRight + questItemButtonSize)
|
|
|
|
-- Reset Quest Title Label and linePool widths
|
|
altButton.line.label:SetWidth(trackerBaseFrame:GetWidth() -
|
|
questMarginLeft - trackerMarginRight - questItemButtonSize)
|
|
altButton.line:SetWidth(altButton.line.label:GetWidth() + questMarginLeft +
|
|
questItemButtonSize)
|
|
|
|
-- Re-compare largest text Label in the tracker with Secondary Button/Quest and current Label, then save widest width
|
|
trackerLineWidth = math.max(trackerLineWidth,
|
|
altButton.line.label:GetStringWidth() + questMarginLeft +
|
|
questItemButtonSize)
|
|
elseif altButton:GetAlpha() == 0 then
|
|
-- Set Quest Title linePool
|
|
altButton.line.label:ClearAllPoints()
|
|
altButton.line.label:SetPoint("TOPLEFT", altButton.line, "TOPLEFT",
|
|
questMarginLeft, 0)
|
|
|
|
-- Recheck and Remeasure Quest Label text width and update tracker width
|
|
QuestieTracker:UpdateWidth(altButton.line.label:GetStringWidth() +
|
|
questMarginLeft + trackerMarginRight)
|
|
|
|
-- Reset Quest Title Label and linePool widths
|
|
altButton.line.label:SetWidth(trackerBaseFrame:GetWidth() -
|
|
questMarginLeft - trackerMarginRight)
|
|
altButton.line:SetWidth(altButton.line.label:GetWidth() + questMarginLeft)
|
|
|
|
-- Re-compare largest text Label in the tracker with current Label, then save widest width
|
|
trackerLineWidth = math.max(trackerLineWidth,
|
|
altButton.line.label:GetStringWidth() + questMarginLeft)
|
|
end
|
|
|
|
-- Attach button to Quest Title linePool
|
|
altButton:SetPoint("TOPLEFT", altButton.line, "TOPLEFT",
|
|
2 + questItemButtonSize, 0)
|
|
altButton:SetParent(altButton.line)
|
|
altButton:Show()
|
|
|
|
-- Set flag to shift objective lines
|
|
secondaryButton = true
|
|
secondaryButtonAlpha = altButton:GetAlpha()
|
|
|
|
-- If the Quest Zone or Quest is minimized then set UIParent and hide buttons since the buttons are normally attached to the Quest frame.
|
|
-- If buttons are left attached to the Quest frame and if the Tracker frame is hidden in combat, then it would also try and hide the
|
|
-- buttons which you can't do in combat. This helps avoid violating the Blizzard SecureActionButtonTemplate restrictions relating to combat.
|
|
if Questie.db.char.collapsedZones[zoneName] or Questie.db.char.collapsedQuests[quest.Id] then
|
|
altButton:SetParent(UIParent)
|
|
altButton:Hide()
|
|
end
|
|
else
|
|
-- See previous comment for details on why we're setting this button to UIParent.
|
|
altButton:SetParent(UIParent)
|
|
altButton:Hide()
|
|
end
|
|
|
|
-- Save button to linePool
|
|
line.altButton = altButton
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Set Secondary Quest Item Button Margins (QBC - Quest Button Check)
|
|
local lineLabelWidthQBC, lineLabelBaseFrameQBC, lineWidthQBC
|
|
if secondaryButton and secondaryButtonAlpha ~= 0 then
|
|
lineLabelWidthQBC = objectiveMarginLeft + trackerMarginRight + questItemButtonSize
|
|
lineLabelBaseFrameQBC = objectiveMarginLeft + trackerMarginRight + questItemButtonSize
|
|
lineWidthQBC = objectiveMarginLeft + questItemButtonSize
|
|
else
|
|
lineLabelWidthQBC = objectiveMarginLeft + trackerMarginRight
|
|
lineLabelBaseFrameQBC = objectiveMarginLeft + trackerMarginRight
|
|
lineWidthQBC = objectiveMarginLeft
|
|
end
|
|
|
|
-- Set Quest Line states
|
|
line:Show()
|
|
line.label:Show()
|
|
|
|
-- Add quest Objectives (if applicable)
|
|
if (not Questie.db.char.collapsedQuests[quest.Id]) then
|
|
-- Add Quest Timers (if applicable)
|
|
if timedQuest then
|
|
-- Get next line in linePool
|
|
line = TrackerLinePool.GetNextLine()
|
|
|
|
-- Safety check - make sure we didn't run over our linePool limit.
|
|
if not line then return "BREAK" end
|
|
|
|
-- Set Line Mode, Types, Clickers
|
|
line:SetMode("objective")
|
|
line:SetOnClick("quest")
|
|
line:SetQuest(quest)
|
|
line.expandZone:Hide()
|
|
line.expandQuest:Hide()
|
|
line.criteriaMark:Hide()
|
|
line.playButton:Hide()
|
|
|
|
-- Setup Timer Label
|
|
line.label:ClearAllPoints()
|
|
line.label:SetPoint("TOPLEFT", line, "TOPLEFT", lineWidthQBC, 0)
|
|
|
|
-- Set Timer font
|
|
line.label:SetFont((LSM30 and LSM30.Fetch and LSM30:Fetch("font", Questie.db.profile.trackerFontObjective)) or Questie.db.profile.trackerFontObjective,
|
|
Questie.db.profile.trackerFontSizeObjective, Questie.db.profile.trackerFontOutline)
|
|
|
|
-- Set Timer Title based on states
|
|
line.label.activeTimer = false
|
|
if quest.timedBlizzardQuest then
|
|
line.label:SetText(Questie:Colorize(l10n("Blizzard Timer Active") .. "!", "blue"))
|
|
else
|
|
local timeRemainingString, timeRemaining = TrackerQuestTimers:GetRemainingTime(quest,
|
|
line, false)
|
|
if timeRemaining then
|
|
if timeRemaining <= 1 then
|
|
line.label:SetText(Questie:Colorize("0 Seconds", "blue"))
|
|
line.label.activeTimer = false
|
|
else
|
|
line.label:SetText(Questie:Colorize(timeRemainingString, "blue"))
|
|
line.label.activeTimer = true
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Check and measure Timer text width and update tracker width
|
|
QuestieTracker:UpdateWidth(line.label:GetStringWidth() + lineLabelWidthQBC)
|
|
|
|
-- Set Timer Label and Line widthsl
|
|
line.label:SetWidth(trackerBaseFrame:GetWidth() - lineLabelBaseFrameQBC)
|
|
line:SetWidth(line.label:GetWidth() + lineWidthQBC)
|
|
|
|
-- Compare largest text Label in the tracker with current Label, then save widest width
|
|
trackerLineWidth = math.max(trackerLineWidth,
|
|
line.label:GetStringWidth() + lineWidthQBC)
|
|
|
|
-- Set Timer states
|
|
line:Show()
|
|
line.label:Show()
|
|
end
|
|
|
|
-- Add incomplete Quest Objectives
|
|
if complete == 0 and quest.isComplete ~= true then
|
|
for _, objective in pairs(quest.Objectives) do
|
|
if objective and objective.Description and (not Questie.db.profile.hideCompletedQuestObjectives or (Questie.db.profile.hideCompletedQuestObjectives and objective.Needed ~= objective.Collected)) then
|
|
-- Get next line in linePool
|
|
line = TrackerLinePool.GetNextLine()
|
|
|
|
-- Safety check - make sure we didn't run over our linePool limit.
|
|
if not line then return "BREAK" end
|
|
|
|
-- Set Line Mode, Types, Clickers
|
|
line:SetMode("objective")
|
|
line:SetOnClick("quest")
|
|
line:SetQuest(quest)
|
|
line:SetObjective(objective)
|
|
line.expandZone:Hide()
|
|
line.expandQuest:Hide()
|
|
line.criteriaMark:Hide()
|
|
line.playButton:Hide()
|
|
|
|
-- Setup Objective Label based on states.
|
|
line.label:ClearAllPoints()
|
|
line.label:SetPoint("TOPLEFT", line, "TOPLEFT", lineWidthQBC, 0)
|
|
|
|
-- Set Objective based on states
|
|
local objDesc = objective.Description:gsub("%.", "")
|
|
|
|
if (objective.Completed ~= true or (objective.Completed == true and #quest.Objectives > 1)) then
|
|
local lineEnding
|
|
lineEnding = tostring(objective.Collected) ..
|
|
"/" .. tostring(objective.Needed)
|
|
|
|
-- Set Objective text
|
|
line.label:SetText(QuestieLib:GetRGBForObjective(objective) ..
|
|
objDesc .. ": " .. lineEnding)
|
|
|
|
-- Check and measure Objective text and update tracker width
|
|
QuestieTracker:UpdateWidth(line.label:GetStringWidth() +
|
|
lineLabelWidthQBC)
|
|
|
|
-- Set Objective label and Line widths
|
|
line.label:SetWidth(trackerBaseFrame:GetWidth() - lineLabelBaseFrameQBC)
|
|
line:SetWidth(line.label:GetWidth() + lineWidthQBC)
|
|
|
|
-- Compare current text label and the largest text label in the Tracker, then save the widest width
|
|
trackerLineWidth = math.max(trackerLineWidth,
|
|
line.label:GetStringWidth() + lineWidthQBC)
|
|
|
|
-- Edge case where the quest is still flagged incomplete for single objectives and yet the objective itself is flagged complete
|
|
elseif (objective.Completed == true and completionText ~= nil and #quest.Objectives == 1) and objectiveColor ~= "minimal" then
|
|
-- Set Blizzard Completion text for single objectives
|
|
line.label:SetText(completionText)
|
|
|
|
-- If the line width is less than the minimum Tracker width then don't wrap text
|
|
if line.label:GetStringWidth() + objectiveMarginLeft < trackerMinLineWidth then
|
|
-- Check and measure Blizzard Completion text and update tracker width
|
|
QuestieTracker:UpdateWidth(line.label:GetStringWidth() +
|
|
objectiveMarginLeft + trackerMarginRight)
|
|
|
|
-- Set Blizzard Completion label and Line widths
|
|
line.label:SetWidth(trackerBaseFrame:GetWidth() - objectiveMarginLeft -
|
|
trackerMarginRight)
|
|
line:SetWidth(line.label:GetWidth() + objectiveMarginLeft)
|
|
|
|
-- Compare current text label and the largest text label in the Tracker, then save the widest width
|
|
trackerLineWidth = math.max(trackerLineWidth,
|
|
line.label:GetStringWidth() + objectiveMarginLeft)
|
|
else
|
|
-- Set Blizzard Completion Label and Line widths
|
|
line.label:SetWidth(trackerBaseFrame:GetWidth() - objectiveMarginLeft -
|
|
trackerMarginRight)
|
|
line:SetWidth(GetWrappedWidth(line.label) + objectiveMarginLeft)
|
|
|
|
-- Blizzard Completion Text tends to be rather verbose. Allow text wrapping.
|
|
line.label:SetHeight(line.label:GetStringHeight() *
|
|
GetNumLines(line.label))
|
|
line:SetHeight(line.label:GetHeight())
|
|
|
|
-- Compare trackerLineWidth, trackerMinLineWidth and the current label, then save the widest width
|
|
trackerLineWidth = math.max(trackerLineWidth, trackerMinLineWidth,
|
|
GetWrappedWidth(line.label) + objectiveMarginLeft)
|
|
end
|
|
|
|
-- Update Quest has a check for this edge case. Should reset the Quest Icons and show the Quest Finisher
|
|
QuestieQuest:UpdateQuest(quest.Id)
|
|
|
|
-- Hide the Secondary Quest Item Button
|
|
if secondaryButton and secondaryButtonAlpha ~= 0 then
|
|
line.altButton:SetParent(UIParent)
|
|
line.altButton:Hide()
|
|
end
|
|
end
|
|
|
|
-- Adds 1 pixel between multiple Objectives
|
|
line:SetHeight(line.label:GetHeight() + 1)
|
|
|
|
-- Set Objective state
|
|
line:Show()
|
|
line.label:Show()
|
|
end
|
|
end
|
|
|
|
-- Add complete/failed Quest Objectives and tag them as either complete or failed so as to always have at least one objective.
|
|
-- Some quests have "Blizzard Completion Text" that is displayed to show where to go next or where to turn in the quest.
|
|
elseif complete == 1 or complete == -1 or quest.isComplete == true then
|
|
-- Get next line in linePool
|
|
line = TrackerLinePool.GetNextLine()
|
|
|
|
-- Safety check - make sure we didn't run over our linePool limit.
|
|
if not line then return "BREAK" end
|
|
|
|
-- Set Line Mode, Types, Clickers
|
|
line:SetMode("objective")
|
|
line:SetOnClick("quest")
|
|
line:SetQuest(quest)
|
|
line.expandZone:Hide()
|
|
line.expandQuest:Hide()
|
|
line.criteriaMark:Hide()
|
|
line.playButton:Hide()
|
|
|
|
-- Setup Objective Label
|
|
line.label:ClearAllPoints()
|
|
line.label:SetPoint("TOPLEFT", line, "TOPLEFT", lineWidthQBC, 0)
|
|
|
|
-- Set Objective label based on states
|
|
if ((complete == 1 and completionText ~= nil and #quest.Objectives == 0) or (quest.isComplete == true and completionText ~= nil)) and objectiveColor ~= "minimal" then
|
|
-- Set Blizzard Completion text for single objectives
|
|
line.label:SetText(completionText)
|
|
|
|
-- If the line width is less than the minimum Tracker width then don't wrap text
|
|
if line.label:GetStringWidth() + objectiveMarginLeft < trackerMinLineWidth then
|
|
-- Check and measure Blizzard Completion text and update tracker width
|
|
QuestieTracker:UpdateWidth(line.label:GetStringWidth() +
|
|
objectiveMarginLeft + trackerMarginRight)
|
|
|
|
-- Set Blizzard Completion label and Line widths
|
|
line.label:SetWidth(trackerBaseFrame:GetWidth() - objectiveMarginLeft -
|
|
trackerMarginRight)
|
|
line:SetWidth(line.label:GetWidth() + objectiveMarginLeft)
|
|
|
|
-- Compare current text label and the largest text label in the Tracker, then save the widest width
|
|
trackerLineWidth = math.max(trackerLineWidth,
|
|
line.label:GetStringWidth() + objectiveMarginLeft)
|
|
else
|
|
-- Set Blizzard Completion Label and Line widths
|
|
line.label:SetWidth(trackerBaseFrame:GetWidth() - objectiveMarginLeft -
|
|
trackerMarginRight)
|
|
line:SetWidth(GetWrappedWidth(line.label) + objectiveMarginLeft)
|
|
|
|
-- Blizzard Completion Text tends to be rather verbose. Allow text wrapping.
|
|
line.label:SetHeight(line.label:GetStringHeight() * GetNumLines(line.label))
|
|
line:SetHeight(line.label:GetHeight())
|
|
|
|
-- Compare trackerLineWidth, trackerMinLineWidth and the current label, then save the widest width
|
|
trackerLineWidth = math.max(trackerLineWidth, trackerMinLineWidth,
|
|
GetWrappedWidth(line.label) + objectiveMarginLeft)
|
|
end
|
|
|
|
-- Hide the Secondary Quest Item Button. There are some quests with usable items after a quest is completed I
|
|
-- have yet to encounter a completed quest where both a Primary and Secondary "usable" Quest Item was needed.
|
|
if secondaryButton and secondaryButtonAlpha ~= 0 then
|
|
line.altButton:SetParent(UIParent)
|
|
line.altButton:Hide()
|
|
end
|
|
else
|
|
if complete == 1 or (#quest.Objectives == 0 and quest.isComplete == true and completionText == nil and complete ~= -1) then
|
|
line.label:SetText(Questie:Colorize(l10n("Quest Complete") .. "!", "green"))
|
|
elseif complete == -1 then
|
|
line.label:SetText(Questie:Colorize(l10n("Quest Failed") .. "!", "red"))
|
|
end
|
|
|
|
-- Check and measure Objective text width and update tracker width
|
|
QuestieTracker:UpdateWidth(line.label:GetStringWidth() + lineLabelWidthQBC)
|
|
|
|
-- Set Objective Label and Line widths
|
|
line.label:SetWidth(trackerBaseFrame:GetWidth() - lineLabelBaseFrameQBC)
|
|
line:SetWidth(line.label:GetWidth() + lineWidthQBC)
|
|
|
|
-- Compare largest text Label in the tracker with current Label, then save widest width
|
|
trackerLineWidth = math.max(trackerLineWidth,
|
|
line.label:GetStringWidth() + lineWidthQBC)
|
|
end
|
|
|
|
-- Set Objective state
|
|
line:Show()
|
|
line.label:Show()
|
|
end
|
|
end
|
|
|
|
-- Safety check in case we hit the linePool limit
|
|
if not line then
|
|
line = TrackerLinePool.GetLastLine()
|
|
end
|
|
|
|
-- Adds 2 pixels and "Padding Between Quests" setting in Tracker Options
|
|
line:SetHeight(line.label:GetHeight() + (Questie.db.profile.trackerQuestPadding + 2))
|
|
end
|
|
|
|
primaryButton = false
|
|
secondaryButton = false
|
|
end
|
|
end)
|
|
|
|
if not status then
|
|
Questie:Error("Tracker Error for quest " .. tostring(questId) .. ": " .. tostring(result))
|
|
elseif result == "BREAK" then
|
|
break
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Begin populating the tracker with achievements
|
|
local _UpdateAchievements = function()
|
|
-- Begin populating the tracker with achievements
|
|
if Questie.IsWotlk or QuestieCompat.Is335 then
|
|
-- Begin populating the tracker with tracked achievements - Note: We're limited to tracking only 10 Achievements at a time.
|
|
-- For all intents and purposes at a code level we're going to treat each tracked Achievement the same way we treat and add Quests. This loop is
|
|
-- necessary to keep separate from the above tracked Quests loop so we can place all tracked Achievements into it's own "Zone" called Achievements.
|
|
-- This will force Achievements to always appear at the bottom of the tracker. Obviously it'll show at the top if there are no quests being tracked.
|
|
local firstAchieveInZone = false
|
|
local achieveId, achieveName, achieveDescription, achieveComplete, numCriteria, zoneName, achieve
|
|
|
|
for trackedId, _ in pairs(trackedAchievementIds) do
|
|
achieveId, achieveName, _, _, _, _, _, achieveDescription, _, _, _, _, achieveComplete, _, _ =
|
|
GetAchievementInfo(trackedId)
|
|
numCriteria = GetAchievementNumCriteria(trackedId)
|
|
zoneName = "Achievements"
|
|
|
|
achieve = {
|
|
Id = achieveId,
|
|
Name = achieveName,
|
|
Description = achieveDescription
|
|
}
|
|
|
|
if achieveId and (not achieveComplete) and trackedAchievementIds[achieveId] == true then
|
|
-- Add Achievement Zone
|
|
if zoneCheck ~= zoneName then
|
|
firstAchieveInZone = true
|
|
end
|
|
|
|
if firstAchieveInZone then
|
|
-- Get first line in linePool
|
|
line = TrackerLinePool.GetNextLine()
|
|
|
|
-- Safety check - make sure we didn't run over our linePool limit.
|
|
if not line then break end
|
|
|
|
-- Set Line Mode, Types, Clickers
|
|
line:SetMode("zone")
|
|
line:SetZone(zoneName)
|
|
line.expandQuest:Hide()
|
|
line.criteriaMark:Hide()
|
|
line.playButton:Hide()
|
|
|
|
-- Setup Zone Label
|
|
line.label:ClearAllPoints()
|
|
line.label:SetPoint("TOPLEFT", line, "TOPLEFT", 0, 0)
|
|
|
|
-- Set Zone Title and Min/Max states
|
|
if Questie.db.char.collapsedZones[zoneName] then
|
|
line.expandZone:SetMode(0)
|
|
local text = zoneName == "Achievements" and l10n("Achievements") or zoneName
|
|
line.label:SetText("|cFFC0C0C0" .. text .. " +|r")
|
|
else
|
|
line.expandZone:SetMode(1)
|
|
local text = zoneName == "Achievements" and l10n("Achievements") or zoneName
|
|
line.label:SetText("|cFFC0C0C0" .. text .. ": " .. GetNumTrackedAchievements(true) .. "/10|r")
|
|
end
|
|
|
|
-- Checks the minAllQuestsInZone[zone] table and if empty, zero out the table.
|
|
if Questie.db.char.minAllQuestsInZone[zoneName] ~= nil and not Questie.db.char.minAllQuestsInZone[zoneName].isTrue and not Questie.db.char.collapsedZones[zoneName] then
|
|
local minQuestIdCount = 0
|
|
for minQuestId, _ in pairs(Questie.db.char.minAllQuestsInZone[zoneName]) do
|
|
if type(minQuestId) == "number" then
|
|
minQuestIdCount = minQuestIdCount + 1
|
|
end
|
|
end
|
|
|
|
if minQuestIdCount == 0 then
|
|
Questie.db.char.minAllQuestsInZone[zoneName] = nil
|
|
end
|
|
end
|
|
|
|
-- Check and measure Zone Label text width and update tracker width
|
|
QuestieTracker:UpdateWidth(line.label:GetStringWidth() + trackerMarginLeft +
|
|
trackerMarginRight)
|
|
|
|
-- Set Zone Label and Line widths
|
|
line.label:SetWidth(trackerBaseFrame:GetWidth() - trackerMarginLeft - trackerMarginRight)
|
|
line:SetWidth(line.label:GetWidth())
|
|
|
|
-- Compare largest text Label in the tracker with current Label, then save widest width
|
|
trackerLineWidth = math.max(trackerLineWidth,
|
|
line.label:GetStringWidth() + trackerMarginLeft)
|
|
|
|
-- Setup Min/Max Button
|
|
line.expandZone:ClearAllPoints()
|
|
line.expandZone:SetPoint("TOPLEFT", line.label, "TOPLEFT", 0, 0)
|
|
line.expandZone:SetWidth(line.label:GetWidth())
|
|
line.expandZone:SetHeight(line.label:GetHeight())
|
|
line.expandZone:Show()
|
|
|
|
-- Adds 4 pixels between Zone and first Achievement Title
|
|
line:SetHeight(line.label:GetHeight() + 4)
|
|
|
|
-- Set Zone states
|
|
line:Show()
|
|
line.label:Show()
|
|
line.Quest = nil
|
|
line.Objective = nil
|
|
firstAchieveInZone = false
|
|
zoneCheck = zoneName
|
|
end
|
|
|
|
-- Add Achievements
|
|
if (not Questie.db.char.collapsedZones[zoneName]) then
|
|
-- Get next line in linePool
|
|
line = TrackerLinePool.GetNextLine()
|
|
|
|
-- Safety check - make sure we didn't run over our linePool limit.
|
|
if not line then break end
|
|
|
|
-- Set Line Mode, Types, Clickers
|
|
line:SetMode("achieve")
|
|
line:SetOnClick("achieve")
|
|
line:SetQuest(achieve)
|
|
line:SetObjective(nil)
|
|
line.expandZone:Hide()
|
|
line.criteriaMark:Hide()
|
|
line.playButton:Hide()
|
|
|
|
-- Set Min/Max Button and default states
|
|
line.expandQuest:Show()
|
|
line.expandQuest:SetPoint("TOPRIGHT", line, "TOPLEFT", questMarginLeft - 8, 1)
|
|
line.expandQuest.zoneId = zoneName
|
|
|
|
-- The minAllQuestsInZone table is always blank until a player Shift+Clicks the Zone header (MouseDown).
|
|
-- QuestieTracker:Update is triggered and the table is then filled with all Achievement ID's in the same Zone.
|
|
if Questie.db.char.minAllQuestsInZone[zoneName] ~= nil and Questie.db.char.minAllQuestsInZone[zoneName].isTrue then
|
|
Questie.db.char.minAllQuestsInZone[zoneName][achieve.Id] = true
|
|
end
|
|
|
|
-- Handles all the Min/Max behavior individually for each Achievement.
|
|
if Questie.db.char.collapsedQuests[achieve.Id] then
|
|
line.expandQuest:SetMode(0)
|
|
else
|
|
line.expandQuest:SetMode(1)
|
|
end
|
|
|
|
-- Setup Achievement Label
|
|
line.label:ClearAllPoints()
|
|
line.label:SetPoint("TOPLEFT", line, "TOPLEFT", questMarginLeft, 0)
|
|
|
|
-- Set Achievement Title
|
|
if Questie.db.profile.enableTooltipsQuestID then
|
|
line.label:SetText("|cFFFFFF00" .. achieve.Name .. " (" .. achieve.Id .. ")|r")
|
|
else
|
|
line.label:SetText("|cFFFFFF00" .. achieve.Name .. "|r")
|
|
end
|
|
|
|
-- Check and measure Achievement Label text width and update tracker width
|
|
QuestieTracker:UpdateWidth(line.label:GetStringWidth() + questMarginLeft +
|
|
trackerMarginRight)
|
|
|
|
-- Set Achievement Label and Line widths
|
|
line.label:SetWidth(trackerBaseFrame:GetWidth() - questMarginLeft - trackerMarginRight)
|
|
line:SetWidth(line.label:GetWidth() + questMarginLeft)
|
|
|
|
-- Compare largest text Label in the tracker with current Label, then save widest width
|
|
trackerLineWidth = math.max(trackerLineWidth,
|
|
line.label:GetStringWidth() + questMarginLeft)
|
|
|
|
-- Adds 4 pixels between Achievement Title and first Objective
|
|
line:SetHeight(line.label:GetHeight() + 4)
|
|
|
|
-- Set Achievement states
|
|
line:Show()
|
|
line.label:Show()
|
|
|
|
-- Add achievement Objective (if applicable)
|
|
if (not Questie.db.char.collapsedQuests[achieve.Id]) then
|
|
-- Achievements with no number criteria
|
|
if numCriteria == 0 then
|
|
-- Get next line in linePool
|
|
line = TrackerLinePool.GetNextLine()
|
|
|
|
-- Safety check - make sure we didn't run over our linePool limit.
|
|
if not line then break end
|
|
|
|
-- Set Line Mode, Types, Clickers
|
|
line:SetMode("objective")
|
|
line:SetOnClick("achieve")
|
|
line:SetQuest(achieve)
|
|
line:SetObjective("objective")
|
|
line.expandZone:Hide()
|
|
line.expandQuest:Hide()
|
|
line.criteriaMark:Hide()
|
|
line.playButton:Hide()
|
|
|
|
-- Setup Objective Label
|
|
line.label:ClearAllPoints()
|
|
line.label:SetPoint("TOPLEFT", line, "TOPLEFT", objectiveMarginLeft, 0)
|
|
|
|
-- Set Objective text
|
|
local objDesc = achieve.Description:gsub("%.", "")
|
|
line.label:SetText(QuestieLib:GetRGBForObjective({ Collected = 0, Needed = 1 }) ..
|
|
objDesc)
|
|
|
|
-- If the line width is less than the minimum Tracker width then don't wrap text
|
|
if line.label:GetStringWidth() + objectiveMarginLeft < trackerMinLineWidth then
|
|
-- Check and measure Objective text width and update tracker width
|
|
QuestieTracker:UpdateWidth(line.label:GetStringWidth() + objectiveMarginLeft +
|
|
trackerMarginRight)
|
|
|
|
-- Set Objective Label and Line widths
|
|
line.label:SetWidth(trackerBaseFrame:GetWidth() - objectiveMarginLeft -
|
|
trackerMarginRight)
|
|
line:SetWidth(line.label:GetWidth() + objectiveMarginLeft)
|
|
|
|
-- Compare largest text Label in the tracker with current Label, then save widest width
|
|
trackerLineWidth = math.max(trackerLineWidth,
|
|
line.label:GetStringWidth() + objectiveMarginLeft)
|
|
else
|
|
-- Set Label and Line widths
|
|
line.label:SetWidth(trackerBaseFrame:GetWidth() - objectiveMarginLeft -
|
|
trackerMarginRight)
|
|
line:SetWidth(GetWrappedWidth(line.label) + objectiveMarginLeft)
|
|
|
|
-- TextWrap Objective and set height
|
|
line.label:SetHeight(line.label:GetStringHeight() * GetNumLines(line.label))
|
|
line:SetHeight(line.label:GetHeight())
|
|
|
|
-- Compare trackerLineWidth, trackerMinLineWidth and the current label, then save the widest width
|
|
trackerLineWidth = math.max(trackerLineWidth, trackerMinLineWidth,
|
|
GetWrappedWidth(line.label) + objectiveMarginLeft)
|
|
end
|
|
|
|
-- Set Objective state
|
|
line:Show()
|
|
line.label:Show()
|
|
end
|
|
|
|
-- Achievements with number criteria
|
|
for objCriteria = 1, numCriteria do
|
|
local criteriaString, _, completed, quantityProgress, quantityNeeded, _, _, refId, quantityString =
|
|
GetAchievementCriteriaInfo(achieve.Id, objCriteria)
|
|
if ((Questie.db.profile.hideCompletedAchieveObjectives) and (not completed)) or (not Questie.db.profile.hideCompletedAchieveObjectives) then
|
|
-- Get next line in linePool
|
|
line = TrackerLinePool.GetNextLine()
|
|
|
|
-- Safety check - make sure we didn't run over our linePool limit.
|
|
if not line then break end
|
|
|
|
-- Set Line Mode, Types, Clickers
|
|
line:SetMode("objective")
|
|
line:SetOnClick("achieve")
|
|
|
|
-- Set correct Objective ID. Sometimes stand alone trackable Achievements are part of a group of Achievements under a parent Achievement.
|
|
local objId
|
|
|
|
if refId and select(2, GetAchievementInfo(refId)) == criteriaString and ((GetAchievementInfo(refId) and refId ~= 0) or (refId > 0 and (not QuestieDB.GetQuest(refId)))) then
|
|
objId = refId
|
|
else
|
|
objId = achieve
|
|
end
|
|
|
|
line:SetQuest(objId)
|
|
line:SetObjective("objective")
|
|
line.expandZone:Hide()
|
|
line.expandQuest:Hide()
|
|
line.criteriaMark:Hide()
|
|
line.playButton:Hide()
|
|
|
|
-- Setup Objective Label
|
|
line.label:ClearAllPoints()
|
|
line.label:SetPoint("TOPLEFT", line, "TOPLEFT", objectiveMarginLeft, 0)
|
|
|
|
-- Set Objective label based on state
|
|
if (criteriaString == "") then
|
|
criteriaString = achieve.Description
|
|
end
|
|
|
|
local objDesc = criteriaString:gsub("%.", "")
|
|
|
|
-- Set Objectives with more than one Objective number criteria
|
|
if not (completed or quantityNeeded == 1 or quantityProgress == quantityNeeded) then
|
|
if string.find(quantityString, "|") then
|
|
quantityString = quantityString:gsub("/%s?", "/")
|
|
else
|
|
quantityString = quantityProgress .. "/" .. quantityNeeded
|
|
end
|
|
|
|
local lineEnding = tostring(quantityString)
|
|
|
|
-- Set Objective text
|
|
line.label:SetText(QuestieLib:GetRGBForObjective({
|
|
Collected = quantityProgress,
|
|
Needed =
|
|
quantityNeeded
|
|
}) .. objDesc .. ": " .. lineEnding)
|
|
|
|
-- Check and measure Objective text width and update tracker width
|
|
QuestieTracker:UpdateWidth(line.label:GetStringWidth() +
|
|
objectiveMarginLeft + trackerMarginRight)
|
|
|
|
-- Set Label width
|
|
line.label:SetWidth(trackerBaseFrame:GetWidth() - objectiveMarginLeft -
|
|
trackerMarginRight)
|
|
|
|
-- Split Objective description and Progress/Needed into seperate lines
|
|
if (trackerLineWidth < line.label:GetStringWidth() + objectiveMarginLeft) and (line.label:GetWidth() < line.label:GetStringWidth() + 5) then
|
|
-- Set Objective text
|
|
line.label:SetText(QuestieLib:GetRGBForObjective({
|
|
Collected =
|
|
quantityProgress,
|
|
Needed = quantityNeeded
|
|
}) .. objDesc .. ": ")
|
|
|
|
-- Check and measure Objective text width and update tracker width
|
|
QuestieTracker:UpdateWidth(line.label:GetStringWidth() +
|
|
objectiveMarginLeft + trackerMarginRight)
|
|
|
|
-- Set Label and Line widths
|
|
line.label:SetWidth(trackerBaseFrame:GetWidth() - objectiveMarginLeft -
|
|
trackerMarginRight)
|
|
line:SetWidth(line.label:GetWidth() + objectiveMarginLeft)
|
|
|
|
-- Compare largest text Label in the tracker with current Label, then save widest width
|
|
trackerLineWidth = math.max(trackerLineWidth,
|
|
line.label:GetStringWidth() + objectiveMarginLeft)
|
|
|
|
-- Adds 1 pixel between split Objectives
|
|
line:SetHeight(line.label:GetHeight() + 1)
|
|
|
|
-- Set Objective state
|
|
line:Show()
|
|
line.label:Show()
|
|
|
|
-- Get next line in linePool
|
|
line = TrackerLinePool.GetNextLine()
|
|
|
|
-- Safety check - make sure we didn't run over our linePool limit.
|
|
if not line then break end
|
|
|
|
-- Set Line Mode, Types, Clickers
|
|
line:SetMode("objective")
|
|
line:SetOnClick("achieve")
|
|
line:SetQuest(objId)
|
|
line:SetObjective("objective")
|
|
line.expandZone:Hide()
|
|
line.expandQuest:Hide()
|
|
line.criteriaMark:Hide()
|
|
line.playButton:Hide()
|
|
|
|
-- Set Objective Label
|
|
line.label:ClearAllPoints()
|
|
line.label:SetPoint("TOPLEFT", line, "TOPLEFT", objectiveMarginLeft, 0)
|
|
|
|
-- Set Objective text
|
|
line.label:SetText(QuestieLib:GetRGBForObjective({
|
|
Collected =
|
|
quantityProgress,
|
|
Needed = quantityNeeded
|
|
}) .. " > " .. lineEnding)
|
|
|
|
-- Check and measure Objective text width and update tracker width
|
|
QuestieTracker:UpdateWidth(line.label:GetStringWidth() +
|
|
objectiveMarginLeft + trackerMarginRight)
|
|
|
|
-- Set Label and Line widths
|
|
line.label:SetWidth(trackerBaseFrame:GetWidth() - objectiveMarginLeft -
|
|
trackerMarginRight)
|
|
line:SetWidth(line.label:GetWidth() + objectiveMarginLeft)
|
|
else
|
|
-- Set Line widths
|
|
line:SetWidth(line.label:GetWidth() + objectiveMarginLeft)
|
|
|
|
-- Compare largest text Label in the tracker with current Label, then save widest width
|
|
trackerLineWidth = math.max(trackerLineWidth,
|
|
line.label:GetStringWidth() + objectiveMarginLeft)
|
|
end
|
|
|
|
-- Set Objectives with a single Objective number criteria
|
|
else
|
|
-- Set Objective text
|
|
if completed then
|
|
line.label:SetText(QuestieLib:GetRGBForObjective({ Collected = 1, Needed = 1 }) ..
|
|
objDesc)
|
|
else
|
|
line.label:SetText(QuestieLib:GetRGBForObjective({ Collected = 0, Needed = 1 }) ..
|
|
objDesc)
|
|
end
|
|
|
|
-- Set Objective criteria mark
|
|
if not Questie.db.profile.hideCompletedAchieveObjectives and (not objectiveColor or objectiveColor == "white") then
|
|
line.criteriaMark:SetCriteria(completed)
|
|
|
|
if line.criteriaMark.mode == true then
|
|
line.criteriaMark:Show()
|
|
end
|
|
end
|
|
|
|
-- Check and measure Objective text width and update tracker width
|
|
QuestieTracker:UpdateWidth(line.label:GetStringWidth() +
|
|
objectiveMarginLeft + trackerMarginRight)
|
|
|
|
-- Set Objective Label and Line widths
|
|
line.label:SetWidth(trackerBaseFrame:GetWidth() - objectiveMarginLeft -
|
|
trackerMarginRight)
|
|
line:SetWidth(line.label:GetWidth() + objectiveMarginLeft)
|
|
|
|
-- Compare largest text Label in the tracker with current Label, then save widest width
|
|
trackerLineWidth = math.max(trackerLineWidth,
|
|
line.label:GetStringWidth() + objectiveMarginLeft)
|
|
end
|
|
|
|
-- Adds 1 pixel between multiple Objectives
|
|
line:SetHeight(line.label:GetHeight() + 1)
|
|
|
|
-- Set Objective state
|
|
line:Show()
|
|
line.label:Show()
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Safety check in case we hit the linePool limit
|
|
if not line then
|
|
line = TrackerLinePool.GetLastLine()
|
|
end
|
|
|
|
-- Adds 2 pixels and "Padding Between Quests" setting in Tracker Options
|
|
line:SetHeight(line.label:GetHeight() + (Questie.db.profile.trackerQuestPadding + 2))
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Populate Achievements first then Quests
|
|
if Questie.db.profile.listAchievementsFirst and (Questie.IsWotlk or QuestieCompat.Is335) then
|
|
_UpdateAchievements()
|
|
_UpdateQuests()
|
|
else
|
|
_UpdateQuests()
|
|
_UpdateAchievements()
|
|
end
|
|
|
|
-- Safety check in case we hit the linePool limit
|
|
if not line then
|
|
line = TrackerLinePool.GetLastLine()
|
|
end
|
|
|
|
-- Update tracker formatting
|
|
if line then
|
|
QuestieTracker:UpdateFormatting()
|
|
end
|
|
|
|
-- First run clean up
|
|
if isFirstRun then
|
|
trackerBaseFrame:Hide()
|
|
for questId, quest in pairs(QuestiePlayer.currentQuestlog) do
|
|
if quest then
|
|
if type(quest) ~= "table" then
|
|
quest = QuestieDB and QuestieDB.GetQuest and QuestieDB.GetQuest(questId) or nil
|
|
if quest then
|
|
QuestiePlayer.currentQuestlog[questId] = quest
|
|
end
|
|
end
|
|
|
|
if type(quest) == "table" then
|
|
if Questie.db.char.TrackerHiddenQuests[questId] then
|
|
quest.HideIcons = true
|
|
end
|
|
|
|
if Questie.db.char.TrackerFocus and type(Questie.db.char.TrackerFocus) == "number" and quest.Id and Questie.db.char.TrackerFocus == quest.Id then -- quest focus
|
|
TrackerUtils:FocusQuest(quest.Id)
|
|
end
|
|
|
|
if quest.Objectives then
|
|
for _, objective in pairs(quest.Objectives) do
|
|
if objective and objective.Index then
|
|
if Questie.db.char.TrackerHiddenObjectives[tostring(questId) .. " " .. tostring(objective.Index)] then
|
|
objective.HideIcons = true
|
|
end
|
|
|
|
if Questie.db.char.TrackerFocus and type(Questie.db.char.TrackerFocus) == "string" and quest.Id and Questie.db.char.TrackerFocus == tostring(quest.Id) .. " " .. tostring(objective.Index) then
|
|
TrackerUtils:FocusObjective(quest.Id, objective.Index)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
if quest.SpecialObjectives then
|
|
for _, objective in pairs(quest.SpecialObjectives) do
|
|
if objective and objective.Index then
|
|
if Questie.db.char.TrackerHiddenObjectives[tostring(questId) .. " " .. tostring(objective.Index)] then
|
|
objective.HideIcons = true
|
|
end
|
|
|
|
if Questie.db.char.TrackerFocus and type(Questie.db.char.TrackerFocus) == "string" and quest.Id and Questie.db.char.TrackerFocus == tostring(quest.Id) .. " " .. tostring(objective.Index) then
|
|
TrackerUtils:FocusObjective(quest.Id, objective.Index)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
isFirstRun = false
|
|
C_Timer.After(1.0, function()
|
|
QuestieCombatQueue:Queue(function()
|
|
allowFormattingUpdate = true
|
|
QuestieTracker:Update()
|
|
end)
|
|
end)
|
|
end
|
|
end
|
|
|
|
function QuestieTracker:UpdateFormatting()
|
|
if not allowFormattingUpdate then
|
|
return
|
|
end
|
|
|
|
if TrackerBaseFrame.isSizing == true or TrackerBaseFrame.isMoving == true or TrackerUtils.FilterProximityTimer == true then
|
|
Questie:Debug(Questie.DEBUG_SPAM, "[QuestieTracker:UpdateFormatting]")
|
|
else
|
|
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieTracker:UpdateFormatting]")
|
|
end
|
|
|
|
-- The Proximity Timer only pulses every 5 secs while running.
|
|
-- Flip back to false so we're not hiding other valid updates.
|
|
TrackerUtils.FilterProximityTimer = nil
|
|
|
|
-- Hide unused lines
|
|
TrackerLinePool.HideUnusedLines()
|
|
|
|
-- Hide unused item buttons
|
|
QuestieCombatQueue:Queue(function()
|
|
TrackerLinePool.HideUnusedButtons()
|
|
end)
|
|
|
|
-- This is responsible for handling the visibility of the Tracker
|
|
-- when nothing is tracked or when alwaysShowTracker is being used.
|
|
if (not QuestieTracker:HasQuest()) then
|
|
if Questie.db.profile.alwaysShowTracker then
|
|
trackerBaseFrame:Show()
|
|
else
|
|
trackerBaseFrame:Hide()
|
|
end
|
|
else
|
|
trackerBaseFrame:Show()
|
|
end
|
|
|
|
TrackerHeaderFrame:Update()
|
|
|
|
if TrackerLinePool.GetCurrentLine() and trackerLineWidth > 1 then
|
|
local trackerVarsCombined = trackerLineWidth + trackerMarginRight
|
|
TrackerLinePool.UpdateWrappedLineWidths(trackerLineWidth)
|
|
QuestieTracker:UpdateWidth(trackerVarsCombined)
|
|
QuestieTracker:UpdateHeight()
|
|
TrackerQuestFrame:Update()
|
|
end
|
|
|
|
TrackerBaseFrame:Update()
|
|
|
|
if Questie.db.profile.trackerHeaderEnabled or (Questie.db.profile.alwaysShowTracker and not QuestieTracker:HasQuest()) then
|
|
QuestieCompat.SetResizeBounds(trackerBaseFrame,
|
|
trackerHeaderFrame:GetWidth() + Questie.db.profile.trackerFontSizeHeader + 10,
|
|
trackerHeaderFrame:GetHeight() + Questie.db.profile.trackerFontSizeZone + 23)
|
|
else
|
|
QuestieCompat.SetResizeBounds(trackerBaseFrame,
|
|
(TrackerLinePool.GetFirstLine().label:GetStringWidth() + 40),
|
|
Questie.db.profile.trackerFontSizeZone + 22)
|
|
end
|
|
|
|
TrackerUtils:ShowVoiceOverPlayButtons()
|
|
TrackerUtils:UpdateVoiceOverPlayButtons()
|
|
end
|
|
|
|
function QuestieTracker:UpdateWidth(trackerVarsCombined)
|
|
local trackerWidthByManual = Questie.db.profile.TrackerWidth
|
|
local trackerHeaderFrameWidth = (trackerHeaderFrame:GetWidth() + Questie.db.profile.trackerFontSizeHeader + 10)
|
|
local trackerHeaderlessWidth = (TrackerLinePool.GetFirstLine().label:GetStringWidth() + 30)
|
|
|
|
if Questie.db.char.isTrackerExpanded then
|
|
if trackerWidthByManual > 0 then
|
|
-- Tracker Sizer is in Manual Mode
|
|
if (not TrackerBaseFrame.isSizing) then
|
|
-- Tracker is not being Sized | Manual width based on the width set by the Tracker Sizer
|
|
if trackerWidthByManual < trackerHeaderFrameWidth and (Questie.db.profile.trackerHeaderEnabled or (Questie.db.profile.alwaysShowTracker and not QuestieTracker:HasQuest())) then
|
|
trackerBaseFrame:SetWidth(trackerHeaderFrameWidth)
|
|
elseif trackerWidthByManual < trackerHeaderlessWidth then
|
|
trackerBaseFrame:SetWidth(trackerHeaderlessWidth)
|
|
else
|
|
trackerBaseFrame:SetWidth(trackerWidthByManual)
|
|
end
|
|
else
|
|
-- Tracker is being Sized | This will update the Tracker width while the Sizer is being used
|
|
trackerBaseFrame:SetWidth(trackerWidthByManual)
|
|
end
|
|
else
|
|
-- Tracker Sizer is in Auto Mode
|
|
if (trackerVarsCombined < trackerHeaderFrameWidth and (Questie.db.profile.trackerHeaderEnabled or (Questie.db.profile.alwaysShowTracker and not QuestieTracker:HasQuest()))) then
|
|
-- Apply headerFrameWidth
|
|
trackerBaseFrame:SetWidth(trackerHeaderFrameWidth)
|
|
else
|
|
-- Apply trackerVarsCombined width based on the maximum size of the largest line in the Tracker
|
|
trackerBaseFrame:SetWidth(trackerVarsCombined)
|
|
end
|
|
end
|
|
|
|
trackerQuestFrame:SetWidth(trackerBaseFrame:GetWidth())
|
|
trackerQuestFrame.ScrollChildFrame:SetWidth(trackerBaseFrame:GetWidth())
|
|
else
|
|
if Questie.db.profile.trackerHeaderEnabled or (Questie.db.profile.alwaysShowTracker and not QuestieTracker:HasQuest()) then
|
|
trackerBaseFrame:SetWidth(trackerHeaderFrameWidth)
|
|
trackerQuestFrame:SetWidth(trackerHeaderFrameWidth)
|
|
trackerQuestFrame.ScrollChildFrame:SetWidth(trackerHeaderFrameWidth)
|
|
end
|
|
end
|
|
end
|
|
|
|
function QuestieTracker:UpdateHeight()
|
|
local trackerHeaderFrameHeight = trackerHeaderFrame:GetHeight() + Questie.db.profile.trackerFontSizeZone + 23
|
|
local trackerHeightByRatio = GetScreenHeight() * Questie.db.profile.trackerHeightRatio
|
|
local trackerHeightByManual = Questie.db.profile.TrackerHeight
|
|
local trackerHeightCheck = trackerHeightByManual > 0 and trackerHeightByManual or trackerHeightByRatio
|
|
local trackerHeaderlessHeight = Questie.db.profile.trackerFontSizeZone + 22
|
|
|
|
if Questie.db.char.isTrackerExpanded then
|
|
-- Removes any padding from the last line in the tracker
|
|
TrackerLinePool.GetCurrentLine():SetHeight(TrackerLinePool.GetCurrentLine().label:GetStringHeight())
|
|
|
|
if TrackerLinePool.GetCurrentLine().mode == "zone" then
|
|
-- If a single zone is the only line in the tracker then don't add pixel padding
|
|
trackerQuestFrame.ScrollChildFrame:SetHeight((TrackerLinePool.GetFirstLine():GetTop() - TrackerLinePool.GetCurrentLine():GetBottom()))
|
|
else
|
|
-- Add 3 pixels to bottom of tracker to account for text that traverses beyond the GetStringHeight() function such as lower case "g".
|
|
trackerQuestFrame.ScrollChildFrame:SetHeight((TrackerLinePool.GetFirstLine():GetTop() - TrackerLinePool.GetCurrentLine():GetBottom() + 3))
|
|
end
|
|
|
|
-- Set the baseFrame to full height so we can measure it
|
|
trackerQuestFrame:SetHeight(trackerQuestFrame.ScrollChildFrame:GetHeight())
|
|
|
|
if Questie.db.profile.trackerHeaderEnabled or (Questie.db.profile.alwaysShowTracker and not QuestieTracker:HasQuest()) then
|
|
trackerBaseFrame:SetHeight(trackerQuestFrame:GetHeight() + trackerHeaderFrame:GetHeight() + 20)
|
|
else
|
|
trackerBaseFrame:SetHeight(trackerQuestFrame:GetHeight() + 20)
|
|
end
|
|
|
|
-- Use trackerHeightCheck (Sizer Manual or Auto) and set the heights
|
|
if (not TrackerBaseFrame.isSizing) then
|
|
-- Tracker is not being re-sized
|
|
if trackerBaseFrame:GetHeight() > trackerHeightCheck then
|
|
if trackerHeightCheck < trackerHeaderFrameHeight + 10 and (Questie.db.profile.trackerHeaderEnabled or (Questie.db.profile.alwaysShowTracker and not QuestieTracker:HasQuest())) then
|
|
trackerBaseFrame:SetHeight(trackerHeaderFrameHeight)
|
|
elseif trackerHeightCheck < trackerHeaderlessHeight then
|
|
trackerBaseFrame:SetHeight(trackerHeaderlessHeight)
|
|
else
|
|
trackerBaseFrame:SetHeight(trackerHeightCheck)
|
|
end
|
|
end
|
|
else
|
|
trackerBaseFrame:SetHeight(trackerHeightCheck)
|
|
end
|
|
|
|
-- Resize the questFrame to match the baseFrame after the trackerHeightCheck is applied
|
|
if Questie.db.profile.trackerHeaderEnabled or (Questie.db.profile.alwaysShowTracker and not QuestieTracker:HasQuest()) then
|
|
-- With Header Frame
|
|
trackerQuestFrame:SetHeight(trackerBaseFrame:GetHeight() - trackerHeaderFrame:GetHeight() - 20)
|
|
else
|
|
-- Without Header Frame
|
|
trackerQuestFrame:SetHeight(trackerBaseFrame:GetHeight() - 20)
|
|
end
|
|
else
|
|
trackerBaseFrame:SetHeight(trackerHeaderFrameHeight - 20)
|
|
trackerQuestFrame:SetHeight(trackerHeaderFrameHeight - 20)
|
|
trackerQuestFrame.ScrollChildFrame:SetHeight(trackerHeaderFrameHeight - 20)
|
|
end
|
|
end
|
|
|
|
function QuestieTracker:Unhook()
|
|
if (not QuestieTracker.alreadyHooked) then
|
|
return
|
|
end
|
|
|
|
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieTracker:Unhook]")
|
|
|
|
QuestieTracker.disableHooks = true
|
|
|
|
TrackerQuestTimers:ShowBlizzardTimer()
|
|
|
|
-- Quest Hooks
|
|
if QuestieTracker.IsQuestWatched then
|
|
IsQuestWatched = QuestieTracker.IsQuestWatched
|
|
GetNumQuestWatches = QuestieTracker.GetNumQuestWatches
|
|
end
|
|
|
|
-- Achievement Hooks
|
|
if Questie.IsWotlk or QuestieCompat.Is335 then
|
|
if QuestieTracker.IsTrackedAchievement then
|
|
IsTrackedAchievement = QuestieTracker.IsTrackedAchievement
|
|
GetNumTrackedAchievements = QuestieTracker.GetNumTrackedAchievements
|
|
end
|
|
end
|
|
|
|
QuestieTracker.alreadyHooked = nil
|
|
end
|
|
|
|
function QuestieTracker:HookBaseTracker()
|
|
if QuestieTracker.alreadyHooked then
|
|
return
|
|
end
|
|
|
|
QuestieTracker.disableHooks = nil
|
|
|
|
if not QuestieTracker.alreadyHookedSecure then
|
|
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieTracker:HookBaseTracker] - Secure hooks")
|
|
|
|
-- Durability Frame hook
|
|
hooksecurefunc("UIParent_ManageFramePositions", QuestieTracker.UpdateDurabilityFrame)
|
|
|
|
-- QuestWatch secure hook
|
|
if AutoQuestWatch_Insert then
|
|
hooksecurefunc("AutoQuestWatch_Insert",
|
|
function(index, watchTimer) QuestieTracker:AQW_Insert(index, watchTimer) end)
|
|
end
|
|
|
|
hooksecurefunc("AddQuestWatch", function(index, watchTimer) QuestieTracker:AQW_Insert(index, watchTimer) end)
|
|
hooksecurefunc("RemoveQuestWatch", QuestieTracker.RemoveQuestWatch)
|
|
|
|
-- Achievement secure hooks
|
|
if Questie.IsWotlk or QuestieCompat.Is335 then
|
|
hooksecurefunc("AddTrackedAchievement", function(achieveId) QuestieTracker:TrackAchieve(achieveId) end)
|
|
hooksecurefunc("RemoveTrackedAchievement", QuestieTracker.RemoveTrackedAchievement)
|
|
end
|
|
|
|
QuestieTracker.alreadyHookedSecure = true
|
|
end
|
|
|
|
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieTracker:HookBaseTracker] - Non-secure hooks")
|
|
|
|
-- Quest Hooks
|
|
if not QuestieTracker.IsQuestWatched then
|
|
QuestieTracker.IsQuestWatched = IsQuestWatched
|
|
QuestieTracker.GetNumQuestWatches = GetNumQuestWatches
|
|
end
|
|
|
|
-- Intercept and return a Questie boolean value
|
|
IsQuestWatched = function(index)
|
|
local questId = select(8, GetQuestLogTitle(index))
|
|
if questId == 0 then
|
|
-- When an objective progresses in TBC "index" is the questId, but when a quest is manually added to the quest watch
|
|
-- (e.g. shift clicking it in the quest log) "index" is the questLogIndex.
|
|
questId = index
|
|
end
|
|
|
|
if not Questie.db.profile.autoTrackQuests then
|
|
return questId and Questie.db.char.TrackedQuests[questId]
|
|
else
|
|
return questId and QuestiePlayer.currentQuestlog[questId] and (not Questie.db.char.AutoUntrackedQuests[questId])
|
|
end
|
|
end
|
|
|
|
-- Intercept and return only what Questie is tracking
|
|
GetNumQuestWatches = function(isQuestie)
|
|
local activeQuests = 0
|
|
if isQuestie and Questie.db.profile.autoTrackQuests and Questie.db.char.AutoUntrackedQuests then
|
|
local autoUnTrackedQuests = 0
|
|
for _ in pairs(Questie.db.char.AutoUntrackedQuests) do
|
|
autoUnTrackedQuests = autoUnTrackedQuests + 1
|
|
end
|
|
return select(2, GetNumQuestLogEntries()) - autoUnTrackedQuests
|
|
elseif isQuestie and Questie.db.char.TrackedQuests then
|
|
local autoTrackedQuests = 0
|
|
for _ in pairs(Questie.db.char.TrackedQuests) do
|
|
autoTrackedQuests = autoTrackedQuests + 1
|
|
end
|
|
return autoTrackedQuests
|
|
else
|
|
return 0
|
|
end
|
|
end
|
|
|
|
-- Achievement Hooks
|
|
if Questie.IsWotlk or QuestieCompat.Is335 then
|
|
if not QuestieTracker.IsTrackedAchievement then
|
|
QuestieTracker.IsTrackedAchievement = IsTrackedAchievement
|
|
QuestieTracker.GetNumTrackedAchievements = GetNumTrackedAchievements
|
|
end
|
|
|
|
-- Intercept and return a Questie boolean value
|
|
IsTrackedAchievement = function(achieveId)
|
|
if Questie.db.char.trackedAchievementIds[achieveId] then
|
|
return achieveId and Questie.db.char.trackedAchievementIds[achieveId]
|
|
else
|
|
return false
|
|
end
|
|
end
|
|
|
|
-- Intercept and return only what Questie is tracking
|
|
GetNumTrackedAchievements = function(isQuestie)
|
|
if isQuestie and Questie.db.char.trackedAchievementIds then
|
|
local numTrackedAchievements = 0
|
|
for _ in pairs(Questie.db.char.trackedAchievementIds) do
|
|
numTrackedAchievements = numTrackedAchievements + 1
|
|
end
|
|
return numTrackedAchievements
|
|
else
|
|
return 0
|
|
end
|
|
end
|
|
end
|
|
|
|
if Questie.db.profile.showBlizzardQuestTimer then
|
|
TrackerQuestTimers:ShowBlizzardTimer()
|
|
else
|
|
TrackerQuestTimers:HideBlizzardTimer()
|
|
end
|
|
|
|
QuestieTracker.alreadyHooked = true
|
|
QuestieCombatQueue:Queue(function()
|
|
QuestieTracker:Update()
|
|
end)
|
|
end
|
|
|
|
function QuestieTracker:RemoveQuest(questId)
|
|
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieTracker:RemoveQuest] - ", questId)
|
|
-- Clean up any fallback quest object we built for this quest
|
|
if TrackerUtils._fallbackQuests then
|
|
TrackerUtils._fallbackQuests[questId] = nil
|
|
end
|
|
if Questie.db.char.collapsedQuests then
|
|
Questie.db.char.collapsedQuests[questId] = nil
|
|
end
|
|
|
|
-- Let's remove the Quest from the Tracker tables just in case...
|
|
if Questie.db.char.AutoUntrackedQuests[questId] then
|
|
Questie.db.char.AutoUntrackedQuests[questId] = nil
|
|
elseif Questie.db.char.TrackedQuests[questId] then
|
|
Questie.db.char.TrackedQuests[questId] = nil
|
|
end
|
|
|
|
if Questie.db.char.TrackerFocus then
|
|
if (type(Questie.db.char.TrackerFocus) == "number" and Questie.db.char.TrackerFocus == questId)
|
|
or (type(Questie.db.char.TrackerFocus) == "string" and Questie.db.char.TrackerFocus:sub(1, #tostring(questId)) == tostring(questId)) then
|
|
TrackerUtils:UnFocus()
|
|
QuestieQuest:ToggleNotes(true)
|
|
end
|
|
end
|
|
end
|
|
|
|
function QuestieTracker.RemoveQuestWatch(index, isQuestie)
|
|
if QuestieTracker.disableHooks then
|
|
return
|
|
end
|
|
|
|
if not isQuestie then
|
|
if index then
|
|
local _, _, _, isHeader, _, _, _, questId = GetQuestLogTitle(index)
|
|
|
|
if isHeader then
|
|
return
|
|
end
|
|
|
|
if (not questId) or questId == 0 then
|
|
-- Maybe index was already a questId (Ascension/Ebonhold extension)
|
|
if index > 0 and (GetQuestLogIndexByID and GetQuestLogIndexByID(index) > 0) then
|
|
questId = index
|
|
else
|
|
return
|
|
end
|
|
end
|
|
|
|
if questId and questId > 0 then
|
|
local stack = debugstack(2, 5, 0)
|
|
local isUserAction = stack:find("QuestLog") or stack:find("OnClick") or stack:find("QuestWatch") or stack:find("TrackerLinePool") or stack:find("TrackerMenu") or IsShiftKeyDown()
|
|
|
|
if not isUserAction then
|
|
-- Internal update: Only untrack if we are NOT in auto-track mode
|
|
if not Questie.db.profile.autoTrackQuests then
|
|
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieTracker.RemoveQuestWatch] - Internal update (untrack):", questId)
|
|
QuestieTracker:UntrackQuestId(questId)
|
|
end
|
|
else
|
|
-- User triggered untrack: Explicitly follow it.
|
|
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieTracker.RemoveQuestWatch] - User action (untrack):", questId)
|
|
QuestieTracker:UntrackQuestId(questId)
|
|
end
|
|
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieTracker.RemoveQuestWatch] - by Blizzard", questId)
|
|
end
|
|
end
|
|
else
|
|
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieTracker.RemoveQuestWatch] - by Questie")
|
|
end
|
|
end
|
|
|
|
function QuestieTracker:UntrackQuestId(questId)
|
|
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieTracker:UntrackQuestId] - ", questId)
|
|
if Questie.db.profile.autoTrackQuests then
|
|
-- In auto-track mode, mark the quest as explicitly hidden
|
|
Questie.db.char.AutoUntrackedQuests[questId] = true
|
|
Questie.db.char.TrackedQuests[questId] = nil
|
|
else
|
|
-- In manual-track mode, remove from tracked list
|
|
Questie.db.char.TrackedQuests[questId] = nil
|
|
Questie.db.char.AutoUntrackedQuests[questId] = nil
|
|
end
|
|
|
|
if Questie.db.profile.hideUntrackedQuestsMapIcons then
|
|
-- Hides objective icons for untracked quests.
|
|
QuestieQuest:ToggleNotes(false)
|
|
|
|
-- Removes objective tooltips for untracked quests.
|
|
QuestieTooltips:RemoveQuest(questId)
|
|
end
|
|
|
|
QuestieCombatQueue:Queue(function()
|
|
QuestieTracker:Update()
|
|
end)
|
|
end
|
|
|
|
function QuestieTracker:AQW_Insert(index, expire)
|
|
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieTracker:AQW_Insert]")
|
|
if (not Questie.db.profile.trackerEnabled) or (index == 0) or (index == nil) then
|
|
return
|
|
end
|
|
|
|
-- This prevents double calling this function
|
|
local now = GetTime()
|
|
if index and index == QuestieTracker.last_aqw and (now - lastAQW) < 0.05 then
|
|
return
|
|
end
|
|
|
|
lastAQW = now
|
|
QuestieTracker.last_aqw = index
|
|
|
|
-- This removes quests from the Blizzard QuestWatchFrame so when the option "Show Blizzard Timer" is enabled,
|
|
-- that is all the player will see. This also prevents hitting the Blizzard Quest Watch Limit.
|
|
RemoveQuestWatch(index, true)
|
|
|
|
local _, _, _, isHeader, _, _, _, questId = GetQuestLogTitle(index)
|
|
if isHeader then return end
|
|
|
|
if (not questId) or questId == 0 then
|
|
-- When an objective progresses in TBC "index" is the questId, but when a quest is manually added to the quest watch
|
|
-- (e.g. shift clicking it in the quest log) "index" is the questLogIndex.
|
|
if index and index > 50 and GetQuestLogIndexByID and GetQuestLogIndexByID(index) > 0 then
|
|
questId = index
|
|
else
|
|
return
|
|
end
|
|
end
|
|
|
|
if questId and questId > 0 then
|
|
-- Check if this was a manual user action (Shift-Click in Quest Log or similar)
|
|
local stack = debugstack(2, 8, 0)
|
|
local isUserAction = stack:find("QuestLog") or stack:find("OnClick") or stack:find("QuestWatch") or stack:find("Toggle") or stack:find("TrackerLinePool") or stack:find("TrackerMenu") or IsShiftKeyDown()
|
|
|
|
-- These checks makes sure the only way to track a quest is through the Blizzard Quest Log
|
|
-- or another Addon hooked into the Blizzard Quest Log that replaces the default Quest Log.
|
|
if not Questie.db.profile.autoTrackQuests then
|
|
if isUserAction then
|
|
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieTracker:AQW_Insert] - Manual mode, user re-track:", questId)
|
|
Questie.db.char.TrackedQuests[questId] = true
|
|
Questie.db.char.AutoUntrackedQuests[questId] = nil
|
|
else
|
|
-- In manual mode, we normally only track on user action, but if Blizzard calls it,
|
|
-- it might be a re-sync of something the user HAD tracked.
|
|
if Questie.db.char.TrackedQuests[questId] then
|
|
-- Keep it tracked
|
|
else
|
|
-- Blizzard auto-tracked something we didn't ask for? Ignore it in Manual mode.
|
|
return
|
|
end
|
|
end
|
|
else
|
|
if isUserAction then
|
|
-- Auto track mode: User manually tracked it (un-hiding)
|
|
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieTracker:AQW_Insert] - Auto mode, user un-hide:", questId)
|
|
Questie.db.char.AutoUntrackedQuests[questId] = nil
|
|
elseif Questie.db.char.AutoUntrackedQuests[questId] then
|
|
-- Auto track mode: Internal update for a HIDDEN quest — respect the hidden state!
|
|
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieTracker:AQW_Insert] - Auto mode, skipping hidden quest:", questId)
|
|
return
|
|
end
|
|
end
|
|
|
|
local quest = QuestieDB.GetQuest(questId)
|
|
|
|
if quest then
|
|
-- Make sure quests or zones (re)added to the tracker isn't in a minimized state
|
|
local zoneId = quest.zoneOrSort
|
|
if Questie.db.char.collapsedQuests[questId] == true then
|
|
Questie.db.char.collapsedQuests[questId] = nil
|
|
end
|
|
|
|
if Questie.db.char.collapsedZones[zoneId] == true then
|
|
Questie.db.char.collapsedZones[zoneId] = nil
|
|
end
|
|
|
|
-- Unhide quest icons when retracking quests.
|
|
if Questie.db.profile.hideUntrackedQuestsMapIcons then
|
|
-- Shows objective icons for tracked quests.
|
|
QuestieQuest:ToggleNotes(true)
|
|
|
|
-- Readd objective tooltips for tracked quests.
|
|
QuestieQuest:PopulateObjectiveNotes(quest)
|
|
end
|
|
else
|
|
if Questie.IsSoD then
|
|
QuestieDebugOffer.QuestTracking(questId)
|
|
else
|
|
-- Quest not in DB — try building a fallback object from the quest log.
|
|
-- Store in TrackerUtils._fallbackQuests only, NOT currentQuestlog,
|
|
-- so QuestieArrow/QuestieQuest don't call DB-only methods on it.
|
|
local fallback = TrackerUtils:BuildFallbackQuest(questId)
|
|
if fallback then
|
|
TrackerUtils._fallbackQuests[questId] = fallback
|
|
QuestieCombatQueue:Queue(function()
|
|
QuestieTracker:Update()
|
|
end)
|
|
else
|
|
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieTracker] Quest " .. tostring(questId) .. " not in DB and not in quest log, skipping")
|
|
end
|
|
end
|
|
end
|
|
end
|
|
QuestieCombatQueue:Queue(function()
|
|
QuestieTracker:Update()
|
|
end)
|
|
end
|
|
|
|
QuestieTracker.RemoveTrackedAchievement = function(achieveId, isQuestie)
|
|
if QuestieTracker.disableHooks then
|
|
return
|
|
end
|
|
|
|
if not isQuestie then
|
|
if achieveId then
|
|
QuestieTracker:UntrackAchieveId(achieveId)
|
|
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieTracker.RemoveTrackedAchievement] - by Blizzard")
|
|
end
|
|
else
|
|
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieTracker.RemoveTrackedAchievement] - by Questie")
|
|
end
|
|
end
|
|
|
|
function QuestieTracker:UpdateAchieveTrackerCache(achieveId)
|
|
-- Since we're essentially adding & force removing an achievement from the QuestWatch frame while we add an achievement to the Questie Tracker, the event this
|
|
-- function is called from, TRACKED_ACHIEVEMENT_LIST_CHANGED, fires twice. When we remove an achievement from the Questie Tracker the event still fires twice
|
|
-- because the Blizzard function responsible for this is essentially a "toggle". It quickly re-adds the achievement to the QuestWatch frame and then removes it.
|
|
-- So, again this event again fires twice. We only need to allow this to run once and it often fires before the Questie.db.char.trackedAchievementIds table is
|
|
-- updated so we're going to throttle this 1/10th of a second.
|
|
if Questie.db.profile.trackerEnabled then
|
|
if achieveId then
|
|
C_Timer.After(0.1, function()
|
|
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieTracker:UpdateAchieveTrackerCache] - ", achieveId)
|
|
|
|
if (not Questie.db.profile.trackerEnabled) or (achieveId == 0) then
|
|
return
|
|
end
|
|
|
|
-- Look for changes in the Saved VAR and update the achievement cache
|
|
if Questie.db.char.trackedAchievementIds[achieveId] ~= trackedAchievementIds[achieveId] then
|
|
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieTracker:UpdateAchieveTrackerCache] - Change Detected!")
|
|
|
|
trackedAchievementIds[achieveId] = Questie.db.char.trackedAchievementIds[achieveId]
|
|
|
|
QuestieCombatQueue:Queue(function()
|
|
C_Timer.After(0.1, function()
|
|
QuestieTracker:Update()
|
|
end)
|
|
end)
|
|
else
|
|
Questie:Debug(Questie.DEBUG_DEVELOP,
|
|
"[QuestieTracker:UpdateAchieveTrackerCache] - No Change Detected!")
|
|
end
|
|
end)
|
|
end
|
|
end
|
|
end
|
|
|
|
function QuestieTracker:UntrackAchieveId(achieveId)
|
|
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieTracker:UntrackAchieve] - ", achieveId)
|
|
if Questie.db.char.trackedAchievementIds[achieveId] then
|
|
Questie.db.char.trackedAchievementIds[achieveId] = nil
|
|
end
|
|
end
|
|
|
|
function QuestieTracker:TrackAchieve(achieveId)
|
|
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieTracker:TrackAchieve] - ", achieveId)
|
|
if (not Questie.db.profile.trackerEnabled) or (achieveId == 0) then
|
|
return
|
|
end
|
|
|
|
-- If an achievement is already tracked in the Achievement UI then untrack it (Mimicks a Toggle effect).
|
|
if Questie.db.char.trackedAchievementIds[achieveId] then
|
|
QuestieTracker:UntrackAchieveId(achieveId)
|
|
RemoveTrackedAchievement(achieveId, true)
|
|
return
|
|
end
|
|
|
|
-- Prevents tracking more than 10 Achievements
|
|
if (GetNumTrackedAchievements(true) == 10) then
|
|
RemoveTrackedAchievement(achieveId, true)
|
|
UIErrorsFrame:AddMessage(format(l10n("You may only track 10 achievements at a time."), 10), 1.0, 0.1, 0.1, 1.0)
|
|
return
|
|
end
|
|
|
|
-- This prevents double calling this function
|
|
local now = GetTime()
|
|
if achieveId and achieveId == QuestieTracker.last_achieveId and (now - lastAchieveId) < 0.1 then
|
|
return
|
|
end
|
|
|
|
lastAchieveId = now
|
|
QuestieTracker.last_achieveId = achieveId
|
|
|
|
-- This removes achievements from the Blizzard QuestWatchFrame so when the
|
|
-- option "Show Blizzard Timer" is enabled, that is all the player will see.
|
|
RemoveTrackedAchievement(achieveId, true)
|
|
|
|
if achieveId > 0 then
|
|
-- This handles the Track check box in the Achievement UI
|
|
local mouseFocus
|
|
local frameMatch
|
|
|
|
-- Krowi isn't using this check box for their Achievement frame
|
|
if not IsAddOnLoaded("Krowi_AchievementFilter") then
|
|
mouseFocus = GetMouseFocus():GetName()
|
|
frameMatch = strmatch(mouseFocus, "(AchievementFrameAchievementsContainerButton%dTracked.*)")
|
|
end
|
|
|
|
-- Upon first login or reloadui, this frame isn't loaded
|
|
if (not AchievementFrame) then
|
|
AchievementFrame_LoadUI()
|
|
end
|
|
|
|
-- This check makes sure the only way to track an achieve is through the Blizzard Achievement UI
|
|
if Questie.db.char.trackedAchievementIds[achieveId] then
|
|
Questie.db.char.trackedAchievementIds[achieveId] = nil
|
|
elseif IsShiftKeyDown() and AchievementFrame:IsShown() then
|
|
Questie.db.char.trackedAchievementIds[achieveId] = true
|
|
elseif AchievementFrame:IsShown() and (mouseFocus == frameMatch) then
|
|
Questie.db.char.trackedAchievementIds[achieveId] = true
|
|
end
|
|
|
|
-- Forces the achievement out of a minimized state
|
|
if Questie.db.char.collapsedQuests[achieveId] == true then
|
|
Questie.db.char.collapsedQuests[achieveId] = nil
|
|
end
|
|
|
|
-- Forces the 'Achievement Zone' out of a minimized state
|
|
if Questie.db.char.collapsedZones["Achievements"] == true then
|
|
Questie.db.char.collapsedZones["Achievements"] = nil
|
|
end
|
|
end
|
|
end
|