def947bec1
Previous guard only checked LSM30 ~= nil; if Fetch method is absent on the stub object the call still crashes. Now uses full 3-part check: (LSM30 and LSM30.Fetch and LSM30:Fetch(...)) or fallback Matches the pattern already used in QuestieArrow.lua.
2675 lines
131 KiB
Lua
2675 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 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(line.label:GetWrappedWidth() + objectiveMarginLeft)
|
|
|
|
-- Blizzard Completion Text tends to be rather verbose. Allow text wrapping.
|
|
line.label:SetHeight(line.label:GetStringHeight() *
|
|
line.label:GetNumLines())
|
|
line:SetHeight(line.label:GetHeight())
|
|
|
|
-- Compare trackerLineWidth, trackerMinLineWidth and the current label, then save the widest width
|
|
trackerLineWidth = math.max(trackerLineWidth, trackerMinLineWidth,
|
|
line.label:GetWrappedWidth() + 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(line.label:GetWrappedWidth() + objectiveMarginLeft)
|
|
|
|
-- Blizzard Completion Text tends to be rather verbose. Allow text wrapping.
|
|
line.label:SetHeight(line.label:GetStringHeight() * line.label:GetNumLines())
|
|
line:SetHeight(line.label:GetHeight())
|
|
|
|
-- Compare trackerLineWidth, trackerMinLineWidth and the current label, then save the widest width
|
|
trackerLineWidth = math.max(trackerLineWidth, trackerMinLineWidth,
|
|
line.label:GetWrappedWidth() + 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(line.label:GetWrappedWidth() + objectiveMarginLeft)
|
|
|
|
-- TextWrap Objective and set height
|
|
line.label:SetHeight(line.label:GetStringHeight() * line.label:GetNumLines())
|
|
line:SetHeight(line.label:GetHeight())
|
|
|
|
-- Compare trackerLineWidth, trackerMinLineWidth and the current label, then save the widest width
|
|
trackerLineWidth = math.max(trackerLineWidth, trackerMinLineWidth,
|
|
line.label:GetWrappedWidth() + 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
|