local addonName, QuestKing = ... local opt = QuestKing.options -- quest "The Arena of Annihilation" is in "Kun-Lai Summit" zone header... ---- Options -- low freq local opt_font = opt.font local opt_fontChallengeTimer = opt.fontChallengeTimer local opt_fontSize = opt.fontSize local opt_fontStyle = opt.fontStyle local opt_fontLayer = opt.fontLayer local opt_positionPresets = opt.positionPresets local opt_tooltipAnchor = opt.tooltipAnchor local opt_tooltipScale = opt.tooltipScale local opt_enableItemPopups = opt.enableItemPopups local opt_subzoneHeuristicHighlight = opt.subzoneHeuristicHighlight -- high freq local opt_buttonWidth = opt.buttonWidth local opt_lineHeight = opt.lineHeight local opt_titleHeight = opt.titleHeight local opt_itemAnchorSide = opt.itemAnchorSide local opt_showCompletedObjectives = opt.showCompletedObjectives local opt_updateRate = opt.updateRate local opt_colors = opt.colors ---- Locals local fEvents = CreateFrame("Frame", "QuestKing_EventsFrame") local fTimerMonitor = CreateFrame("Frame", "QuestKing_TimerMonitorFrame") local fCombat = CreateFrame("Frame", "QuestKing_CombatFrame") local headerList = {} -- updated by buildQuestSortTable local questSortTable = {} -- " local totalQuestCount = 0 -- " local trackedAchievementCache = {} local updatedObjectives = {} -- objectives updated since last updateTracker local achievementTimers = {} local achievementTimersMeta = {} local numWatchButtons = 0 -- total watch buttons local numButtonsShown = 0 -- buttons curtently in use local prev_GetNumQuestLogEntries = 0 -- used to determine if updateTracker needs to call buildQuestTable local prev_GetNumQuestWatches = 0 -- " local cached_numQuestTimers = 0 -- used to determine if the number of timers has changed while timers are running in update mode local watchMoney = false -- set true if a quest we're watching needs money local OBJECTIVE_PATTERN = "(.*):%s*([%d]+)%s*/%s*([%d]+)" local db = nil -- savedvariables local dbc = nil local newPlayerLevel = nil local itemPopups = {} local QUEST_START_ITEMS = nil local LOOT_SELF_REGEX = gsub(LOOT_ITEM_SELF, "%%s", "(.+)") local checkCombat = false ---- ############################ -- Upvalues local _G = _G local pairs = pairs local format = format local floor = math.floor local math_modf = math.modf local math_ceil = math.ceil local GetTime = GetTime local GetQuestTimers = GetQuestTimers local SecondsToTime = SecondsToTime local GetQuestLink = GetQuestLink local GetQuestLogTitle = GetQuestLogTitle local GetNumQuestLogEntries = GetNumQuestLogEntries local GetQuestLogQuestText = GetQuestLogQuestText local GetNumQuestLeaderBoards = GetNumQuestLeaderBoards -- Local functions local QuestKing_Tracker, WatchButton local checkCombatTimer, startCombatTimer, checkPlayerLevelUp, parseLoot, UseContainerItemByID, GetTimeStringFromSecondsShort local hookQuestWatch local updateTracker local updateTrackerChallengeTimers, setButtonToChallengeTimer, updateChallengeMedal, onUpdateChallengeTimer local updateTrackerScenarios, setButtonToScenario local updateTrackerQuestTimers, setButtonToQuestTimer, onUpdateQuestTimer local updateTrackerPopups, setButtonToPopup, setButtonToItemPopup local updateTrackerQuests, setButtonToQuest local updateTrackerAchievements, setButtonToAchievement, onUpdateAchievementTimer local setButtonToProvingGroundsTimer, onUpdateProvingGroundsTimer, UpdateProvingGroundsBar local buildQuestSortTable, getQuestTaggedTitle, colorGradient, getObjectiveColor -- Tracker function QuestKing:CreateTracker () local frame = CreateFrame("Frame", "QuestKing_Tracker", UIParent) QuestKing_Tracker = frame QuestKing:PositionTracker() frame:SetWidth(opt_buttonWidth) frame:SetHeight(opt_titleHeight) -- frame:SetBackdrop({ -- bgFile = "Interface/Tooltips/UI-Tooltip-Background", -- insets = { left = 0, right = 0, top = 0, bottom = 0 } -- }) -- frame:SetBackdropColor(0,0,0,1) -- titlebar local titlebar = CreateFrame("Button", nil, frame) titlebar:SetWidth(opt_buttonWidth) titlebar:SetHeight(opt_titleHeight) titlebar:SetPoint("TOPLEFT", UIParent, "TOPLEFT", 0, -100) -- titlebar:SetBackdrop({ -- bgFile = "Interface/Tooltips/UI-Tooltip-Background", -- insets = { left = 0, right = 0, top = 0, bottom = 0 } -- }) -- titlebar:SetBackdropColor(1, 0, 0, 0) titlebar.parent = frame frame.titlebar = titlebar -- minimize button local minimizeButton = CreateFrame("Button", "QuestKing_TrackerMinimizeButton", titlebar) minimizeButton:SetWidth(15) minimizeButton:SetHeight(15) local tex = minimizeButton:CreateTexture() tex:SetPoint("CENTER") tex:SetTexture([[Interface\Buttons\UI-Quickslot2]]) tex:SetWidth(22) tex:SetHeight(22) minimizeButton:SetNormalTexture(tex) local tex = minimizeButton:CreateTexture() tex:SetPoint("CENTER") tex:SetTexture([[Interface\Buttons\UI-Quickslot2]]) tex:SetWidth(15) tex:SetHeight(15) minimizeButton:SetPushedTexture(tex) local tex = minimizeButton:CreateTexture() tex:SetPoint("CENTER") tex:SetTexture([[Interface\Buttons\UI-Quickslot-Depress]]) tex:SetWidth(15) tex:SetHeight(15) minimizeButton:SetHighlightTexture(tex, "ADD") local label = minimizeButton:CreateFontString(nil, opt_fontLayer) label:SetFont(opt_font, opt_fontSize, opt_fontStyle) label:SetJustifyH("CENTER") label:SetJustifyV("MIDDLE") label:SetTextColor(opt_colors.TrackerTitlebarText[1], opt_colors.TrackerTitlebarText[2], opt_colors.TrackerTitlebarText[3]) label:SetShadowOffset(1, -1) label:SetShadowColor(0, 0, 0, 1) label:SetPoint("CENTER", 1, 0.5) label:SetText("+") minimizeButton.label = label minimizeButton:RegisterForClicks("LeftButtonUp", "RightButtonUp") minimizeButton:SetScript("OnClick", QuestKing.MinimizeButtonOnClick) -- mode button local modeButton = CreateFrame("Button", "QuestKing_TrackerModeButton", titlebar) modeButton:SetWidth(15) modeButton:SetHeight(15) local tex = modeButton:CreateTexture() tex:SetPoint("CENTER") tex:SetTexture([[Interface\Buttons\UI-Quickslot2]]) tex:SetWidth(22) tex:SetHeight(22) modeButton:SetNormalTexture(tex) local tex = modeButton:CreateTexture() tex:SetPoint("CENTER") tex:SetTexture([[Interface\Buttons\UI-Quickslot2]]) tex:SetWidth(15) tex:SetHeight(15) modeButton:SetPushedTexture(tex) local tex = modeButton:CreateTexture() tex:SetPoint("CENTER") tex:SetTexture([[Interface\Buttons\UI-Quickslot-Depress]]) tex:SetWidth(15) tex:SetHeight(15) modeButton:SetHighlightTexture(tex, "ADD") local label = modeButton:CreateFontString(nil, opt_fontLayer) label:SetFont(opt_font, opt_fontSize, opt_fontStyle) label:SetJustifyH("CENTER") label:SetJustifyV("MIDDLE") label:SetTextColor(opt_colors.TrackerTitlebarText[1], opt_colors.TrackerTitlebarText[2], opt_colors.TrackerTitlebarText[3]) label:SetShadowOffset(1, -1) label:SetShadowColor(0, 0, 0, 1) label:SetPoint("CENTER", 1, 0.5) label:SetText("Q") modeButton.label = label modeButton:RegisterForClicks("LeftButtonUp", "RightButtonUp") modeButton:SetScript("OnClick", QuestKing.ModeButtonOnClick) -- titlebar text local titlebarText = titlebar:CreateFontString(nil, opt_fontLayer) titlebarText:SetFont(opt_font, opt_fontSize, opt_fontStyle) titlebarText:SetJustifyH("RIGHT") titlebarText:SetTextColor(opt_colors.TrackerTitlebarText[1], opt_colors.TrackerTitlebarText[2], opt_colors.TrackerTitlebarText[3]) titlebarText:SetShadowOffset(1, -1) titlebarText:SetShadowColor(0, 0, 0, 1) titlebarText:SetText("0/"..MAX_QUESTS) frame.titlebarText = titlebarText -- layout if true then minimizeButton:SetPoint("RIGHT", titlebar, "RIGHT", 100, 0) modeButton:SetPoint("RIGHT", minimizeButton, "LEFT", 100, 0) titlebarText:SetPoint("RIGHT", modeButton, "LEFT", 100, 0) end --frame:SetPoint("TOPLEFT", titlebar) --frame:SetPoint("BOTTOMLEFT", titlebar) --frame:SetWidth(opt_buttonWidth) titlebar:SetPoint("TOPLEFT", frame) -- frame:SetMovable(true) -- titlebar:SetScript("OnMouseDown", function () -- frame:StartMoving() -- end) -- titlebar:SetScript("OnMouseUp", function () -- frame:StopMovingOrSizing() -- frame:SetUserPlaced(false) -- end) end local measureFrame = nil function QuestKing:ResizeTracker (lastShown) if (not lastShown) then QuestKing_Tracker:SetHeight(opt_titleHeight) else if not measureFrame then measureFrame = CreateFrame("Frame", nil, UIParent) measureFrame:SetWidth(opt_buttonWidth) -- measureFrame:SetBackdrop({ -- bgFile = "Interface/Tooltips/UI-Tooltip-Background", -- insets = { left = 0, right = 0, top = 0, bottom = 0 } -- }) -- measureFrame:SetBackdropColor(0,1,0,0.5) end measureFrame:ClearAllPoints() measureFrame:SetPoint("TOPLEFT", QuestKing_Tracker) measureFrame:SetPoint("BOTTOMLEFT", lastShown) local height = measureFrame:GetHeight() QuestKing_Tracker:SetHeight(height) end end function QuestKing:PositionTracker() local preset = opt_positionPresets[dbc.trackerPositionPreset] if not preset then dbc.trackerPositionPreset = 1 preset = opt_positionPresets[1] end QuestKing_Tracker:SetPoint(unpack(preset)) end function QuestKing:CycleTrackerPosition() local new = dbc.trackerPositionPreset + 1 if new > #opt_positionPresets then new = 1 end dbc.trackerPositionPreset = new QuestKing:PositionTracker() end -- Events function checkCombatTimer () if not InCombatLockdown() then --D("FINISH") checkCombat = false fCombat:SetScript("OnUpdate", nil) QuestKing_TrackerModeButton.label:SetTextColor(opt_colors.TrackerTitlebarText[1], opt_colors.TrackerTitlebarText[2], opt_colors.TrackerTitlebarText[3]) updateTracker() end end function startCombatTimer () if (checkCombat == false) then checkCombat = true fCombat:SetScript("OnUpdate", checkCombatTimer) QuestKing_TrackerModeButton.label:SetTextColor(1, 0, 0) end end function checkPlayerLevelUp () local level = UnitLevel("player") if level >= newPlayerLevel then QuestKing_Tracker:SetScript("OnUpdate", nil) updateTracker() else -- end end function parseLoot (msg) local _, _, link = string.find(msg, LOOT_SELF_REGEX) if link then local _, _, itemID, itemName = string.find(link, "item:(%d+):.*|h%[(.+)%]|h") itemID = tonumber(itemID) if itemID then if tContains(QUEST_START_ITEMS, itemID) then itemPopups[itemID] = itemName PlaySoundFile("Sound\\Interface\\PVPWarningHordeMono.wav") updateTracker() end end end end function UseContainerItemByID(searchID) for i = 0,4 do for j = 1, GetContainerNumSlots(i) do local id = GetContainerItemID(i,j) if id == searchID then UseContainerItem(i, j) return end end end end function QuestKing_HandleEvent (self, event, ...) --D("|cffaaccff"..event, ...) if (event == "CHAT_MSG_LOOT") then parseLoot(...) elseif (event == "PLAYER_MONEY") and (watchMoney) then updateTracker() elseif (event == "PLAYER_LEVEL_UP") then -- local v = 60; D("= " .. Hex(GetQuestDifficultyColor(v))..v) -- local v = 61; D("= " .. Hex(GetQuestDifficultyColor(v))..v) -- local v = 62; D("= " .. Hex(GetQuestDifficultyColor(v))..v) -- local v = 63; D("= " .. Hex(GetQuestDifficultyColor(v))..v) -- local v = 64; D("= " .. Hex(GetQuestDifficultyColor(v))..v) -- D("GreenRange is " .. GetQuestGreenRange()) newPlayerLevel = ... QuestKing_Tracker:SetScript("OnUpdate", checkPlayerLevelUp) elseif (event == "QUEST_LOG_UPDATE") or (event == "ITEM_PUSH") then updateTracker() elseif (event == "UI_INFO_MESSAGE") then local desc = ... local p1, p2, quantName, quantCur, quantMax = string.find(desc, OBJECTIVE_PATTERN) if quantName then updatedObjectives[quantName] = true end elseif (event == "TRACKED_ACHIEVEMENT_UPDATE") then -- can i ignore this/updateTracker entirely if achieveID isnt in trackedAchievementCache? (tContains) -- if i do, tracking a quest with a timer that's already started ma not show it (for a while...?) local achievementID, criteriaID, timeElapsed, timeLimit = ... -- if timeElapsed and timeLimit then if timeElapsed >= timeLimit then achievementTimers[criteriaID] = nil achievementTimersMeta[achievementID] = nil else achievementTimers[criteriaID] = achievementTimers[criteriaID] or {} achievementTimers[criteriaID].startTime = GetTime() - timeElapsed achievementTimers[criteriaID].duration = timeLimit achievementTimersMeta[achievementID] = achievementTimers[criteriaID] end end --D(">>>") updateTracker() elseif (event == "QUEST_AUTOCOMPLETE") then local questId = ... if (AddAutoQuestPopUp(questId, "COMPLETE")) then PlaySound("UI_AutoQuestComplete") end updateTracker() elseif (event == "SCENARIO_UPDATE") or (event == "SCENARIO_CRITERIA_UPDATE") then -- D("SCENARIO_UPDATE") updateTracker() elseif (event == "PLAYER_ENTERING_WORLD") or (event == "WORLD_STATE_TIMER_START") or (event == "WORLD_STATE_TIMER_STOP") then -- challenge/scenario zone in + timers updateTracker() elseif (event == "ZONE_CHANGED") or (event == "ZONE_CHANGED_INDOORS") or (event == "ZONE_CHANGED_NEW_AREA") then -- zone heuristic highlight updateTracker() end end function QuestKing.MinimizeButtonOnClick (self, mouse, down) if mouse == "RightButton" then QuestKing:CycleTrackerPosition() else if dbc.trackerCollapsed then dbc.trackerCollapsed = false --PlaySound("igMiniMapOpen") else dbc.trackerCollapsed = true --PlaySound("igMiniMapClose") end updateTracker() end end function QuestKing.ModeButtonOnClick (self, mouse, down) if mouse == "RightButton" then if IsAltKeyDown() then SetSuperTrackedQuestID(0) elseif dbc.displayMode ~= "combined" then dbc.displayMode = "combined" else dbc.displayMode = "quests" end else if dbc.displayMode == "quests" then dbc.displayMode = "achievements" else dbc.displayMode = "quests" end end updateTracker() end function QuestKing.ButtonOnClick (self, mouse, down) local button = self if button.type == "popup" then if button.popupType == "ITEM" then if mouse == "RightButton" then itemPopups[button.itemID] = nil updateTracker() else --if InCombatLockdown() then return end UseContainerItemByID(button.itemID) itemPopups[button.itemID] = nil updateTracker() end elseif mouse == "RightButton" then RemoveAutoQuestPopUp(self.questID) updateTracker() else if button.popupType == "OFFER" then QuestLog_OpenToQuest(self.questIndex) RemoveAutoQuestPopUp(self.questID) updateTracker() elseif button.popupType == "COMPLETE" then ShowQuestComplete(self.questIndex) RemoveAutoQuestPopUp(self.questID) updateTracker() end end end end function QuestKing.TitleButtonOnClick (self, mouse, down) local button = self.parent if (IsModifiedClick("CHATLINK") and ChatEdit_GetActiveWindow()) then if (button.type == "quest") then local questLink = GetQuestLink(button.questIndex) if (questLink) then ChatEdit_InsertLink(questLink) return end elseif (button.type == "achievement") then local achievementLink = GetAchievementLink(button.achievementID) if (achievementLink) then ChatEdit_InsertLink(achievementLink) return end end end if button.type == "header" then local headerName = button.headerName if dbc.collapsedHeaders[headerName] then dbc.collapsedHeaders[headerName] = nil else dbc.collapsedHeaders[headerName] = true end updateTracker() elseif button.type == "quest" then if IsAltKeyDown() then if mouse == "RightButton" then RemoveQuestWatch(button.questIndex) updateTracker() return else if dbc.collapsedQuests[button.questID] then dbc.collapsedQuests[button.questID] = nil else dbc.collapsedQuests[button.questID] = true end updateTracker() return end end if mouse == "RightButton" then WORLDMAP_SETTINGS.selectedQuestId = button.questID SetSuperTrackedQuestID(button.questID) QuestPOIUpdateIcons() if WorldMapFrame:IsShown() then HideUIPanel(WorldMapFrame) ShowUIPanel(WorldMapFrame) end else if (QuestLogFrame:IsShown()) and (QuestLogFrame.selectedIndex == button.questIndex) then HideUIPanel(QuestLogFrame) else QuestLog_OpenToQuest(button.questIndex) ShowUIPanel(QuestLogFrame) end end elseif button.type == "achievement" then if IsAltKeyDown() then if mouse == "RightButton" then RemoveTrackedAchievement(button.achievementID) updateTracker() return else if dbc.collapsedAchievements[button.achievementID] then dbc.collapsedAchievements[button.achievementID] = nil else dbc.collapsedAchievements[button.achievementID] = true end updateTracker() return end end if (not AchievementFrame) then AchievementFrame_LoadUI() end if (not AchievementFrame:IsShown()) then AchievementFrame_ToggleAchievementFrame() AchievementFrame_SelectAchievement(button.achievementID) else if (AchievementFrameAchievements.selection ~= button.achievementID) then AchievementFrame_SelectAchievement(button.achievementID) else AchievementFrame_ToggleAchievementFrame() end end end end function QuestKing.TitleButtonOnEnter (self, event, ...) local button = self.parent if (button.type == "quest") or (button.type == "questtimer") then local link = GetQuestLink(button.questIndex) if link then GameTooltip:SetOwner(self, opt_tooltipAnchor) if opt_tooltipScale then if not GameTooltip.__QuestKingPreviousScale then GameTooltip.__QuestKingPreviousScale = GameTooltip:GetScale() end GameTooltip:SetScale(opt_tooltipScale) end GameTooltip:SetHyperlink(link) GameTooltip:Show() end elseif (button.type == "achievement") then local link = GetAchievementLink(button.achievementID) if link then GameTooltip:SetOwner(self, opt_tooltipAnchor) if opt_tooltipScale then if not GameTooltip.__QuestKingPreviousScale then GameTooltip.__QuestKingPreviousScale = GameTooltip:GetScale() end GameTooltip:SetScale(opt_tooltipScale) end GameTooltip:SetHyperlink(link) GameTooltip:Show() end elseif (button.type == "scenario") then local stageName, stageDescription, numCriteria = C_Scenario.GetStepInfo() GameTooltip:SetOwner(self, opt_tooltipAnchor) if opt_tooltipScale then if not GameTooltip.__QuestKingPreviousScale then GameTooltip.__QuestKingPreviousScale = GameTooltip:GetScale() end GameTooltip:SetScale(opt_tooltipScale) end GameTooltip:AddLine(stageName, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) GameTooltip:AddLine(" ") GameTooltip:AddLine(stageDescription, 1, 1, 1, 1) GameTooltip:Show() end end function QuestKing.TitleButtonOnLeave (self, event, ...) if opt_tooltipScale then local oldScale = GameTooltip.__QuestKingPreviousScale or 1 GameTooltip.__QuestKingPreviousScale = nil GameTooltip:SetScale(oldScale) end GameTooltip:Hide() end function hookQuestWatch () --D("|cffaaffcchookQuestWatch") updateTracker(true) end -- Watch buttons local WatchButtonPrototype = CreateFrame("Frame") local WatchButton = setmetatable({}, { __index = WatchButtonPrototype }) WatchButton.__index = WatchButton local watchButtonList = {} do function WatchButton:GetNext() numButtonsShown = numButtonsShown + 1 local wb = self:Get(numButtonsShown) wb:Reset() return wb end function WatchButton:Get(num) local button = watchButtonList[num] if button then return button end local name = "QuestKing_WatchButton" .. num -- button button = CreateFrame("Button", name, QuestKing_Tracker) button:SetBackdrop({ bgFile = "Interface/Tooltips/UI-Tooltip-Background", insets = { left = 0, right = 0, top = 0, bottom = 0 } }) button:SetBackdropColor(0, 0, 0, 0) button:SetWidth(opt_buttonWidth) button:SetHeight(opt_lineHeight) button:SetPoint("TOPLEFT", 0, 0) local buttonHighlight = button:CreateTexture() buttonHighlight:SetAllPoints(button) buttonHighlight:SetTexture([[Interface\QuestFrame\UI-QuestLogTitleHighlight]]) buttonHighlight:SetAlpha(0.6) button:RegisterForClicks("LeftButtonUp", "RightButtonUp") button:EnableMouse(false) button:SetHighlightTexture(buttonHighlight, "ADD") button:SetScript("OnClick", QuestKing.ButtonOnClick) -- icons local iconExclamationMark = button:CreateTexture(nil, nil, "QuestIcon-Exclamation") iconExclamationMark:ClearAllPoints() iconExclamationMark:SetPoint("RIGHT", button, "LEFT") iconExclamationMark:SetHeight(opt_lineHeight * 2 - 2) iconExclamationMark:SetWidth(opt_lineHeight * 1.4) iconExclamationMark:Hide() button.iconExclamationMark = iconExclamationMark local animGroup = iconExclamationMark:CreateAnimationGroup() local a1 = animGroup:CreateAnimation("Alpha") a1:SetStartDelay(0.25); a1:SetDuration(0.33); a1:SetChange(-1); a1:SetOrder(1); a1:SetSmoothing("IN"); animGroup:SetLooping("BOUNCE") iconExclamationMark.animGroup = animGroup local iconQuestionMark = button:CreateTexture(nil, nil, "QuestIcon-QuestionMark") iconQuestionMark:ClearAllPoints() iconQuestionMark:SetPoint("RIGHT", button, "LEFT") iconQuestionMark:SetHeight(opt_lineHeight * 2 - 2) iconQuestionMark:SetWidth(opt_lineHeight * 1.4) iconQuestionMark:Hide() button.iconQuestionMark = iconQuestionMark local animGroup = iconQuestionMark:CreateAnimationGroup() local a1 = animGroup:CreateAnimation("Alpha") a1:SetStartDelay(0.25); a1:SetDuration(0.33); a1:SetChange(-1); a1:SetOrder(1); a1:SetSmoothing("IN"); animGroup:SetLooping("BOUNCE") iconQuestionMark.animGroup = animGroup -- title button local titleButton = CreateFrame("Button", nil, button) titleButton:SetPoint("BOTTOMLEFT", 0, 0) titleButton:SetWidth(opt_buttonWidth) titleButton:SetHeight(opt_lineHeight) titleButton.parent = button titleButton:RegisterForClicks("LeftButtonUp", "RightButtonUp") titleButton:SetScript("OnClick", QuestKing.TitleButtonOnClick) titleButton:SetScript("OnEnter", QuestKing.TitleButtonOnEnter) titleButton:SetScript("OnLeave", QuestKing.TitleButtonOnLeave) button.titleButton = titleButton -- title button hover local tex = titleButton:CreateTexture() tex:SetAllPoints(titleButton) tex:SetTexture([[Interface\QuestFrame\UI-QuestLogTitleHighlight]]) tex:SetAlpha(0.6) titleButton:EnableMouse(true) titleButton:SetHighlightTexture(tex, "ADD") -- title text local title = button:CreateFontString(nil, opt_fontLayer) title:SetFont(opt_font, opt_fontSize, opt_fontStyle) title:SetJustifyH("LEFT") title:SetTextColor(1, 1, 0) title:SetShadowOffset(1, -1) title:SetShadowColor(0, 0, 0, 1) title:SetPoint("TOPLEFT", 0, 0) title:SetWidth(opt_buttonWidth) title:SetHeight(opt_lineHeight) title:SetText("") button.title = title -- variables button.linesLeft = {} button.linesRight = {} button.currentLine = 0 button.updateTimer = opt_updateRate button.challengeBarShown = false button.type = "none" button.name = name setmetatable(button, WatchButton) watchButtonList[num] = button numWatchButtons = numWatchButtons + 1 button.buttonNumber = numWatchButtons return button end function WatchButton:Reset() self.currentLine = 0 if self.itemButton and self.itemButton:IsShown() then if InCombatLockdown() then startCombatTimer() else self.itemButton:Hide() end end self:SetBackdropColor(0, 0, 0, 0) self:SetScript("OnUpdate", nil) self.updateTimer = opt_updateRate self:EnableMouse(false) self.titleButton:EnableMouse(true) self.iconExclamationMark.animGroup:Stop() self.iconExclamationMark:Hide() self.iconQuestionMark.animGroup:Stop() self.iconQuestionMark:Hide() if (self.challengeBarShown) then self.challengeBarShown = false self.challengeBar:Hide() end end function WatchButton:CreateLines() local left = self:CreateFontString(nil, opt_fontLayer) left:SetFont(opt_font, opt_fontSize, opt_fontStyle) left:SetJustifyH("LEFT") left:SetTextColor(1, 1, 0) left:SetShadowOffset(1, -1) left:SetShadowColor(0, 0, 0, 1) left:SetPoint("TOPLEFT", 0, 0) left:SetJustifyV("TOP") tinsert(self.linesLeft, left) local right = self:CreateFontString(nil, opt_fontLayer) right:SetFont(opt_font, opt_fontSize, opt_fontStyle) right:SetJustifyH("LEFT") right:SetTextColor(1, 1, 0) right:SetShadowOffset(1, -1) right:SetShadowColor(0, 0, 0, 1) right:SetPoint("TOPLEFT", 0, 0) right:SetJustifyV("TOP") tinsert(self.linesRight, right) local flash = self:CreateTexture() flash:SetPoint("TOPLEFT", left) flash:SetPoint("BOTTOMLEFT", left) flash:SetWidth(opt_buttonWidth) flash:SetTexture([[Interface\QuestFrame\UI-QuestLogTitleHighlight]]) flash:SetBlendMode("ADD") flash:SetVertexColor(opt_colors.ObjectiveFlash[1], opt_colors.ObjectiveFlash[2], opt_colors.ObjectiveFlash[3], 0) local animGroup = flash:CreateAnimationGroup() local a1 = animGroup:CreateAnimation("Alpha") local a2 = animGroup:CreateAnimation("Alpha") a1:SetStartDelay(0) a1:SetDuration(0.15) a1:SetChange(1) a1:SetOrder(1) --a1:SetSmoothing("IN") a2:SetStartDelay(0.25) a2:SetDuration(0.50) a2:SetChange(-1) a2:SetOrder(2) --a1:SetSmoothing("OUT") left.flash = flash left.flash.animGroup = animGroup return left, right end function WatchButton:AddLine(textleft, textright, r, g, b, a) local currentLine = self.currentLine + 1 self.currentLine = currentLine local left, right if self.linesLeft[currentLine] then left = self.linesLeft[currentLine] right = self.linesRight[currentLine] else left, right = self:CreateLines() end left.isTimer = false left:SetText(textleft) right:SetText(textright) if r ~= nil then left:SetTextColor(r, g, b, a or 1) right:SetTextColor(r, g, b, a or 1) end return left end function WatchButton:Layout() local height = 0 local lastLine = nil for i = 1, #self.linesLeft do local left, right = self.linesLeft[i], self.linesRight[i] if i > self.currentLine then left:Hide() right:Hide() left.flash.animGroup:Stop() else left:Show() right:Show() if lastLine == nil then left:SetPoint("TOPLEFT", self.title, "BOTTOMLEFT", 0, 0) else left:SetPoint("TOPLEFT", lastLine, "BOTTOMLEFT", 0, 0) end right:SetPoint("TOPLEFT", left, "TOPRIGHT", -1, 0) left:SetWidth(0) left:SetHeight(0) local lenLeft = left:GetStringWidth() local lenRight = right:GetStringWidth() if (lenLeft + lenRight) > opt_buttonWidth then --left:SetHeight(left:GetStringHeight()) left:SetHeight(opt_lineHeight) left:SetWidth(opt_buttonWidth - lenRight) else left:SetHeight(opt_lineHeight) end lastLine = left height = (opt_lineHeight * i) end end -- if (self.type == "popup") then -- self.iconExclamationMark:SetHeight((opt_lineHeight * 2 - 2) * 3.5) -- self.iconExclamationMark:SetWidth((opt_lineHeight * 1.4) * 3.5) -- self.iconQuestionMark:SetHeight((opt_lineHeight * 2 - 2) * 3.5) -- self.iconQuestionMark:SetWidth((opt_lineHeight * 1.4) * 3.5) -- height = height * 6 -- end if (self.challengeBarShown) then height = height + 18 end self:SetHeight(opt_lineHeight + height) end end -- Tracker Updating function updateTracker (forceBuild) local numEntries = GetNumQuestLogEntries() local numWatches = GetNumQuestWatches() if forceBuild then buildQuestSortTable() prev_GetNumQuestLogEntries = numEntries -- since we built it... is this safe? prev_GetNumQuestWatches = numWatches else if numEntries ~= prev_GetNumQuestLogEntries then buildQuestSortTable() elseif numWatches ~= prev_GetNumQuestWatches then buildQuestSortTable() end prev_GetNumQuestLogEntries = numEntries prev_GetNumQuestWatches = numWatches end --D("!updateTracker") numButtonsShown = 0 watchMoney = false -- titlebar if dbc.trackerCollapsed == true then QuestKing_TrackerMinimizeButton.label:SetText("+") else QuestKing_TrackerMinimizeButton.label:SetText("-") end -- challenge timers local hasTimer = GetWorldElapsedTimers() local ProvingGroundsType, _, _, _ = C_Scenario.GetProvingGroundsInfo() if hasTimer then if ProvingGroundsType ~= 0 then updateTrackerChallengeTimers(2) else updateTrackerChallengeTimers(GetWorldElapsedTimers()) end end -- scenarios local inScenario = C_Scenario.IsInScenario() if inScenario then updateTrackerScenarios() end -- quest timers if GetQuestTimers() then updateTrackerQuestTimers() end -- popups --if not dbc.trackerCollapsed then -- if (dbc.displayMode == "combined") or (dbc.displayMode == "quests") then updateTrackerPopups() -- end --end -- achievements trackedAchievementCache = { GetTrackedAchievements() } if not dbc.trackerCollapsed then if (dbc.displayMode == "combined") or (dbc.displayMode == "achievements") then -- add header if we're in a scenario since it has its own headers if (inScenario) and (dbc.displayMode == "achievements") then local achheader = WatchButton:GetNext() achheader.type = "header_basic" achheader.title:SetText("Achievements") achheader.title:SetTextColor(opt_colors.AchievementHeader[1], opt_colors.AchievementHeader[2], opt_colors.AchievementHeader[3]) achheader:Layout() end updateTrackerAchievements() end end -- quests if (not inScenario) then if not dbc.trackerCollapsed then if (dbc.displayMode == "combined") or (dbc.displayMode == "quests") then updateTrackerQuests() end end end local numAch = #trackedAchievementCache if dbc.displayMode == "combined" then QuestKing_TrackerModeButton.label:SetText("C") if numAch > 0 then QuestKing_Tracker.titlebarText:SetText(format("%d/%d + %d", totalQuestCount, MAX_QUESTS, numAch)) else QuestKing_Tracker.titlebarText:SetText(format("%d/%d", totalQuestCount, MAX_QUESTS)) end if (numWatches == 0) and (numAch == 0) then QuestKing_Tracker.titlebarText:SetTextColor(opt_colors.TrackerTitlebarTextDimmed[1], opt_colors.TrackerTitlebarTextDimmed[2], opt_colors.TrackerTitlebarTextDimmed[3]) else QuestKing_Tracker.titlebarText:SetTextColor(opt_colors.TrackerTitlebarText[1], opt_colors.TrackerTitlebarText[2], opt_colors.TrackerTitlebarText[3]) end elseif dbc.displayMode == "achievements" then QuestKing_TrackerModeButton.label:SetText("A") QuestKing_Tracker.titlebarText:SetText(numAch) if (numAch == 0) then QuestKing_Tracker.titlebarText:SetTextColor(opt_colors.TrackerTitlebarTextDimmed[1], opt_colors.TrackerTitlebarTextDimmed[2], opt_colors.TrackerTitlebarTextDimmed[3]) else QuestKing_Tracker.titlebarText:SetTextColor(opt_colors.TrackerTitlebarText[1], opt_colors.TrackerTitlebarText[2], opt_colors.TrackerTitlebarText[3]) end else QuestKing_TrackerModeButton.label:SetText("Q") QuestKing_Tracker.titlebarText:SetText(format("%d/%d", totalQuestCount, MAX_QUESTS)) if (numWatches == 0) then QuestKing_Tracker.titlebarText:SetTextColor(opt_colors.TrackerTitlebarTextDimmed[1], opt_colors.TrackerTitlebarTextDimmed[2], opt_colors.TrackerTitlebarTextDimmed[3]) else QuestKing_Tracker.titlebarText:SetTextColor(opt_colors.TrackerTitlebarText[1], opt_colors.TrackerTitlebarText[2], opt_colors.TrackerTitlebarText[3]) end end -- LAYOUT local lastShown = nil if numWatchButtons > 0 then for i = 1, numWatchButtons do local button = watchButtonList[i] if i > numButtonsShown then button:Hide() if (button.itemButton) and (button.itemButton:IsShown()) then if InCombatLockdown() then startCombatTimer() else button.itemButton:Hide() end end elseif lastShown == nil then button:SetPoint("TOPLEFT", QuestKing_Tracker.titlebar, "BOTTOMLEFT", 0, -1) button:Show() lastShown = button else if (button.type == "header") or (button.type == "header_basic") then button:SetPoint("TOPLEFT", lastShown, "BOTTOMLEFT", 0, -4) elseif (lastShown.type == "header") or (lastShown.type == "header_basic") then button:SetPoint("TOPLEFT", lastShown, "BOTTOMLEFT", 0, -3) else button:SetPoint("TOPLEFT", lastShown, "BOTTOMLEFT", 0, -2) end button:Show() lastShown = button end end end QuestKing:ResizeTracker(lastShown) end -- simplified and shortened version of Blizzard equivalent GetTimeStringFromSeconds function GetTimeStringFromSecondsShort (timeAmount) local seconds = timeAmount local hours = floor(seconds / 3600) local minutes = floor((seconds / 60) - (hours * 60)) seconds = seconds - hours * 3600 - minutes * 60 if hours > 0 then return format("%d:%.2d:%.2d", hours, minutes, seconds) else return format("%d:%.2d", minutes, seconds) end end function updateTrackerChallengeTimers (...) for i = 1, select("#", ...) do local timerID = select(i, ...) local description, elapsedTime, isChallengeModeTimer = GetWorldElapsedTime(timerID) if isChallengeModeTimer == 2 then local _, _, _, _, _, _, _, mapID, _ = GetInstanceInfo() if (mapID) then local button = WatchButton:GetNext() button.type = "challengetimer" setButtonToChallengeTimer(button, timerID, elapsedTime, GetChallengeModeMapTimes(mapID)) button:Layout() return end elseif isChallengeModeTimer == 3 then local difficulty, curWave, maxWave, duration = C_Scenario.GetProvingGroundsInfo() local button = WatchButton:GetNext() button.type = "challengetimer" setButtonToProvingGroundsTimer(button, difficulty, elapsedTime, curWave, maxWave, duration) end end end function setButtonToChallengeTimer (button, timerID, elapsedTime, ...) if not (button.challengeMedalTimes) then button.challengeMedalTimes = { } end for i = 1, select("#", ...) do button.challengeMedalTimes[i] = select(i, ...); end button.titleButton:EnableMouse(false) button.title:SetText("") if not button.challengeBar then local challengeBar = CreateFrame("StatusBar", nil, button) challengeBar:SetStatusBarTexture("Interface\\TargetingFrame\\UI-StatusBar") challengeBar:GetStatusBarTexture():SetHorizTile(false) challengeBar:SetStatusBarColor(0, 0.33, 0.61) challengeBar:SetMinMaxValues(0, 100) challengeBar:SetValue(100) challengeBar:SetWidth(opt_buttonWidth - 36) challengeBar:SetHeight(17) challengeBar:SetPoint("BOTTOMLEFT", button, "BOTTOMLEFT", 26, 5) button.challengeBar = challengeBar local border = challengeBar:CreateTexture(nil, "OVERLAY") border:SetTexture([[Interface\Challenges\challenges-main]]) border:SetPoint("TOPLEFT", challengeBar, "TOPLEFT", -5, 5) border:SetPoint("BOTTOMRIGHT", challengeBar, "BOTTOMRIGHT", 5, -5) border:SetTexCoord(0.00097656, 0.13769531, 0.47265625, 0.51757813) challengeBar.border = border local icon = challengeBar:CreateTexture(nil, "OVERLAY") icon:SetTexture([[Interface\Challenges\challenges-plat-sm]]) icon:SetSize(22, 22) icon:SetPoint("RIGHT", challengeBar, "LEFT", -6, 0) icon:SetTexCoord(0.25, 0.7, 0.25, 0.7) challengeBar.icon = icon button.challengeBarIcon = icon local text = challengeBar:CreateFontString(nil, "OVERLAY") text:SetFont(opt_fontChallengeTimer, opt_fontSize, opt_fontStyle) text:SetJustifyH("CENTER") text:SetJustifyV("CENTER") text:SetAllPoints(true) text:SetTextColor(1, 1, 1) text:SetShadowOffset(1, -1) text:SetShadowColor(0, 0, 0, 1) text:SetText("No Medal") challengeBar.text = text button.challengeBarText = text else button.challengeBar:Show() end button.challengeBarShown = true button.challengeTime = 0 button.challengeCurrentMedalTime = -1 button.challengeRecheck = 0 -- adding a little to help reduce sync jitter when difference is floor'd later onUpdateChallengeTimer(button, (elapsedTime + 0.01), true) if (button.challengeCurrentMedalTime) then button:SetScript("OnUpdate", onUpdateChallengeTimer) end end function setButtonToProvingGroundsTimer (button, difficulty, elapsedTime, curWave, maxWave, duration) button.titleButton:EnableMouse(false) button.ProvingGroundsDuration = duration button.title:SetText("") if not button.challengeBar then local challengeBar = CreateFrame("StatusBar", nil, button) challengeBar:SetStatusBarTexture("Interface\\TargetingFrame\\UI-StatusBar") challengeBar:GetStatusBarTexture():SetHorizTile(false) challengeBar:SetStatusBarColor(0, 0.33, 0.61) challengeBar:SetMinMaxValues(0, 100) challengeBar:SetValue(100) challengeBar:SetWidth(opt_buttonWidth - 36) challengeBar:SetHeight(17) challengeBar:SetPoint("BOTTOMLEFT", button, "BOTTOMLEFT", 26, 5) button.challengeBar = challengeBar local border = challengeBar:CreateTexture(nil, "OVERLAY") border:SetTexture([[Interface\Challenges\challenges-main]]) border:SetPoint("TOPLEFT", challengeBar, "TOPLEFT", -5, 5) border:SetPoint("BOTTOMRIGHT", challengeBar, "BOTTOMRIGHT", 5, -5) border:SetTexCoord(0.00097656, 0.13769531, 0.47265625, 0.51757813) challengeBar.border = border local icon = challengeBar:CreateTexture(nil, "OVERLAY") icon:SetTexture([[Interface\Challenges\challenges-plat-sm]]) icon:SetSize(22, 22) icon:SetPoint("RIGHT", challengeBar, "LEFT", -6, 0) icon:SetTexCoord(0.25, 0.7, 0.25, 0.7) challengeBar.icon = icon button.challengeBarIcon = icon local text = challengeBar:CreateFontString(nil, "OVERLAY") text:SetFont(opt_fontChallengeTimer, opt_fontSize, opt_fontStyle) text:SetJustifyH("CENTER") text:SetJustifyV("CENTER") text:SetAllPoints(true) text:SetTextColor(1, 1, 1) text:SetShadowOffset(1, -1) text:SetShadowColor(0, 0, 0, 1) text:SetText("") challengeBar.text = text button.challengeBarText = text else button.challengeBar:Show() end button.challengeBarShown = true button.ProvingGroundsTime = 0 button.ProvingGroundsDurationMax = -1 button.ProvingGroundsCurrentWave = curWave button.ProvingGroundsMaxWave = maxWave button.ProvingGroundsRecheck = 0 -- adding a little to help reduce sync jitter when difference is floor'd later onUpdateProvingGroundsTimer(button, (elapsedTime), true, difficulty) if (button.ProvingGroundsTime) then button:SetScript("OnUpdate", onUpdateProvingGroundsTimer) end end function updateChallengeMedal (self, elapsedTime) local prevMedalTime = 0 for i = #self.challengeMedalTimes, 1, -1 do local curMedalTime = self.challengeMedalTimes[i] if (elapsedTime < curMedalTime) then self.challengeCurrentMedalTime = curMedalTime self.challengeBar:SetMinMaxValues(0, curMedalTime - prevMedalTime) if i == 1 then self.challengeBar:SetStatusBarColor(0.76, 0.38, 0.15) self.challengeBarIcon:SetTexture([[Interface\Challenges\challenges-bronze-sm]]) self.challengeBarIcon:Show() elseif i == 2 then self.challengeBar:SetStatusBarColor(0.64, 0.6, 0.6) self.challengeBarIcon:SetTexture([[Interface\Challenges\challenges-silver-sm]]) self.challengeBarIcon:Show() elseif i == 3 then self.challengeBar:SetStatusBarColor(0.93, 0.67, 0.25) self.challengeBarIcon:SetTexture([[Interface\Challenges\challenges-gold-sm]]) self.challengeBarIcon:Show() elseif i == 4 then self.challengeBar:SetStatusBarColor(0.6, 0.75, 0.7) self.challengeBarIcon:SetTexture([[Interface\Challenges\challenges-plat-sm]]) self.challengeBarIcon:Show() else self.challengeBar:SetStatusBarColor(1, 0.3, 0.3) self.challengeBarIcon:Hide() end return else prevMedalTime = curMedalTime end end -- no medal self.challengeCurrentMedalTime = false self:SetScript("OnUpdate", nil) self.challengeBarText:SetText(CHALLENGES_TIMER_NO_MEDAL) self.challengeBar:SetMinMaxValues(0, 1) self.challengeBar:SetValue(1) self.challengeBar:SetStatusBarColor(0.3, 0.3, 0.3) self.challengeBarIcon:Hide() end function updateProvingGroundsBar (self, elapsedTime, difficulty) local DurTime = self.ProvingGroundsDuration self.challengeBar:SetMinMaxValues(0, DurTime) if elapsedTime < DurTime then self.ProvingGroundsDurationMax = DurTime self.challengeBar:SetMinMaxValues(0, DurTime) if difficulty == 1 then self.challengeBar:SetStatusBarColor(0.76, 0.38, 0.15) self.challengeBarIcon:SetTexture([[Interface\Challenges\challenges-bronze-sm]]) self.challengeBarIcon:Show() elseif difficulty == 2 then self.challengeBar:SetStatusBarColor(0.64, 0.6, 0.6) self.challengeBarIcon:SetTexture([[Interface\Challenges\challenges-silver-sm]]) self.challengeBarIcon:Show() elseif difficulty == 3 then self.challengeBar:SetStatusBarColor(0.93, 0.67, 0.25) self.challengeBarIcon:SetTexture([[Interface\Challenges\challenges-gold-sm]]) self.challengeBarIcon:Show() elseif difficulty == 4 then self.challengeBar:SetStatusBarColor(0.6, 0.75, 0.7) self.challengeBarIcon:SetTexture([[Interface\Challenges\challenges-plat-sm]]) self.challengeBarIcon:Show() end else self.ProvingGroundsDurationMax = -1 elapsedTime = 0 --self:SetScript("OnUpdate", nil) self.challengeBarText:SetText("") self.challengeBar:SetMinMaxValues(0, 1) self.challengeBar:SetValue(0) self.challengeBar:SetStatusBarColor(0.3, 0.3, 0.3) self.challengeBarIcon:Hide() end end function onUpdateChallengeTimer (self, elapsed, manual) local newTime = self.challengeTime + elapsed self.challengeTime = newTime local currentMedalTime = self.challengeCurrentMedalTime if (currentMedalTime) then if (newTime > currentMedalTime) then -- manual update or medal expired, force update updateChallengeMedal(self, newTime) currentMedalTime = self.challengeCurrentMedalTime if currentMedalTime then local timeLeft = floor(currentMedalTime - newTime) self.challengeBar:SetValue(timeLeft) self.challengeBarText:SetText(GetTimeStringFromSecondsShort(timeLeft)) --D("forceupd", manual) end else -- timed update, throttle it local updateTimer = self.updateTimer updateTimer = updateTimer - elapsed if (updateTimer <= 0) then local timeLeft = floor(currentMedalTime - newTime) self.challengeBar:SetValue(timeLeft) self.challengeBarText:SetText(GetTimeStringFromSecondsShort(timeLeft)) updateTimer = opt_updateRate --D("noskip") end self.updateTimer = updateTimer end else --D("nomedal!?") end -- force a resync every 10 sec for onupdate calls if not manual then local recheck = self.challengeRecheck + elapsed if recheck > 10.1 then --D("Recheck", recheck, elapsed) self.challengeRecheck = 0 self:SetScript("OnUpdate", updateTracker) else self.challengeRecheck = recheck end end end function onUpdateProvingGroundsTimer (self, elapsed, manual, difficulty) local newTime = self.ProvingGroundsTime + elapsed self.ProvingGroundsTime = newTime local durationTime = self.ProvingGroundsDurationMax curWave = self.ProvingGroundsCurrentWave maxWave = self.ProvingGroundsMaxWave if (durationTime) then if floor(newTime) == durationTime then self.challengeBar:SetValue(0) if maxWave == 0 then self.challengeBarText:SetText(format("Wave %u %s", curWave, GetTimeStringFromSecondsShort(0))) else self.challengeBarText:SetText(format("Wave %u of %u %s", curWave, maxWave, GetTimeStringFromSecondsShort(0))) end elseif newTime > durationTime then -- manual update or medal expired, force update updateProvingGroundsBar(self, newTime, difficulty) durationTime = self.ProvingGroundsDurationMax --local timeLeft = durationTime - newTime --self.challengeBar:SetValue(timeLeft) --if maxWave == 0 then -- self.challengeBarText:SetText(format("Wave %u %s", curWave, GetTimeStringFromSecondsShort(timeLeft))) --else -- self.challengeBarText:SetText(format("Wave %u of %u %s", curWave, maxWave, GetTimeStringFromSecondsShort(timeLeft))) --end --D("forceupd", manual) else -- timed update, throttle it local updateTimer = self.updateTimer updateTimer = updateTimer - elapsed if (updateTimer <= 0) then local timeLeft = durationTime - newTime + 1 self.challengeBar:SetValue(timeLeft) if maxWave == 0 then self.challengeBarText:SetText(format("Wave %u %s", curWave, GetTimeStringFromSecondsShort(timeLeft))) else self.challengeBarText:SetText(format("Wave %u of %u %s", curWave, maxWave, GetTimeStringFromSecondsShort(timeLeft))) end updateTimer = opt_updateRate / 2 --D("noskip") end self.updateTimer = updateTimer end else --D("nomedal!?") end --force a resync every 10 sec for onupdate calls if not manual then local recheck = self.ProvingGroundsRecheck + elapsed if recheck > 10.1 then --D("Recheck", recheck, elapsed) self.ProvingGroundsRecheck = 0 self:SetScript("OnUpdate", updateTracker) else self.ProvingGroundsRecheck = recheck end end end function updateTrackerScenarios () local name, currentStage, numStages = C_Scenario.GetInfo() local stageName, stageDescription, numCriteria = C_Scenario.GetStepInfo() local inChallengeMode = C_Scenario.IsChallengeMode() if (currentStage > 0) then if (currentStage <= numStages) then -- scenario type header local header = WatchButton:GetNext() header.type = "header_basic" if (not inChallengeMode) then if (currentStage == numStages) then header.title:SetText("Scenario: Final Stage") else header.title:SetFormattedText("Scenario: Stage %d/%d", currentStage, numStages) end else header.title:SetText("Challenge Mode") end header.title:SetTextColor(opt_colors.QuestHeader[1], opt_colors.QuestHeader[2], opt_colors.QuestHeader[3]) header:Layout() -- scenario stage local button = WatchButton:GetNext() button.type = "scenario" setButtonToScenario(button) button:Layout() elseif (currentStage > numStages) then -- scenario complete header local header = WatchButton:GetNext() header.type = "header_basic" if (not inChallengeMode) then header.title:SetText("Scenario Complete") else header.title:SetText("Challenge Mode Complete") end header.title:SetTextColor(opt_colors.ScenarioComplete[1], opt_colors.ScenarioComplete[2], opt_colors.ScenarioComplete[3]) header:Layout() end -- questtypes -- thunderaan the windseeker = 62 -- stranger in a strange land = 83 -- blades of the anointed = 85 -- the kun-lai kicker = 98 -- soften them up = 81 -- slay them all! = 41 -- the champion's call! = 1 -- imperial qiraji armaments = 62 -- scenario quests local addedHeader = false local currentHeader = "(Unknown)" local numEntries = GetNumQuestLogEntries() for questIndex = 1, numEntries do local questTitle,_,_,_,isHeader = GetQuestLogTitle(questIndex) if isHeader then currentHeader = questTitle elseif (currentHeader == name) and (GetQuestLogQuestType(questIndex) == QUEST_TYPE_SCENARIO) then if not addedHeader then local questHeader = WatchButton:GetNext() questHeader.type = "header_basic" questHeader.title:SetText("Scenario Quests") questHeader.title:SetTextColor(opt_colors.QuestHeader[1], opt_colors.QuestHeader[2], opt_colors.QuestHeader[3]) questHeader:Layout() addedHeader = true end local button = WatchButton:GetNext() button.type = "quest" setButtonToQuest(button, questIndex) button:Layout() end end -- end end function setButtonToScenario (button) local name, currentStage, numStages = C_Scenario.GetInfo() local stageName, stageDescription, numCriteria = C_Scenario.GetStepInfo() local inChallengeMode = C_Scenario.IsChallengeMode() if (not inChallengeMode) then button.title:SetText(stageName) else button.title:SetText(stageName) end button.title:SetTextColor(opt_colors.ScenarioStageTitle[1], opt_colors.ScenarioStageTitle[2], opt_colors.ScenarioStageTitle[3]) for i = 1, numCriteria do local criteriaString, criteriaType, criteriaCompleted, quantity, totalQuantity, flags, assetID, quantityString, criteriaID = C_Scenario.GetCriteriaInfo(i) if (not criteriaCompleted) then local r, g, b = getObjectiveColor(quantity / totalQuantity) button:AddLine(format(" %s", criteriaString), format(": %s/%s", quantity, totalQuantity), r, g, b) elseif (opt_showCompletedObjectives) then button:AddLine(format(" %s", criteriaString), format(": %s/%s", quantity, totalQuantity), opt_colors.ObjectiveGradientComplete[1], opt_colors.ObjectiveGradientComplete[2], opt_colors.ObjectiveGradientComplete[3]) end end end function updateTrackerQuestTimers () local questTimers = { GetQuestTimers() } local numQuestTimers = #questTimers cached_numQuestTimers = numQuestTimers for i = 1, numQuestTimers do local button = WatchButton:GetNext() button.type = "questtimer" setButtonToQuestTimer(button, i, questTimers) button:Layout() end end function setButtonToQuestTimer(button, timerID, questTimers) button.timerID = timerID local questIndex = GetQuestIndexForTimer(timerID) local questTitle, _, _, _, _, _, _, _, questID = GetQuestLogTitle(questIndex) if (not questTitle) or (questTitle == "") then questTitle = "(Unknown Quest)" else questTitle = getQuestTaggedTitle(questIndex) end button.questIndex = questIndex button.questID = questID local timer = questTimers[button.timerID] local timerText = SecondsToTime(timer, false, false, 4) if (timerText == "") then timerText = "0 Sec" end button.title:SetText(questTitle) button.title:SetTextColor(opt_colors.QuestTimerTitle[1], opt_colors.QuestTimerTitle[2], opt_colors.QuestTimerTitle[3]) button:AddLine(" "..timerText, nil, opt_colors.QuestTimerTime[1], opt_colors.QuestTimerTime[2], opt_colors.QuestTimerTime[3]) button:SetBackdropColor(opt_colors.QuestTimerBackground[1], opt_colors.QuestTimerBackground[2], opt_colors.QuestTimerBackground[3], opt_colors.QuestTimerBackground[4]) button:SetScript("OnUpdate", onUpdateQuestTimer) end function onUpdateQuestTimer (self, elapsed) local updateTimer = self.updateTimer updateTimer = updateTimer - elapsed if (updateTimer <= 0) then local questTimers = { GetQuestTimers() } local numQuestTimers = #questTimers if (numQuestTimers ~= cached_numQuestTimers) then -- number of quest timers has changed, force tracker update to dispose of this frame --D("!!! Quest Timer count changed, forcing tracker update!") updateTracker() return end local timer = questTimers[self.timerID] --D(timer, "###", GetQuestTimers()) local timerText = SecondsToTime(timer, false, false, 4) if (timerText == "") then timerText = "0 Sec" end local line = self.linesLeft[1] line:SetText(" "..timerText) updateTimer = opt_updateRate end self.updateTimer = updateTimer end function updateTrackerPopups() for itemID, itemName in pairs(itemPopups) do local button = WatchButton:GetNext() button.type = "popup" setButtonToItemPopup(button, itemID, itemName) button:Layout() end local numPopups = GetNumAutoQuestPopUps() for i = 1, numPopups do local popID, popType = GetAutoQuestPopUp(i) local button = WatchButton:GetNext() button.type = "popup" setButtonToPopup(button, popID, popType) button:Layout() end end function setButtonToItemPopup (button, itemID, itemName) button.popupType = "ITEM" button.itemID = itemID button.itemName = itemName button.title:SetText(itemName) button.title:SetTextColor(opt_colors.PopupItemTitle[1], opt_colors.PopupItemTitle[2], opt_colors.PopupItemTitle[3]) button:AddLine(" Item Begins a Quest", nil, opt_colors.PopupItemDescription[1], opt_colors.PopupItemDescription[2], opt_colors.PopupItemDescription[3]) button:SetBackdropColor(opt_colors.PopupItemBackground[1], opt_colors.PopupItemBackground[2], opt_colors.PopupItemBackground[3], opt_colors.PopupItemBackground[4]) button.iconExclamationMark:Show() button.iconExclamationMark.animGroup:Play() button.titleButton:EnableMouse(false) button:EnableMouse(true) end function setButtonToPopup (button, questID, popType) local questIndex = GetQuestLogIndexByID(questID) local taggedTitle --enter the nexus? --D(button, questID, popType, questIndex) if (questIndex == 0) or (questIndex == nil) then --D("NQ") taggedTitle = "New Quest!" else --D("TI") taggedTitle = getQuestTaggedTitle(questIndex) end button.popupType = popType button.questIndex = questIndex button.questID = questID button.title:SetText(taggedTitle) if popType == "COMPLETE" then button.title:SetTextColor(opt_colors.PopupCompleteTitle[1], opt_colors.PopupCompleteTitle[2], opt_colors.PopupCompleteTitle[3]) button:AddLine(" Quest Completed", nil, opt_colors.PopupCompleteDescription[1], opt_colors.PopupCompleteDescription[2], opt_colors.PopupCompleteDescription[3]) button:SetBackdropColor(opt_colors.PopupCompleteBackground[1], opt_colors.PopupCompleteBackground[2], opt_colors.PopupCompleteBackground[3], opt_colors.PopupCompleteBackground[4]) button.iconQuestionMark:Show() button.iconQuestionMark.animGroup:Play() else button.title:SetTextColor(opt_colors.PopupOfferTitle[1], opt_colors.PopupOfferTitle[2], opt_colors.PopupOfferTitle[3]) button:AddLine(" Quest Received", nil, opt_colors.PopupOfferDescription[1], opt_colors.PopupOfferDescription[2], opt_colors.PopupOfferDescription[3]) button:SetBackdropColor(opt_colors.PopupOfferBackground[1], opt_colors.PopupOfferBackground[2], opt_colors.PopupOfferBackground[3], opt_colors.PopupOfferBackground[4]) button.iconExclamationMark:Show() button.iconExclamationMark.animGroup:Play() end button.titleButton:EnableMouse(false) button:EnableMouse(true) end function updateTrackerQuests() local oldSelection if (opt_subzoneHeuristicHighlight) then oldSelection = GetQuestLogSelection() end local headerName, questIndex for i = 1, #headerList do headerName = headerList[i] -- header if #questSortTable[headerName] > 0 then local button = WatchButton:GetNext() button.type = "header" button.headerName = headerName --|TTexturePath:size1:size2:xoffset:yoffset:dimx:dimy:coordx1:coordx2:coordy1:coordy2:red:green:blue|t if dbc.collapsedHeaders[headerName] then button.title:SetText("|TInterface\\AddOns\\QuestKing\\UI-SortArrow_sm_right:8:8:0:-1:0:0:0:0:0:0:1:1:1|t"..headerName) button.title:SetTextColor(opt_colors.QuestHeaderCollapsed[1], opt_colors.QuestHeaderCollapsed[2], opt_colors.QuestHeaderCollapsed[3]) else button.title:SetText("|TInterface\\AddOns\\QuestKing\\UI-SortArrow_sm_down:8:8:0:-1:0:0:0:0:0:0:1:1:1|t"..headerName) button.title:SetTextColor(opt_colors.QuestHeader[1], opt_colors.QuestHeader[2], opt_colors.QuestHeader[3]) end button:Layout() end -- quests if not dbc.collapsedHeaders[headerName] then for j = 1, #questSortTable[headerName] do questIndex = questSortTable[headerName][j] local button = WatchButton:GetNext() button.type = "quest" setButtonToQuest(button, questIndex) button:Layout() end end end if (opt_subzoneHeuristicHighlight) then SelectQuestLogEntry(oldSelection) end end function setButtonToQuest (button, questIndex) local questTitle, level, questTag, suggestedGroup, isHeader, isCollapsed, isComplete, isDaily, questID, startEvent = GetQuestLogTitle(questIndex) button.questIndex = questIndex button.questID = questID local collapseObjectives = dbc.collapsedQuests[questID] -- set title local taggedTitle = getQuestTaggedTitle(questIndex) -- taggedTitle = GetQuestLogQuestType(questIndex) .. " / " .. taggedTitle if isComplete == -1 then button.title:SetText(opt_colors._FailedQuestTag .. taggedTitle) else button.title:SetText(taggedTitle) end -- add objectives local numObj = GetNumQuestLeaderBoards(questIndex) or 0 local completedObj = 0 local displayedObj = 0 for i = 1, numObj do local desc, objectiveType, isDone = GetQuestLogLeaderBoard(i, questIndex) if (desc == nil) then desc = "Unknown" end local p1, p2, quantName, quantCur, quantMax = string.find(desc, OBJECTIVE_PATTERN) if isDone then completedObj = completedObj + 1 end local displayObjective = true if collapseObjectives then displayObjective = false elseif isComplete == 1 then if (opt_showCompletedObjectives == "always") then displayObjective = true else displayObjective = false end end if (desc == "Unknown") then displayObjective = false end if (displayObjective) then if (not desc) then -- elseif (not quantName) or (objectiveType == "spell") then if (not isDone) or (opt_showCompletedObjectives) then local r, g, b = getObjectiveColor(isDone and 1 or 0) button:AddLine(format(" %s", desc), nil, r, g, b) displayedObj = displayedObj + 1 end else if (not isDone) or (opt_showCompletedObjectives) then local r, g, b = getObjectiveColor(quantCur / quantMax) local line = button:AddLine(format(" %s", quantName), format(": %s/%s", quantCur, quantMax), r, g, b) displayedObj = displayedObj + 1 if updatedObjectives[quantName] then updatedObjectives[quantName] = nil line.flash.animGroup:Play() end end end end end -- money local requiredMoney = GetQuestLogRequiredMoney(questIndex) if requiredMoney > 0 then watchMoney = true local playerMoney = GetMoney() -- not sure about this, but the default watch frame does it -- (fake completion for gold-requiring connectors when gold req is met and no event begins) if (numObj == 0 and playerMoney >= requiredMoney and not startEvent) then isComplete = 1 end numObj = numObj + 1 -- (questking only) ensure all gold-requiring quests aren't marked as connectors if (not collapseObjectives) then -- hide entirely if objectives are collapsed if playerMoney >= requiredMoney then -- show met gold amounts only for incomplete quests if (isComplete ~= 1) and (opt_showCompletedObjectives) then local r, g, b = getObjectiveColor(1) button:AddLine(" Requires: "..GetMoneyString(requiredMoney), nil, r, g, b) end else -- always show unmet gold amount local r, g, b = getObjectiveColor(0) button:AddLine(" Requires: "..GetMoneyString(requiredMoney), nil, r, g, b) end end end -- colour title if (isComplete == -1) then button.title:SetTextColor(opt_colors.QuestTitleFailed[1], opt_colors.QuestTitleFailed[2], opt_colors.QuestTitleFailed[3]) -- failed elseif (isComplete == 1) then if GetQuestLogIsAutoComplete(questIndex) then button.title:SetTextColor(opt_colors.QuestTitleCompleteAuto[1], opt_colors.QuestTitleCompleteAuto[2], opt_colors.QuestTitleCompleteAuto[3]) -- autocompletable elseif (numObj == 0) then button.title:SetTextColor(opt_colors.QuestTitleConnector[1], opt_colors.QuestTitleConnector[2], opt_colors.QuestTitleConnector[3]) -- connector quest [type c] (complete, 0/0 objectives) else button.title:SetTextColor(opt_colors.QuestTitleComplete[1], opt_colors.QuestTitleComplete[2], opt_colors.QuestTitleComplete[3]) -- completed quest (complete, n/n objectives) end -- elseif (GetQuestLogQuestType(questIndex) == QUEST_TYPE_SCENARIO) then -- button.title:SetTextColor(opt_colors.QuestTitleScenario[1], opt_colors.QuestTitleScenario[2], opt_colors.QuestTitleScenario[3]) else if numObj == 0 then button.title:SetTextColor(opt_colors.QuestTitleConnector[1], opt_colors.QuestTitleConnector[2], opt_colors.QuestTitleConnector[3]) -- connector quest [type i] (incomplete, 0/0 objectives) elseif numObj == completedObj then button.title:SetTextColor(1, 0, 1) -- unknown state (incomplete, n/n objectives where n>0) else local color = GetQuestDifficultyColor(level) button.title:SetTextColor(color.r, color.g, color.b) -- incomplete quest (incomplete, n/m objectives where m>n) end end if collapseObjectives then button.title:SetAlpha(0.6) end -- add item button local link, item, charges, showItemWhenComplete = GetQuestLogSpecialItemInfo(questIndex) local itemButton if opt_itemAnchorSide and item and ((isComplete ~= 1) or (showItemWhenComplete)) then if InCombatLockdown() then startCombatTimer() else itemButton = _G["QuestKing_WatchFrameItem" .. button.buttonNumber] if (not itemButton) then --itemButton = CreateFrame("Button", "QuestKing_WatchFrameItem" .. button.buttonNumber, button, "WatchFrameItemButtonTemplate") itemButton = CreateFrame("Button", "QuestKing_WatchFrameItem" .. button.buttonNumber, UIParent, "WatchFrameItemButtonTemplate") button.itemButton = itemButton end -- setup itemButton:Show() itemButton:ClearAllPoints() itemButton:SetID(questIndex) SetItemButtonTexture(itemButton, item) SetItemButtonCount(itemButton, charges) itemButton.charges = charges WatchFrameItem_UpdateCooldown(itemButton) itemButton.rangeTimer = -1 -- anchor if opt_itemAnchorSide == "right" then itemButton:SetPoint("TOPLEFT", button.title, "TOPRIGHT", 4, -1) else itemButton:SetPoint("TOPRIGHT", button.title, "TOPLEFT", -4, -1) end -- resize if displayedObj > 0 then itemButton:SetHeight(opt_lineHeight * 2) _G[format("QuestKing_WatchFrameItem%dIconTexture", button.buttonNumber)]:SetTexCoord(0, 1, 0, 1) _G[format("QuestKing_WatchFrameItem%dNormalTexture", button.buttonNumber)]:SetHeight(42) else itemButton:SetHeight(opt_lineHeight) _G[format("QuestKing_WatchFrameItem%dIconTexture", button.buttonNumber)]:SetTexCoord(0, 1, 0.25, 0.75) _G[format("QuestKing_WatchFrameItem%dNormalTexture", button.buttonNumber)]:SetHeight(21) end itemButton:SetWidth(opt_lineHeight * 2) itemButton:SetScale(0.9) end else if button.itemButton and button.itemButton:IsShown() then if InCombatLockdown() then startCombatTimer() else button.itemButton:Hide() end end end if (opt_subzoneHeuristicHighlight) then local subzone = string.lower(GetSubZoneText() or "") SelectQuestLogEntry(questIndex) local logDescription, logObjectives = GetQuestLogQuestText() logDescription = (logDescription and string.lower(logDescription)) or "<>" logObjectives = (logObjectives and string.lower(logObjectives)) or "<>" if (subzone ~= "") then if (string.find(logDescription, subzone, 1, true)) or (string.find(logObjectives, subzone, 1, true)) then button:SetBackdropColor(opt_colors.SubzoneHeuristicHighlightColor[1], opt_colors.SubzoneHeuristicHighlightColor[2], opt_colors.SubzoneHeuristicHighlightColor[3], opt_colors.SubzoneHeuristicHighlightColor[4]) end end end end function updateTrackerAchievements() local trackedAchievements = trackedAchievementCache trackedAchievementCache = trackedAchievements local numTrackedAchievements = #trackedAchievements -- header local showAchievements = true if (dbc.displayMode == "combined") then local headerName = "Achievements" if numTrackedAchievements > 0 then local button = WatchButton:GetNext() button.type = "header" button.headerName = headerName if dbc.collapsedHeaders[headerName] then button.title:SetText("|TInterface\\AddOns\\QuestKing\\UI-SortArrow_sm_right:8:8:0:-1:0:0:0:0:0:0:1:1:1|t"..headerName) button.title:SetTextColor(opt_colors.AchievementHeaderCollapsed[1], opt_colors.AchievementHeaderCollapsed[2], opt_colors.AchievementHeaderCollapsed[3]) else button.title:SetText("|TInterface\\AddOns\\QuestKing\\UI-SortArrow_sm_down:8:8:0:-1:0:0:0:0:0:0:1:1:1|t"..headerName) button.title:SetTextColor(opt_colors.AchievementHeader[1], opt_colors.AchievementHeader[2], opt_colors.AchievementHeader[3]) end button:Layout() end if dbc.collapsedHeaders[headerName] then showAchievements = false end end -- achievements if showAchievements then for i = 1, numTrackedAchievements do local achievementID = trackedAchievements[i] local button = WatchButton:GetNext() button.type = "achievement" setButtonToAchievement(button, achievementID) button:Layout() end end end function setButtonToAchievement (button, achievementID) local id, achievementName, points, achievemntCompleted, _, _, _, achievementDesc, flags, image, rewardText, isGuildAch = GetAchievementInfo(achievementID) button.achievementID = achievementID local collapseCriteria = dbc.collapsedAchievements[achievementID] -- set title button.title:SetText(achievementName) if completed then button.title:SetTextColor(opt_colors.AchievementTitleComplete[1], opt_colors.AchievementTitleComplete[2], opt_colors.AchievementTitleComplete[3]) else if isGuildAch then button.title:SetTextColor(opt_colors.AchievementTitleGuild[1], opt_colors.AchievementTitleGuild[2], opt_colors.AchievementTitleGuild[3]) else button.title:SetTextColor(opt_colors.AchievementTitle[1], opt_colors.AchievementTitle[2], opt_colors.AchievementTitle[3]) end end if collapseCriteria then button.title:SetAlpha(0.6) end -- criteria setup local numCriteria = GetAchievementNumCriteria(achievementID) local foundTimer = false local timeNow -- avoid multiple calls to GetTime() -- no criteria if (numCriteria == 0) then if (not collapseCriteria) then button:AddLine(" "..achievementDesc, nil, opt_colors.AchievementDescription[1], opt_colors.AchievementDescription[2], opt_colors.AchievementDescription[3]) -- no criteria exist, show desc line end end -- criteria loop for i = 1, numCriteria do local _ local criteriaString, criteriaType, criteriaCompleted, quantity, totalQuantity, name, flags, assetID, quantityString, criteriaID, eligible = GetAchievementCriteriaInfo(achievementID, i) -- set string if (bit.band(flags, EVALUATION_TREE_FLAG_PROGRESS_BAR) == EVALUATION_TREE_FLAG_PROGRESS_BAR) then criteriaString = quantityString else if (criteriaType == CRITERIA_TYPE_ACHIEVEMENT and assetID) then -- meta achievement _, criteriaString = GetAchievementInfo(assetID) end end -- display criteria depending on timer state -- kinda wanna seperate this out, but display is dependent on timer logic (e.g. timeLeft > 0 forces display) local timerTable = achievementTimers[criteriaID] local timeLeft = 0 if timerTable then -- timer exists foundTimer = true timeNow = timeNow or GetTime() local timeLeft = floor(timerTable.startTime + timerTable.duration - timeNow) if timeLeft > 0 then -- timer is running, force showing criteria if criteriaCompleted then button:AddLine(" "..criteriaString, nil, opt_colors.AchievementCriteriaComplete[1], opt_colors.AchievementCriteriaComplete[2], opt_colors.AchievementCriteriaComplete[3]) -- timer running, force showing completed objective else button:AddLine(" "..criteriaString, nil, opt_colors.AchievementCriteria[1], opt_colors.AchievementCriteria[2], opt_colors.AchievementCriteria[3]) -- timer running, force showing normal objective end -- adding timer line local time = SecondsToTime(timeLeft, false, false, 4) if (time == "") then time = "0 Sec" end button.title:SetTextColor(opt_colors.AchievementTimedTitle[1], opt_colors.AchievementTimedTitle[2], opt_colors.AchievementTimedTitle[3]) button:SetBackdropColor(opt_colors.AchievementTimedBackground[1], opt_colors.AchievementTimedBackground[2], opt_colors.AchievementTimedBackground[3], opt_colors.AchievementTimedBackground[4]) --D(opt_colors.AchievementTimedBackground[1], opt_colors.AchievementTimedBackground[2], opt_colors.AchievementTimedBackground[3], opt_colors.AchievementTimedBackground[4]) local line = button:AddLine(" "..time, nil, opt_colors.AchievementTimedTimer[1], opt_colors.AchievementTimedTimer[2], opt_colors.AchievementTimedTimer[3]) line.isTimer = true line.startTime = timerTable.startTime line.duration = timerTable.duration button:SetScript("OnUpdate", onUpdateAchievementTimer) else -- timer has expired if (not criteriaCompleted) and (not collapseCriteria) then button:AddLine(" "..criteriaString, nil, opt_colors.AchievementCriteria[1], opt_colors.AchievementCriteria[2], opt_colors.AchievementCriteria[3]) -- timer expired, show normally unless completed/collapsed end achievementTimers[criteriaID] = nil -- since timer expired, erase it ourselves without waiting for event end else -- no timer exists if (not criteriaCompleted) and (not collapseCriteria) then button:AddLine(" "..criteriaString, nil, opt_colors.AchievementCriteria[1], opt_colors.AchievementCriteria[2], opt_colors.AchievementCriteria[3]) -- no timer, show normally unless completed/collapsed end end end -- show "meta" timer if there is a timer on this achievement, but no associated criteria are found in GetAchievementNumCriteria (Salt and Pepper?) -- multiple timers would be a problem (it sets/unsets with whichever criteria timer fires last), but it's better than nothing if (foundTimer == false) and (achievementTimersMeta[achievementID]) then local timerTable = achievementTimersMeta[achievementID] local timeNow = GetTime() local timeLeft = floor(timerTable.startTime + timerTable.duration - timeNow) if timeLeft > 0 then local time = SecondsToTime(timeLeft, false, false, 4) if (time == "") then time = "0 Sec" end button.title:SetTextColor(opt_colors.AchievementTimedTitle[1], opt_colors.AchievementTimedTitle[2], opt_colors.AchievementTimedTitle[3]) button:SetBackdropColor(opt_colors.AchievementTimedBackground[1], opt_colors.AchievementTimedBackground[2], opt_colors.AchievementTimedBackground[3], opt_colors.AchievementTimedBackground[4]) local line = button:AddLine(" "..time, nil, opt_colors.AchievementTimedTimerMeta[1], opt_colors.AchievementTimedTimerMeta[2], opt_colors.AchievementTimedTimerMeta[3]) line.isTimer = true line.startTime = timerTable.startTime line.duration = timerTable.duration button:SetScript("OnUpdate", onUpdateAchievementTimer) end end end function onUpdateAchievementTimer (self, elapsed) local updateTimer = self.updateTimer updateTimer = updateTimer - elapsed if (updateTimer <= 0) then local timeNow for i = 1, #self.linesLeft do local line = self.linesLeft[i] if line.isTimer then timeNow = timeNow or GetTime() local timeLeft = floor(line.startTime + line.duration - timeNow) if timeLeft > 0 then --D(timeLeft) local time = SecondsToTime(timeLeft, false, false, 4) if (time == "") then time = "0 Sec" end line:SetText(" "..time) else --D("EXPIRED") updateTracker() return end end end updateTimer = opt_updateRate end self.updateTimer = updateTimer end function buildQuestSortTable () for k,v in pairs(questSortTable) do wipe(questSortTable[k]) end wipe(headerList) local numEntries = GetNumQuestLogEntries() local currentHeader = "(Unknown)" local numQuests = 0 for i = 1, numEntries do local title,_,_,_,isHeader,isCollapsed,_,_,_ = GetQuestLogTitle(i) if (not title) or (title == "") then title = "(Unknown)" end if (isHeader) then currentHeader = title tinsert(headerList, title) if not questSortTable[title] then questSortTable[title] = {} end elseif (not isHeader) and (IsQuestWatched(i)) then if (not questSortTable[currentHeader]) then questSortTable[currentHeader] = {} end tinsert(questSortTable[currentHeader], i) end if (not isHeader) then numQuests = numQuests + 1 end end totalQuestCount = numQuests end function getQuestTaggedTitle (questIndex) local questTitle, level, questTag, suggestedGroup, _, _, _, isDaily, questID, startEvent, displayQuestID = GetQuestLogTitle(questIndex) -- determine tag local levelClass = tostring(level) if (isDaily) then levelClass = levelClass.."Y" end if (questTag ~= nil) then if ((questTag == "Group") and (suggestedGroup > 0)) then levelClass = levelClass.."G"..suggestedGroup elseif ((questTag == "Group") or (questTag == "Elite")) then levelClass = levelClass.."+" elseif (questTag == "Dungeon") then levelClass = levelClass.."D" elseif (questTag == "Heroic") then levelClass = levelClass.."H" elseif ((questTag == "Raid (10)") or (questTag == "Raid (25)") or (questTag == "Raid")) then levelClass = levelClass.."R" elseif (questTag == "PvP") then levelClass = levelClass.."P" elseif (questTag == "Scenario") then levelClass = levelClass.."S" elseif (questTag == "Legendary") then levelClass = levelClass.."L" elseif (questTag == "Account") then levelClass = levelClass.."A" else levelClass = levelClass.."+" end end if startEvent then levelClass = levelClass.."e" end if GetQuestLogIsAutoComplete(questIndex) then levelClass = levelClass.."a" end return format("[%s] %s", levelClass, questTitle) end function colorGradient(perc, ...) if perc >= 1 then local r, g, b = select(select('#', ...) - 2, ...) return r, g, b elseif perc <= 0 then local r, g, b = ... return r, g, b end local num = select('#', ...) / 3 local segment, relperc = math_modf(perc*(num-1)) local r1, g1, b1, r2, g2, b2 = select((segment*3)+1, ...) return r1 + (r2-r1)*relperc, g1 + (g2-g1)*relperc, b1 + (b2-b1)*relperc end function getObjectiveColor(progress) local r, g, b if (progress == 1) then r, g, b = opt_colors.ObjectiveGradientComplete[1], opt_colors.ObjectiveGradientComplete[2], opt_colors.ObjectiveGradientComplete[3] else r, g, b = colorGradient(progress, opt_colors.ObjectiveGradient0[1], opt_colors.ObjectiveGradient0[2], opt_colors.ObjectiveGradient0[3], opt_colors.ObjectiveGradient50[1], opt_colors.ObjectiveGradient50[2], opt_colors.ObjectiveGradient50[3], opt_colors.ObjectiveGradient99[1], opt_colors.ObjectiveGradient99[2], opt_colors.ObjectiveGradient99[3]) end return r, g, b end -- Misc local old_WatchFrame_Update = WatchFrame_Update -- @@@@@ test BRC quest with BOTH open - done function WatchFrame_Update() --D('HIDING') WatchFrame:Hide() if not WatchFrame.qkfix then WatchFrame.qkfix = true WatchFrame:UnregisterAllEvents() WatchFrameLines:UnregisterAllEvents() end end WatchFrame:HookScript("OnShow",function () WatchFrame:Hide() end) QuestKing_UpdateTracker = updateTracker SLASH_QUESTKING_RESET1 = "/qkreset" SlashCmdList["QUESTKING_RESET"] = function(msg, editBox) print("QuestKing: Resetting all collapsed headers/quests/achievements.") dbc.collapsedHeaders = {} dbc.collapsedQuests = {} dbc.collapsedAchievements = {} -- dbc.trackerCollapsed = false -- dbc.trackerHidden = false updateTracker() end fEvents:SetScript("OnEvent", function(self, event, name) if name ~= addonName then return end self:UnregisterEvent("ADDON_LOADED") self:SetScript("OnEvent", QuestKing_HandleEvent) if not (QuestKingDB) then QuestKingDB = {} end if not (QuestKingDBPerChar) then QuestKingDBPerChar = {} end db = QuestKingDB dbc = QuestKingDBPerChar dbc.collapsedHeaders = dbc.collapsedHeaders or {} dbc.collapsedQuests = dbc.collapsedQuests or {} dbc.collapsedAchievements = dbc.collapsedAchievements or {} dbc.trackerCollapsed = dbc.trackerCollapsed or false dbc.displayMode = dbc.displayMode or "combined" dbc.trackerPositionPreset = dbc.trackerPositionPreset or 1 -- dbc.trackerHidden = dbc.trackerHidden or false -- dbc.trackerPositionCustom = dbc.trackerPositionCustom or false -- i don't understand why this doesn't work... -- WATCHFRAME_MAXACHIEVEMENTS = 100 self:RegisterEvent("QUEST_LOG_UPDATE") self:RegisterEvent("ITEM_PUSH") self:RegisterEvent("QUEST_AUTOCOMPLETE") self:RegisterEvent("TRACKED_ACHIEVEMENT_UPDATE") -- Achievement timers self:RegisterEvent("ACHIEVEMENT_EARNED") -- necessary? --self:RegisterEvent("CRITERIA_UPDATE") self:RegisterEvent("PLAYER_LEVEL_UP") self:RegisterEvent("UI_INFO_MESSAGE") self:RegisterEvent("PLAYER_MONEY") -- for GetQuestLogRequiredMoney self:RegisterEvent("SCENARIO_UPDATE") self:RegisterEvent("SCENARIO_CRITERIA_UPDATE") self:RegisterEvent("PLAYER_ENTERING_WORLD") self:RegisterEvent("WORLD_STATE_TIMER_START") self:RegisterEvent("WORLD_STATE_TIMER_STOP") if (opt_subzoneHeuristicHighlight) then self:RegisterEvent("ZONE_CHANGED") self:RegisterEvent("ZONE_CHANGED_INDOORS") self:RegisterEvent("ZONE_CHANGED_NEW_AREA") end if (opt_enableItemPopups) then self:RegisterEvent("CHAT_MSG_LOOT") QUEST_START_ITEMS = {1307,1357,1972,2839,3082,3317,4056,4433,4613,4854,4881,4926,5099,5102,5103,5138,5179,5352,5791,5877,6172,6196,6497,6766,6775,6776,6916,8244,8524,8623,8704,8705,9326,9572,10454,10589,10590,10593,10621,11116,11668,12558,12564,12771,12842,13140,14646,14647,14648,14649,14650,14651,16303,16304,16305,16408,16782,17008,17115,17116,17409,18356,18357,18358,18359,18360,18361,18362,18363,18364,18422,18423,18565,18589,18628,18703,18706,18769,18770,18771,18969,18987,19002,19003,19016,19018,19228,19257,19267,19277,19423,19443,19452,19802,20310,20460,20461,20483,20644,20741,20742,20765,20798,20806,20807,20938,20939,20940,20941,20942,20943,20944,20945,20946,20947,20948,21165,21166,21167,21220,21221,21230,21245,21246,21247,21248,21249,21250,21251,21252,21253,21255,21256,21257,21258,21259,21260,21261,21262,21263,21264,21265,21378,21379,21380,21381,21382,21384,21385,21514,21749,21750,21751,21776,22597,22600,22601,22602,22603,22604,22605,22606,22607,22608,22609,22610,22611,22612,22613,22614,22615,22616,22617,22618,22620,22621,22622,22623,22624,22719,22723,22727,22888,22970,22972,22973,22974,22975,22977,23179,23180,23181,23182,23183,23184,23216,23228,23249,23338,23580,23678,23759,23777,23797,23837,23850,23870,23890,23892,23900,23904,23910,24132,24228,24330,24367,24407,24414,24483,24484,24504,24558,24559,25459,25705,25706,25752,25753,28113,28114,28552,28598,29233,29234,29235,29236,29476,29588,29590,29738,30431,30579,30756,31120,31239,31241,31345,31363,31384,31489,31707,31890,31891,31907,31914,32385,32386,32405,32523,32621,32726,33102,33121,33289,33314,33345,33347,33961,33962,33978,34028,34090,34091,34469,34777,34815,34984,35120,35567,35568,35569,35648,35723,35787,35855,36742,36744,36746,36756,36780,36855,36856,36940,36958,37163,37164,37432,37571,37599,37736,37737,37830,37833,38280,38281,38321,38567,38660,38673,39713,40666,41267,41556,42203,42772,43242,43297,43512,44148,44158,44259,44276,44294,44326,44569,44577,44725,44927,44979,45039,45506,45857,46004,46052,46053,46128,46318,46697,46875,46876,46877,46878,46879,46880,46881,46882,46883,46884,46955,47039,47246,48679,49010,49200,49203,49205,49219,49220,49641,49643,49644,49667,49676,49776,49932,50320,50379,50380,51315,52079,52197,52831,53053,53106,54345,54614,54639,55166,55167,55181,55186,55243,56474,56571,56812,57102,57118,57935,58117,58491,58898,59143,60816,60886,60956,61310,61322,61378,61505,62021,62044,62045,62046,62056,62138,62281,62282,62483,62768,62933,63090,63250,63276,63686,63700,64353,64450,65894,65895,65896,65897,69854,70928,70932,73058,74034,77957,78912,79238,79323,79324,79325,79326,79341,79343,79812,80240,80241,80597,80827,82870,83076,83767,83769,83770,83771,83772,83773,83774,83777,83779,83780,85477,85557,85558,85783,86404,86433,86434,86435,86436,86542,86544,86545,87878,88538,88563,88715,89169,89170,89171,89172,89173,89174,89175,89176,89178,89179,89180,89181,89182,89183,89184,89185,89209} end WatchFrame:UnregisterEvent("QUEST_AUTOCOMPLETE") hooksecurefunc("AddQuestWatch", hookQuestWatch) hooksecurefunc("RemoveQuestWatch", hookQuestWatch) hooksecurefunc("AddAutoQuestPopUp", function () updateTracker() end) QuestKing:CreateTracker() updateTracker() -- QuestKing.UpdateTracker = updateTracker -- QuestKing_Tracker:SetScript("OnShow", function (self) -- dbc.trackerHidden = false -- updateTracker() -- print("QuestKing tracker shown.") -- end) -- QuestKing_Tracker:SetScript("OnHide", function (self) -- dbc.trackerHidden = true -- print("QuestKing tracker hidden.") -- end) -- if (dbc.trackerHidden == true) then -- QuestKing_Tracker:Hide() -- end -- QuestKing_Tracker.TitleRegion = QuestKing_Tracker:CreateTitleRegion() -- QuestKing_Tracker.TitleRegion:SetAllPoints() -- QuestKing_Tracker:EnableMouse(true) -- QuestKing_Tracker:SetMovable(true) -- QuestKing_Tracker:SetScript("OnMouseDown", function () -- QuestKing_Tracker:StartMoving() -- end) -- QuestKing_Tracker:SetScript("OnMouseUp", function () -- QuestKing_Tracker:StopMovingOrSizing() -- end) --QuestKing_Tracker.TitleRegion:EnableMouse(1) --QuestKing_Tracker.TitleRegion:SetPoint("TOPLEFT") --QuestKing_Tracker.TitleRegion:SetPoint("TOPRIGHT") --QuestKing_Tracker.TitleRegion:SetHeight(opt_titleHeight) end) fEvents:RegisterEvent("ADDON_LOADED") -- Debug stuff, ignore -- /run QuestKing_HandleEvent(nil, "TRACKED_ACHIEVEMENT_UPDATE", 2188, 7622, 10, 15); QuestKing_HandleEvent(nil, "TRACKED_ACHIEVEMENT_UPDATE", 3815, 0, 10, 20); -- /run AddAutoQuestPopUp(28790, "OFFER"); AddAutoQuestPopUp(25771, "COMPLETE"); QuestKing_UpdateTracker(); -- function GetQuestTimers() -- return GetTime() - 2095200, GetTime() - 2095200, GetTime() - 2095200 -- end -- -- function GetQuestIndexForTimer(timerID) -- if timerID == 1 then -- return 2 -- elseif timerID == 2 then -- return 4 -- else -- return 5 -- end -- end --/run Boss1TargetFrame:Show(); Boss1TargetFrame:SetPoint("TOPRIGHT", "QuestKing_Tracker", "TOPLEFT", 50, 0) --/run VehicleSeatIndicator_SetUpVehicle(221) --/run UIParent_ManageFramePositions() -- FramePositionDelegate:UIParentManageFramePositions -- Boss1TargetFrame:UnregisterEvent("INSTANCE_ENCOUNTER_ENGAGE_UNIT") -- 221 222 223 224 225 226 227 228 249 254 -- hook setpoint? -- ? convert quest item checks to GetContainerItemQuestInfo -- requires expensive bag scans on inventory change, issues with knowing which item is picked up, retriggering items on login etc. -- probably not worth it... but does avoid issue of having to manually update IDs