Files
Questie-X/Modules/Tracker/TrackerLinePool.lua
T
2026-03-20 22:04:51 -05:00

1136 lines
45 KiB
Lua

---@class TrackerLinePool
local TrackerLinePool = QuestieLoader:CreateModule("TrackerLinePool")
-------------------------
--Import QuestieTracker modules.
-------------------------
---@type QuestieTracker
local QuestieTracker = QuestieLoader:ImportModule("QuestieTracker")
---@type TrackerBaseFrame
local TrackerBaseFrame = QuestieLoader:ImportModule("TrackerBaseFrame")
---@type TrackerUtils
local TrackerUtils = QuestieLoader:ImportModule("TrackerUtils")
---@type TrackerQuestTimers
local TrackerQuestTimers = QuestieLoader:ImportModule("TrackerQuestTimers")
---@type TrackerMenu
local TrackerMenu = QuestieLoader:ImportModule("TrackerMenu")
---@type TrackerFadeTicker
local TrackerFadeTicker = QuestieLoader:ImportModule("TrackerFadeTicker")
-------------------------
--Import Questie modules.
-------------------------
---@type QuestieLink
local QuestieLink = QuestieLoader:ImportModule("QuestieLink")
---@type QuestieMap
local QuestieMap = QuestieLoader:ImportModule("QuestieMap")
---@type QuestieCombatQueue
local QuestieCombatQueue = QuestieLoader:ImportModule("QuestieCombatQueue")
---@type QuestieDB
local QuestieDB = QuestieLoader:ImportModule("QuestieDB")
---@type QuestieLib
local QuestieLib = QuestieLoader:ImportModule("QuestieLib");
---@type l10n
local l10n = QuestieLoader:ImportModule("l10n")
--- COMPATIBILITY ---
local C_Timer = QuestieCompat.C_Timer
local C_QuestLog = QuestieCompat.C_QuestLog
local GetQuestLogIndexByID = QuestieCompat.GetQuestLogIndexByID
local LibDropDown = QuestieCompat.LibUIDropDownMenu or LibStub:GetLibrary("LibUIDropDownMenuQuestie-4.0")
local LSM30 = LibStub("LibSharedMedia-3.0")
local linePoolSize = 250
local lineIndex = 0
local buttonPoolSize = 25
local buttonIndex = 0
local linePool = {}
local buttonPool = {}
local lineMarginLeft = 10
---@param questFrame Frame
function TrackerLinePool.Initialize(questFrame)
local trackerQuestFrame = questFrame
local trackerFontSizeQuest = Questie.db.profile.trackerFontSizeQuest
-- create linePool for quests/achievements
local nextFrame
for i = 1, linePoolSize do
local timeElapsed = 0
local line = CreateFrame("Button", "linePool" .. i, trackerQuestFrame.ScrollChildFrame)
line:SetWidth(1)
line:SetHeight(1)
line.label = line:CreateFontString(nil, "ARTWORK", "GameFontNormal")
line.label:SetJustifyH("LEFT")
line.label:SetJustifyV("TOP")
line.label:SetPoint("TOPLEFT", line)
line.label:Hide()
-- autoadjust parent size for clicks
line.label._SetText = line.label.SetText
line.label.frame = line
line.label.SetText = function(self, text)
self:_SetText(text)
self.frame:SetWidth(self:GetWidth())
self.frame:SetHeight(self:GetHeight())
end
if nextFrame then
-- Second lineIndex hearafter
line:SetPoint("TOPLEFT", nextFrame, "BOTTOMLEFT", 0, 0)
else
-- First lineIndex
line:SetPoint("TOPLEFT", trackerQuestFrame.ScrollChildFrame, "TOPLEFT", lineMarginLeft, 0)
end
line.SetMode = TrackerLinePool.SetMode
function line:SetZone(ZoneId)
if type(ZoneId) == "string" then
self.expandZone.zoneId = ZoneId
elseif type(ZoneId) == "number" then
self.ZoneId = TrackerUtils:GetZoneNameByID(ZoneId)
self.expandZone.zoneId = ZoneId
end
end
function line:SetQuest(Quest)
if type(Quest) == "number" then
Quest = {
Id = Quest
}
self.Quest = Quest
self.expandQuest.questId = Quest.Id
else
self.Quest = Quest
self.expandQuest.questId = Quest.Id
end
-- Set Timed Quest Flag
if Quest.trackTimedQuest then
self.trackTimedQuest = Quest.trackTimedQuest
end
end
function line:SetObjective(Objective)
self.Objective = Objective
end
line.OnUpdate = function(self, elapsed)
if Questie.IsWotlk or QuestieCompat.Is335 then
timeElapsed = timeElapsed + elapsed
if timeElapsed > 1 and self.trackTimedQuest and self.label.activeTimer then
local _, timeRemaining = TrackerQuestTimers:GetRemainingTimeByQuestId(self.Quest.Id)
if timeRemaining ~= nil then
if timeRemaining > 1 then
TrackerQuestTimers:UpdateTimerFrame()
end
if timeRemaining == 1 then
TrackerQuestTimers:UpdateTimerFrame()
end
timeElapsed = 0
else
timeElapsed = 0
return
end
end
else
return
end
end
function line:SetVerticalPadding(amount)
if self.mode == "zone" then
self:SetHeight(Questie.db.profile.trackerFontSizeZone + amount)
elseif self.mode == "quest" or "achieve" then
self:SetHeight(Questie.db.profile.trackerFontSizeQuest + amount)
else
self:SetHeight(Questie.db.profile.trackerFontSizeObjective + amount)
end
end
line:EnableMouse(true)
line:RegisterForDrag("LeftButton")
line:RegisterForClicks("RightButtonUp", "LeftButtonUp")
-- TEST: Always capture clicks to debug
line:SetScript("OnClick", function(self, button)
Questie:Debug(Questie.DEBUG_DEVELOP, "[TrackerLinePool:TEST_OnClick] button:", button, "Shift:", IsShiftKeyDown())
end)
function line:SetOnClick(onClickmode)
if onClickmode == "quest" then
self:SetScript("OnClick", TrackerLinePool.OnClickQuest)
elseif onClickmode == "achieve" then
self:SetScript("OnClick", TrackerLinePool.OnClickAchieve)
end
end
line:SetScript("OnDragStart", TrackerBaseFrame.OnDragStart)
line:SetScript("OnDragStop", TrackerBaseFrame.OnDragStop)
line:SetScript("OnEnter", function(self)
TrackerLinePool.OnHighlightEnter(self)
TrackerFadeTicker.Unfade()
end)
line:SetScript("OnLeave", function(self)
TrackerLinePool.OnHighlightLeave(self)
TrackerFadeTicker.Fade()
end)
-- create objective complete criteria marks
local criteriaMark = CreateFrame("Button", "linePool.criteriaMark" .. i, line)
criteriaMark.texture = criteriaMark:CreateTexture(nil, "OVERLAY", nil, 0)
criteriaMark.texture:SetWidth(Questie.db.profile.trackerFontSizeObjective)
criteriaMark.texture:SetHeight(Questie.db.profile.trackerFontSizeObjective)
criteriaMark.texture:SetAllPoints(criteriaMark)
criteriaMark:SetWidth(1)
criteriaMark:SetHeight(1)
criteriaMark:SetPoint("RIGHT", line.label, "LEFT", -4, 0)
criteriaMark:SetFrameLevel(100)
criteriaMark.SetCriteria = function(self, criteria)
if criteria ~= self.mode then
self.mode = criteria
if criteria == true then
self.texture:SetTexture(QuestieLib.AddonPath.."Icons\\Checkmark")
---------------------------------------------------------------------
-- Just in case we decide to show the minus sign for incompletes
---------------------------------------------------------------------
--self.texture:SetAlpha(1)
--else
--self.texture:SetTexture("Interface\\Addons\\Questie\\Icons\\Minus")
--self.texture:SetAlpha(0.5)
---------------------------------------------------------------------
end
self:SetWidth(Questie.db.profile.trackerFontSizeObjective)
self:SetHeight(Questie.db.profile.trackerFontSizeObjective)
end
end
criteriaMark:SetCriteria(false)
criteriaMark:Hide()
line.criteriaMark = criteriaMark
-- create expanding zone headers for quests sorted by zones
local expandZone = CreateFrame("Button", "linePool.expandZone" .. i, line)
expandZone:SetWidth(1)
expandZone:SetHeight(1)
expandZone:SetPoint("TOPLEFT", line, "TOPLEFT", 0, 0)
expandZone.SetMode = function(self, mode)
if mode ~= self.mode then
self.mode = mode
end
end
expandZone:SetMode(1) -- maximized
expandZone:EnableMouse(true)
expandZone:RegisterForDrag("LeftButton")
expandZone:RegisterForClicks("LeftButtonUp", "LeftButtonDown", "RightButtonUp", "RightButtonDown")
expandZone:SetScript("OnMouseDown", function(self, button)
if button == "LeftButton" then
if IsShiftKeyDown() then
-- This sets up the minAllQuestsInZone table upon first click
if not Questie.db.char.collapsedZones[self.zoneId] then
if not Questie.db.char.minAllQuestsInZone[self.zoneId] then
Questie.db.char.minAllQuestsInZone[self.zoneId] = {}
-- This flag prevents repopulating QuestID's where we don't want them.
Questie.db.char.minAllQuestsInZone[self.zoneId].isTrue = true
QuestieCombatQueue:Queue(function()
QuestieTracker:Update()
end)
end
end
end
end
end)
expandZone:SetScript("OnMouseUp", function(self, button)
if button == "LeftButton" then
if IsShiftKeyDown() then
if not Questie.db.char.collapsedZones[self.zoneId] then
C_Timer.After(0.1, function()
if Questie.db.char.minAllQuestsInZone[self.zoneId].isTrue then
-- Places all QuestID's into the collapsedQuests table and keeps the Min/Max buttons in sync.
Questie:Debug(Questie.DEBUG_DEVELOP, "[TrackerLinePool:minAllQuestsInZone] - Minimize")
for questId, _ in pairs(Questie.db.char.minAllQuestsInZone[self.zoneId]) do
if type(questId) == "number" then
Questie.db.char.collapsedQuests[questId] = true
end
end
Questie.db.char.minAllQuestsInZone[self.zoneId].isTrue = nil
else
-- Removes all QuestID's from the collapsedQuests table.
Questie:Debug(Questie.DEBUG_DEVELOP, "[TrackerLinePool:minAllQuestsInZone] - Maximize")
for questId, _ in pairs(Questie.db.char.minAllQuestsInZone[self.zoneId]) do
if type(questId) == "number" then
Questie.db.char.collapsedQuests[questId] = nil
end
end
Questie.db.char.minAllQuestsInZone[self.zoneId] = nil
end
QuestieCombatQueue:Queue(function()
QuestieTracker:Update()
end)
end)
end
else
if self.mode == 1 then
self:SetMode(0)
Questie:Debug(Questie.DEBUG_DEVELOP, "[TrackerLinePool:expandZone] - Minimize")
else
self:SetMode(1)
Questie:Debug(Questie.DEBUG_DEVELOP, "[TrackerLinePool:expandZone] - Maximize")
end
if Questie.db.char.collapsedZones[self.zoneId] == true then
Questie.db.char.collapsedZones[self.zoneId] = nil
else
Questie.db.char.collapsedZones[self.zoneId] = true
end
QuestieCombatQueue:Queue(function()
QuestieTracker:Update()
end)
end
end
end)
expandZone:SetScript("OnEnter", function(self)
TrackerLinePool.OnHighlightEnter(self)
TrackerFadeTicker.Unfade()
end)
expandZone:SetScript("OnLeave", function(self)
TrackerLinePool.OnHighlightLeave(self)
TrackerFadeTicker.Fade()
end)
expandZone:Hide()
line.expandZone = expandZone
-- create play buttons for AI_VoiceOver
local playButton = CreateFrame("Button", "linePool.playButton" .. i, line)
playButton:SetWidth(20)
playButton:SetHeight(20)
playButton:SetHitRectInsets(2, 2, 2, 2)
playButton:SetPoint("RIGHT", line.label, "LEFT", -4, 0)
playButton:SetFrameLevel(0)
playButton:SetNormalTexture(QuestieLib.AddonPath.."Icons\\QuestLogPlayButton")
playButton:SetHighlightTexture("Interface\\BUTTONS\\UI-Panel-MinimizeButton-Highlight")
playButton.SetPlayButton = function(self, questId)
if questId ~= self.mode then
self.mode = questId
if questId and TrackerUtils:IsVoiceOverLoaded() then
self:Show()
else
self.mode = nil
self:SetAlpha(0)
self:Hide()
end
end
end
playButton:EnableMouse(true)
playButton:RegisterForClicks("LeftButtonUp")
playButton:SetScript("OnClick", function(self)
if self.mode ~= nil then
if TrackerUtils:IsVoiceOverLoaded() then
local button = VoiceOver.QuestOverlayUI.questPlayButtons[self.mode]
if button then
if not VoiceOver.QuestOverlayUI.questPlayButtons[self.mode].soundData then
local type, id = VoiceOver.DataModules:GetQuestLogQuestGiverTypeAndID(self.mode)
local qli = GetQuestLogIndexByID(self.mode)
local title = (qli and GetQuestLogTitle(qli)) or ""
VoiceOver.QuestOverlayUI.questPlayButtons[self.mode].soundData = {
event = VoiceOver.Enums.SoundEvent.QuestAccept,
questID = self.mode,
name = id and VoiceOver.DataModules:GetObjectName(type, id) or "Unknown Name",
title = title,
unitGUID = id and VoiceOver.Enums.GUID:CanHaveID(type) and VoiceOver.Utils:MakeGUID(type, id) or nil
}
end
local soundData = VoiceOver.QuestOverlayUI.questPlayButtons[self.mode].soundData
local isPlaying = VoiceOver.SoundQueue:Contains(soundData)
if not isPlaying then
VoiceOver.SoundQueue:AddSoundToQueue(soundData)
VoiceOver.QuestOverlayUI:UpdatePlayButtonTexture(self.mode)
soundData.stopCallback = function()
VoiceOver.QuestOverlayUI:UpdatePlayButtonTexture(self.mode)
VoiceOver.QuestOverlayUI.questPlayButtons[self.mode].soundData = nil
end
else
VoiceOver.SoundQueue:RemoveSoundFromQueue(soundData)
end
isPlaying = button.soundData and VoiceOver.SoundQueue:Contains(button.soundData)
local texturePath = isPlaying and QuestieLib.AddonPath.."Icons\\QuestLogStopButton" or QuestieLib.AddonPath.."Icons\\QuestLogPlayButton"
self:SetNormalTexture(texturePath)
-- Move the VoiceOverFrame below the DurabilityFrame if it's present and not already moved
if (Questie.db.profile.stickyDurabilityFrame and DurabilityFrame:IsVisible()) and select(5, VoiceOverFrame:GetPoint()) < -125 then
QuestieTracker:UpdateVoiceOverFrame()
end
end
end
end
end)
playButton:SetAlpha(0)
playButton:Hide()
line.playButton = playButton
-- create expanding buttons for quests with objectives
local expandQuest = CreateFrame("Button", "linePool.expandQuest" .. i, line)
expandQuest.texture = expandQuest:CreateTexture(nil, "OVERLAY", nil, 0)
expandQuest.texture:SetWidth(trackerFontSizeQuest)
expandQuest.texture:SetHeight(trackerFontSizeQuest)
expandQuest.texture:SetAllPoints(expandQuest)
expandQuest:SetWidth(trackerFontSizeQuest)
expandQuest:SetHeight(trackerFontSizeQuest)
expandQuest:SetPoint("RIGHT", line, "LEFT", 0, 0)
expandQuest:SetFrameLevel(100)
expandQuest.SetMode = function(self, mode)
if mode ~= self.mode then
self.mode = mode
if mode == 1 then
self.texture:SetTexture("Interface\\Buttons\\UI-MinusButton-Up")
else
self.texture:SetTexture("Interface\\Buttons\\UI-PlusButton-Up")
end
self:SetWidth(Questie.db.profile.trackerFontSizeQuest + 3)
self:SetHeight(Questie.db.profile.trackerFontSizeQuest + 3)
end
end
expandQuest:SetMode(1) -- maximized
expandQuest:EnableMouse(true)
expandQuest:RegisterForClicks("LeftButtonUp", "RightButtonUp")
expandQuest:SetScript("OnClick", function(self)
if self.mode == 1 then
self:SetMode(0)
Questie:Debug(Questie.DEBUG_DEVELOP, "[TrackerLinePool:expandQuest] - Minimize")
else
self:SetMode(1)
Questie:Debug(Questie.DEBUG_DEVELOP, "[TrackerLinePool:expandQuest] - Maximize")
end
if Questie.db.char.collapsedQuests[self.questId] then
Questie.db.char.collapsedQuests[self.questId] = nil
-- This keeps both tables in sync so we can use them to maintain Min/Max states.
if Questie.db.char.minAllQuestsInZone[self.zoneId] and Questie.db.char.minAllQuestsInZone[self.zoneId][self.questId] then
Questie.db.char.minAllQuestsInZone[self.zoneId][self.questId] = nil
end
else
Questie.db.char.collapsedQuests[self.questId] = true
-- This keeps both tables in sync so we can use them to maintain Min/Max states.
if Questie.db.char.minAllQuestsInZone[self.zoneId] then
Questie.db.char.minAllQuestsInZone[self.zoneId][self.questId] = true
end
end
QuestieCombatQueue:Queue(function()
QuestieTracker:Update()
end)
end)
if Questie.IsWotlk or QuestieCompat.Is335 then
line:HookScript("OnUpdate", line.OnUpdate)
end
if Questie.db.profile.trackerFadeMinMaxButtons then
expandQuest:SetAlpha(0)
end
expandQuest:SetScript("OnEnter", function()
TrackerFadeTicker.Unfade()
end)
expandQuest:SetScript("OnLeave", function()
TrackerFadeTicker.Fade()
end)
expandQuest:Hide()
line.expandQuest = expandQuest
linePool[i] = line
nextFrame = line
end
-- create buttonPool for quest items
for i = 1, C_QuestLog.GetMaxNumQuestsCanAccept() do
local buttonName = "Questie_ItemButton" .. i
local btn = CreateFrame("Button", buttonName, UIParent, "SecureActionButtonTemplate")
local cooldown = CreateFrame("Cooldown", nil, btn, "CooldownFrameTemplate")
btn.range = btn:CreateFontString(nil, "OVERLAY", "NumberFontNormalSmallGray")
btn.count = btn:CreateFontString(nil, "ARTWORK", QuestieCompat.Is335 and "SystemFont_Outline_Small" or "Game10Font_o1")
btn:Hide()
if Questie.db.profile.trackerFadeQuestItemButtons then
btn:SetAlpha(0)
end
btn.SetItem = function(self, quest, buttonType, size)
local validTexture
for bag = -2, 4 do
for slot = 1, QuestieCompat.GetContainerNumSlots(bag) do
local texture, _, _, _, _, _, _, _, _, itemId = QuestieCompat.GetContainerItemInfo(bag, slot)
-- These type of quest items can never be secondary buttons
if quest.sourceItemId == itemId and QuestieDB.QueryItemSingle(itemId, "class") == 12 and buttonType == "primary" then
validTexture = texture
self.itemId = quest.sourceItemId
break
end
-- These type of quest items are technically secondary buttons but are assigned primary button slots
if (not quest.sourceItemId or quest.sourceItemId == 0) and type(quest.requiredSourceItems) == "table" and #quest.requiredSourceItems == 1 then
local questItemId = quest.requiredSourceItems[1]
if questItemId and questItemId ~= quest.sourceItemId and QuestieDB.QueryItemSingle(questItemId, "class") == 12 and questItemId == itemId then
validTexture = texture
self.itemId = questItemId
break
end
-- These type of quest items can never be primary buttons
elseif type(quest.requiredSourceItems) == "table" and #quest.requiredSourceItems > 1 then
for _, questItemId in pairs(quest.requiredSourceItems) do
if questItemId and questItemId ~= quest.sourceItemId and QuestieDB.QueryItemSingle(questItemId, "class") == 12 and questItemId == itemId and buttonType == "secondary" then
validTexture = texture
self.itemId = questItemId
break
end
end
end
end
end
-- Edge case to find "equipped" quest items since they will no longer be in the players bag
if (not validTexture) then
for inventorySlot = 1, 19 do
local itemId = GetInventoryItemID("player", inventorySlot)
-- These type of quest items can never be secondary buttons
if quest.sourceItemId == itemId and QuestieDB.QueryItemSingle(itemId, "class") == 12 and buttonType == "primary" then
validTexture = GetInventoryItemTexture("player", inventorySlot)
self.itemId = quest.sourceItemId
break
end
-- These type of quest items are technically secondary buttons but are assigned primary button slots
if type(quest.requiredSourceItems) == "table" and #quest.requiredSourceItems == 1 then
local questItemId = quest.requiredSourceItems[1]
if questItemId and questItemId ~= quest.sourceItemId and QuestieDB.QueryItemSingle(questItemId, "class") == 12 and questItemId == itemId then
validTexture = GetInventoryItemTexture("player", inventorySlot)
self.itemId = questItemId
break
end
-- These type of quest items can never be primary buttons
elseif type(quest.requiredSourceItems) == "table" and #quest.requiredSourceItems > 1 then
for _, questItemId in pairs(quest.requiredSourceItems) do
if questItemId and questItemId ~= quest.sourceItemId and QuestieDB.QueryItemSingle(questItemId, "class") == 12 and questItemId == itemId and buttonType == "secondary" then
validTexture = GetInventoryItemTexture("player", inventorySlot)
self.itemId = questItemId
break
end
end
end
end
end
if validTexture and self.itemId then
self.questID = quest.Id
self.charges = GetItemCount(self.itemId, nil, true)
self.rangeTimer = -1
self:SetNormalTexture(validTexture)
self:SetPushedTexture(validTexture)
self:SetHighlightTexture("Interface\\Buttons\\ButtonHilight-Square")
self:SetSize(size, size)
self:RegisterForClicks("anyUp")
self:SetScript("OnEvent", self.OnEvent)
self:SetScript("OnShow", self.OnShow)
self:SetScript("OnHide", self.OnHide)
self:SetScript("OnEnter", self.OnEnter)
self:SetScript("OnLeave", self.OnLeave)
self:SetAttribute("type1", "item")
self:SetAttribute("item1", "item:" .. self.itemId)
self:Show()
-- Cooldown Updates
cooldown:SetSize(size - 4, size - 4)
cooldown:SetPoint("CENTER", self, "CENTER", 0, 0)
cooldown:Hide()
-- Range Updates
self.range:SetText("●")
self.range:SetPoint("TOPRIGHT", self, "TOPRIGHT", 3, 0)
self.range:Hide()
-- Charges Updates
self.count:Hide()
self.count:SetFont(LSM30:Fetch("font", Questie.db.profile.trackerFontQuest), Questie.db.profile.trackerFontSizeQuest, "OUTLINE")
if self.charges > 1 then
self.count:SetText(self.charges)
self.count:Show()
end
self.count:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", -2, 3)
return true
else
self:SetAttribute("item1", nil)
self:Hide()
end
return false
end
btn.OnEvent = function(self, event, ...)
if (event == "PLAYER_TARGET_CHANGED") then
self.rangeTimer = -1
self.range:Hide()
end
end
btn.OnUpdate = function(self, elapsed)
if not self.itemId or not self:IsVisible() then
return
end
local start, duration, enabled = QuestieCompat.GetItemCooldown(self.itemId)
if enabled == 1 and duration > 0 then
cooldown:SetCooldown(start, duration, enabled)
cooldown:Show()
else
cooldown:Hide()
end
local charges = GetItemCount(self.itemId, nil, true)
if (not charges or charges ~= self.charges) then
self.count:Hide()
self.charges = GetItemCount(self.itemId, nil, true)
if self.charges > 1 then
self.count:SetText(self.charges)
self.count:Show()
end
if self.charges == 0 then
Questie:Debug(Questie.DEBUG_DEVELOP, "[TrackerLinePool: Button.OnUpdate]")
QuestieCombatQueue:Queue(function()
C_Timer.After(0.2, function()
QuestieTracker:Update()
end)
end)
end
end
if UnitExists("target") then
if not self.itemName then
self.itemName = GetItemInfo(self.itemId)
end
local rangeTimer = self.rangeTimer
if (rangeTimer) then
rangeTimer = rangeTimer - elapsed
-- IsItemInRange is restricted to only be used either on hostile targets or friendly ones while NOT in combat
if (rangeTimer <= 0) and (not UnitIsFriend("player", "target") or (not InCombatLockdown())) then
local isInRange = IsItemInRange(self.itemName, "target")
if isInRange == false then
self.range:SetVertexColor(1.0, 0.1, 0.1)
self.range:Show()
elseif isInRange == true then
self.range:SetVertexColor(0.6, 0.6, 0.6)
self.range:Show()
end
rangeTimer = 0.3
end
self.rangeTimer = rangeTimer
end
end
end
btn.OnShow = function(self)
self:RegisterEvent("PLAYER_TARGET_CHANGED")
end
btn.OnHide = function(self)
self:UnregisterEvent("PLAYER_TARGET_CHANGED")
end
btn.OnEnter = function(self)
GameTooltip:SetOwner(self, "ANCHOR_CURSOR")
GameTooltip:SetHyperlink("item:" .. tostring(self.itemId) .. ":0:0:0:0:0:0:0")
GameTooltip:Show()
TrackerFadeTicker.Unfade(self)
end
btn.OnLeave = function(self)
GameTooltip:Hide()
TrackerFadeTicker.Fade(self)
end
btn.FakeHide = function(self)
self:RegisterForClicks()
self:SetScript("OnEnter", nil)
self:SetScript("OnLeave", nil)
end
btn:HookScript("OnUpdate", btn.OnUpdate)
btn:FakeHide()
buttonPool[i] = btn
buttonPool[i]:Hide()
end
end
function TrackerLinePool.ResetLinesForChange()
if TrackerBaseFrame.isSizing == true or TrackerBaseFrame.isMoving == true then
Questie:Debug(Questie.DEBUG_SPAM, "[TrackerLinePool:ResetLinesForChange]")
else
Questie:Debug(Questie.DEBUG_INFO, "[TrackerLinePool:ResetLinesForChange]")
end
if InCombatLockdown() or not Questie.db.profile.trackerEnabled then
return
end
for _, line in pairs(linePool) do
line.mode = nil
line.trackTimedQuest = nil
if line.expandQuest then
line.expandQuest.mode = nil
line.expandQuest.questId = nil
end
if line.expandZone then
line.expandZone.mode = nil
line.expandZone.zoneId = nil
end
if line.criteriaMark then
line.criteriaMark.mode = nil
line.criteriaMark:SetCriteria(false)
line.criteriaMark:Hide()
end
if line.playButton then
line.playButton.mode = nil
line.playButton:SetAlpha(0)
line.playButton:Hide()
end
end
lineIndex = 0
end
function TrackerLinePool.ResetButtonsForChange()
if TrackerBaseFrame.isSizing == true or TrackerBaseFrame.isMoving == true then
Questie:Debug(Questie.DEBUG_SPAM, "[TrackerLinePool:ResetButtonsForChange]")
else
Questie:Debug(Questie.DEBUG_INFO, "[TrackerLinePool:ResetButtonsForChange]")
end
if InCombatLockdown() or not Questie.db.profile.trackerEnabled then
return
end
buttonIndex = 0
end
function TrackerLinePool.UpdateWrappedLineWidths(trackerLineWidth)
local trackerFontSizeQuest = Questie.db.profile.trackerFontSizeQuest
local trackerMarginLeft = 14
local trackerMarginRight = 30
local questMarginLeft = (trackerMarginLeft + trackerMarginRight) - (18 - trackerFontSizeQuest)
local objectiveMarginLeft = questMarginLeft + trackerFontSizeQuest
local questItemButtonSize = 12 + trackerFontSizeQuest
-- Updates all the line.label widths in the linePool for wrapped text only
for _, line in pairs(linePool) do
if Questie.db.profile.TrackerWidth == 0 then
if line.mode == "objective" then
if line.label:GetNumLines() > 1 and line:GetHeight() > Questie.db.profile.trackerFontSizeObjective then
line.label:SetText(line.label:GetText())
if line.altButton then
line.label:SetWidth(trackerLineWidth - objectiveMarginLeft - questItemButtonSize)
line:SetWidth(trackerLineWidth + questItemButtonSize)
else
line.label:SetWidth(trackerLineWidth - objectiveMarginLeft)
line:SetWidth(trackerLineWidth)
end
line:SetHeight(line.label:GetStringHeight() + 2 + Questie.db.profile.trackerQuestPadding)
line.label:SetHeight(line:GetHeight() - 2 - Questie.db.profile.trackerQuestPadding)
end
end
end
end
end
---@return table|nil lineIndex linePool[lineIndex + 1]
function TrackerLinePool.GetNextLine()
lineIndex = lineIndex + 1
if not linePool[lineIndex] then
return nil -- past the line limit
end
return linePool[lineIndex]
end
---@return table|nil buttonIndex buttonPool[buttonIndex]
function TrackerLinePool.GetNextItemButton()
buttonIndex = buttonIndex + 1
if not buttonPool[buttonIndex] then
return nil -- past the line limit
end
return buttonPool[buttonIndex]
end
---@return number lineIndex lineIndex == 1
function TrackerLinePool.IsFirstLine()
return linePool[1]
end
---@param index number
---@return table index linePool[index]
function TrackerLinePool.GetLine(index)
return linePool[index]
end
---@return table lineIndex linePool[lineIndex]
function TrackerLinePool.GetCurrentLine()
return linePool[lineIndex]
end
---@return table buttonIndex buttonPool[buttonIndex]
function TrackerLinePool.GetCurrentButton()
return buttonPool[buttonIndex]
end
---@return table|nil lineIndex linePool[lineIndex - 1]
function TrackerLinePool.GetPreviousLine()
lineIndex = lineIndex - 1
if not linePool[lineIndex] then
return nil -- past the line limit
end
return linePool[lineIndex]
end
---@return table linePool linePool[1]
function TrackerLinePool.GetFirstLine()
return linePool[1]
end
---@return table linePool linePool[linePoolSize]
function TrackerLinePool.GetLastLine()
return linePool[linePoolSize]
end
function TrackerLinePool.HideUnusedLines()
if TrackerBaseFrame.isSizing == true or TrackerBaseFrame.isMoving == true then
Questie:Debug(Questie.DEBUG_SPAM, "[TrackerLinePool:HideUnusedLines]")
else
Questie:Debug(Questie.DEBUG_INFO, "[TrackerLinePool:HideUnusedLines]")
end
local startUnusedLines = 0
if Questie.db.char.isTrackerExpanded then
startUnusedLines = lineIndex + 1
end
for i = startUnusedLines, linePoolSize do
local line = linePool[i]
if line then -- Safe Guard to really concurrent triggers
line:Hide()
line.mode = nil
line.ZoneId = nil
line.Quest = nil
line.Objective = nil
line.Button = nil
line.altButton = nil
line.trackTimedQuest = nil
line.expandQuest.mode = nil
line.expandQuest.questId = nil
line.expandZone.mode = nil
line.expandZone.zoneId = nil
line.criteriaMark.mode = nil
line.playButton.mode = nil
end
end
end
function TrackerLinePool.HideUnusedButtons()
if TrackerBaseFrame.isSizing == true or TrackerBaseFrame.isMoving == true then
Questie:Debug(Questie.DEBUG_SPAM, "[TrackerLinePool:HideUnusedButtons]")
else
Questie:Debug(Questie.DEBUG_INFO, "[TrackerLinePool:HideUnusedButtons]")
end
local startUnusedButtons = 0
if Questie.db.char.isTrackerExpanded then
startUnusedButtons = buttonIndex + 1
end
for i = startUnusedButtons, buttonPoolSize do
local button = buttonPool[i]
if button then
button:FakeHide()
button.itemId = nil
button.itemName = nil
button.lineID = nil
button.fontSize = nil
button:ClearAllPoints()
button:SetParent(UIParent)
button:Hide()
end
end
end
---@return number lineIndex
function TrackerLinePool.GetHighestIndex()
return lineIndex > linePoolSize and linePoolSize or lineIndex
end
---@param alpha number
function TrackerLinePool.SetAllPlayButtonAlpha(alpha)
if TrackerUtils:IsVoiceOverLoaded() then
local highestIndex = TrackerLinePool.GetHighestIndex()
for i = 1, highestIndex do
local line = linePool[i]
local questId = line.playButton.mode or 0
local button = VoiceOver.QuestOverlayUI.questPlayButtons[questId]
local sound = VoiceOver.DataModules:PrepareSound({ event = 1, questID = questId })
if button then
local isPlaying = button.soundData and VoiceOver.SoundQueue:Contains(button.soundData)
local texturePath = isPlaying and QuestieLib.AddonPath.."Icons\\QuestLogStopButton" or QuestieLib.AddonPath.."Icons\\QuestLogPlayButton"
line.playButton:SetNormalTexture(texturePath)
end
if IsShiftKeyDown() then
if sound then
line.playButton:SetAlpha(alpha)
else
line.playButton:SetAlpha(0.33)
end
line.playButton:SetFrameLevel(200)
else
line.playButton:SetAlpha(alpha)
line.playButton:SetFrameLevel(0)
end
end
end
end
---@param alpha number
function TrackerLinePool.SetAllExpandQuestAlpha(alpha)
local highestIndex = TrackerLinePool.GetHighestIndex()
for i = 1, highestIndex do
linePool[i].expandQuest:SetAlpha(alpha)
end
end
---@param alpha number
function TrackerLinePool.SetAllItemButtonAlpha(alpha)
local highestIndex = TrackerLinePool.GetHighestIndex()
-- TODO: I don't remember why I coded this hasButton variable. Going to leave it here for now.
--local hasButton = false
for i = 1, highestIndex do
local line = linePool[i]
if line.button then
line.button:SetAlpha(alpha)
--if line.button:GetAlpha() < 0.07 then
-- hasButton = true
--end
end
if line.altButton then
line.altButton:SetAlpha(alpha)
--if line.altButton:GetAlpha() < 0.07 then
-- hasButton = true
--end
end
end
--[[
if hasButton then
QuestieTracker:Update()
end
--]]
end
---@param button string
TrackerLinePool.OnClickQuest = function(self, button)
Questie:Debug(Questie.DEBUG_DEVELOP, "[TrackerLinePool:_OnClickQuest] button:", button, "Shift:", IsShiftKeyDown(), "Quest:", self.Quest and self.Quest.name or "nil")
if (not self.Quest) then
return
end
if TrackerMenu.menuFrame:IsShown() then
LibDropDown:CloseDropDownMenus()
end
Questie:Debug(Questie.DEBUG_DEVELOP, "[TrackerLinePool:_OnClickQuest] bindUntrack:", Questie.db.profile.trackerbindUntrack, "IsBindTrue:", TrackerUtils:IsBindTrue(Questie.db.profile.trackerbindUntrack, button))
if TrackerUtils:IsBindTrue(Questie.db.profile.trackerbindSetTomTom, button) then
local spawn, zone, name = QuestieMap:GetNearestQuestSpawn(self.Quest)
if spawn then
TrackerUtils:SetTomTomTarget(name, zone, spawn[1], spawn[2])
end
elseif TrackerUtils:IsBindTrue(Questie.db.profile.trackerbindUntrack, button) then
if (IsModifiedClick("CHATLINK") and ChatEdit_GetActiveWindow()) then
-- Follow Ascension's native pattern: get quest log index and use native linking
local questLogIndex = GetQuestLogIndexByID(self.Quest.Id)
if questLogIndex then
local questLink = GetQuestLink(questLogIndex)
if questLink then
ChatEdit_InsertLink(questLink)
end
end
else
local questLogIndex = GetQuestLogIndexByID(self.Quest.Id)
if questLogIndex and questLogIndex > 0 then
RemoveQuestWatch(questLogIndex)
end
QuestieTracker:UntrackQuestId(self.Quest.Id)
local questLogFrame = QuestLogExFrame or ClassicQuestLog or QuestLogFrame
if questLogFrame:IsShown() then
QuestLog_Update()
end
end
elseif TrackerUtils:IsBindTrue(Questie.db.profile.trackerbindOpenQuestLog, button) then
TrackerUtils:ShowQuestLog(self.Quest)
elseif button == "RightButton" then
local menu = TrackerMenu:GetMenuForQuest(self.Quest)
LibDropDown:EasyMenu(menu, TrackerMenu.menuFrame, "cursor", 0, 0, "MENU")
end
end
---@param button string
TrackerLinePool.OnClickAchieve = function(self, button)
Questie:Debug(Questie.DEBUG_DEVELOP, "[TrackerLinePool:_OnClickAchieve]")
if (not self.Quest) then
return
end
if TrackerMenu.menuFrame:IsShown() then
LibDropDown:CloseDropDownMenus()
end
if TrackerUtils:IsBindTrue(Questie.db.profile.trackerbindUntrack, button) then
if (IsModifiedClick("CHATLINK") and ChatEdit_GetActiveWindow()) then
ChatEdit_InsertLink(GetAchievementLink(self.Quest.Id))
else
if Questie.db.char.trackedAchievementIds[self.Quest.Id] then
QuestieTracker:UntrackAchieveId(self.Quest.Id)
QuestieTracker:UpdateAchieveTrackerCache(self.Quest.Id)
if (not AchievementFrame) then
AchievementFrame_LoadUI()
end
AchievementFrameAchievements_ForceUpdate()
QuestieCombatQueue:Queue(function()
QuestieTracker:Update()
end)
else
-- Assume this is an Objective of an Achievement
UIErrorsFrame:AddMessage(format(l10n("You can't untrack an objective of an achievement.")), 1.0, 0.1, 0.1, 1.0)
end
end
elseif TrackerUtils:IsBindTrue(Questie.db.profile.trackerbindOpenQuestLog, button) then
if (not AchievementFrame) then
AchievementFrame_LoadUI()
end
if (not AchievementFrame:IsShown()) then
AchievementFrame_ToggleAchievementFrame()
AchievementFrame_SelectAchievement(self.Quest.Id)
else
if (AchievementFrameAchievements.selection ~= self.Quest.Id) then
AchievementFrame_SelectAchievement(self.Quest.Id)
end
end
elseif button == "RightButton" then
local menu = TrackerMenu:GetMenuForAchievement(self.Quest)
LibDropDown:EasyMenu(menu, TrackerMenu.menuFrame, "cursor", 0, 0, "MENU")
end
end
TrackerLinePool.OnHighlightEnter = function(self)
local highestIndex = TrackerLinePool.GetHighestIndex()
for i = 1, highestIndex do
local line = linePool[i]
line:SetAlpha(0.5)
if (line.Quest ~= nil and line.Quest == self.Quest) or (line.expandZone ~= nil and self:GetParent().expandZone ~= nil and line.expandZone.zoneId == self:GetParent().expandZone.zoneId) then
line:SetAlpha(1)
end
end
end
TrackerLinePool.OnHighlightLeave = function()
local highestIndex = TrackerLinePool.GetHighestIndex()
for i = 1, highestIndex do
linePool[i]:SetAlpha(1)
end
end
---@param mode string
TrackerLinePool.SetMode = function(self, mode)
if mode ~= self.mode then
self.mode = mode
if mode == "zone" then
local trackerFontSizeZone = Questie.db.profile.trackerFontSizeZone
self.label:SetFont(LSM30:Fetch("font", Questie.db.profile.trackerFontZone), trackerFontSizeZone, Questie.db.profile.trackerFontOutline)
self.label:SetHeight(trackerFontSizeZone)
elseif mode == "quest" or mode == "achieve" then
local trackerFontSizeQuest = Questie.db.profile.trackerFontSizeQuest
self.label:SetFont(LSM30:Fetch("font", Questie.db.profile.trackerFontQuest), trackerFontSizeQuest, Questie.db.profile.trackerFontOutline)
self.label:SetHeight(trackerFontSizeQuest)
self.button = nil
elseif mode == "objective" then
local trackerFontSizeObjective = Questie.db.profile.trackerFontSizeObjective
self.label:SetFont(LSM30:Fetch("font", Questie.db.profile.trackerFontObjective), trackerFontSizeObjective, Questie.db.profile.trackerFontOutline)
self.label:SetHeight(trackerFontSizeObjective)
end
end
end