Nenue@7: -- WorldPlan Nenue@7: -- QuestPOI.lua Nenue@7: -- Created: 10/1/2016 7:21 PM Nenue@7: -- %file-revision% Nenue@65: -- Big TODOs: Nenue@65: -- -- generate frames using `WorldMap_GetOrCreateTaskPOI' to remove tainting issues Nenue@7: -- Nenue@40: local _, db = ... Nick@64: local TQ_GetQuestInfoByQuestID = C_TaskQuest.GetQuestInfoByQuestID Nenue@7: local TQ_GetQuestLocation = C_TaskQuest.GetQuestLocation Nenue@7: local TQ_GetQuestTimeLeftMinutes = C_TaskQuest.GetQuestTimeLeftMinutes Nenue@9: local TQ_IsActive = C_TaskQuest.IsActive Nenue@29: local TQ_RequestPreloadRewardData = C_TaskQuest.RequestPreloadRewardData Nenue@7: local QuestPOIGetIconInfo, WorldMapPOIFrame = QuestPOIGetIconInfo, WorldMapPOIFrame Nenue@33: local WorldMap_DoesWorldQuestInfoPassFilters = WorldMap_DoesWorldQuestInfoPassFilters Nenue@33: local QuestMapFrame_IsQuestWorldQuest = QuestMapFrame_IsQuestWorldQuest Nenue@40: local GetAchievementNumCriteria, GetAchievementCriteriaInfo, GetAchievementInfo = GetAchievementNumCriteria, GetAchievementCriteriaInfo, GetAchievementInfo Nick@64: Nick@64: local IsQuestFlaggedCompleted = IsQuestFlaggedCompleted Nick@64: local GetFactionInfoByID, GetQuestObjectiveInfo = GetFactionInfoByID, GetQuestObjectiveInfo Nick@64: local GetQuestTagInfo, GetProfessionInfo = GetQuestTagInfo, GetProfessionInfo Nick@64: local GetNumQuestLogRewards, GetNumQuestLogRewardCurrencies, HaveQuestData = GetNumQuestLogRewards, GetNumQuestLogRewardCurrencies, HaveQuestData Nick@64: local GetQuestLogRewardMoney, GetQuestLogRewardCurrencyInfo, GetMoneyString = GetQuestLogRewardMoney, GetQuestLogRewardCurrencyInfo, GetMoneyString Nick@64: local SpellCanTargetQuest, GetCVarBool = SpellCanTargetQuest, GetCVarBool Nick@64: local SetSuperTrackedQuestID = SetSuperTrackedQuestID Nenue@65: local HaveQuestRewardData = HaveQuestRewardData Nenue@96: local GetTime = GetTime Nenue@65: Nick@64: Nenue@93: local pairs, ipairs, tinsert, tremove, unpack, select = pairs, ipairs, tinsert, tremove, unpack, select Nenue@40: local floor, mod, tostring, tonumber, GetSuperTrackedQuestID = floor, mod, tostring, tonumber, GetSuperTrackedQuestID Nenue@33: local GameTooltip = GameTooltip Nenue@33: local GetItemIcon = GetItemIcon Nenue@7: Nenue@67: local print = DEVIAN_WORKSPACE and function(...) _G.print('POI', ...) end or nop Nenue@67: local wprint = DEVIAN_WORKSPACE and function(...) _G.print('WP', ...) end or nop Nenue@67: local wqprint = DEVIAN_WORKSPACE and function(...) _G.print('WorldQuests', ...) end or nop Nenue@67: local iprint = DEVIAN_WORKSPACE and function(...) _G.print('ItemScan', ...) end or nop Nenue@67: local rprint = DEVIAN_WORKSPACE and function(...) _G.print('WQRefresh', ...) end or nop Nenue@67: local dprint = DEVIAN_WORKSPACE and function(...) _G.print('WQData', ...) end or nop Nenue@7: local QuestPOI = WorldPlanPOIMixin Nenue@7: Nenue@103: local pinBaseIndex = 1400 Nenue@103: local overlayBaseIndex = 1450 Nenue@56: local previousHighlight Nenue@40: Nenue@95: local FADE_TIMING_MULTIPLIER = 3 Nenue@67: local DATA_DEBUG = false Nenue@75: local PIN_REFRESH_DELAY = 1 Nenue@75: local PIN_REQUEST_DELAY = .2 Nenue@9: local ICON_UNKNOWN = "Interface\\ICONS\\inv_misc_questionmark" Nenue@9: local ICON_MONEY = "Interface\\Buttons\\UI-GroupLoot-Coin-Up" Nenue@9: Nenue@40: local WORLD_QUEST_BORDER = "Interface\\UNITPOWERBARALT\\Generic1Target_Circular_Frame" Nenue@47: local PENDING_BORDER = "Interface\\BUTTONS\\YELLOWORANGE64" Nenue@40: local PENDING_ICON = "Interface\\BUTTONS\\YELLOWORANGE64" Nenue@9: Nenue@29: local REWARD_CASH = WORLD_QUEST_REWARD_TYPE_FLAG_GOLD Nenue@29: local REWARD_ARTIFACT_POWER = WORLD_QUEST_REWARD_TYPE_FLAG_ARTIFACT_POWER Nenue@29: local REWARD_GEAR = WORLD_QUEST_REWARD_TYPE_FLAG_EQUIPMENT Nenue@29: local REWARD_CURRENCY = WORLD_QUEST_REWARD_TYPE_FLAG_ORDER_RESOURCES Nenue@29: local REWARD_REAGENT = WORLD_QUEST_REWARD_TYPE_FLAG_MATERIALS Nenue@69: Nenue@69: local REWARD_TYPE_NAMES = { Nenue@69: [REWARD_CASH] = 'Money', Nenue@69: [REWARD_ARTIFACT_POWER] = 'AP', Nenue@69: [REWARD_GEAR] = 'Equipment', Nenue@69: [REWARD_CURRENCY] = 'Currency', Nenue@69: [REWARD_REAGENT] = 'Trade Goods' Nenue@69: } Nenue@29: Nenue@29: local LE_QUEST_TAG_TYPE_PVP = LE_QUEST_TAG_TYPE_PVP Nenue@29: local LE_QUEST_TAG_TYPE_PET_BATTLE = LE_QUEST_TAG_TYPE_PET_BATTLE Nenue@29: local LE_QUEST_TAG_TYPE_DUNGEON = LE_QUEST_TAG_TYPE_DUNGEON Nenue@29: local LE_QUEST_TAG_TYPE_PROFESSION = LE_QUEST_TAG_TYPE_PROFESSION Nenue@29: local LE_QUEST_TAG_TYPE_NORMAL = LE_QUEST_TAG_TYPE_NORMAL Nenue@29: Nenue@29: local LE_QUEST_TAG_TYPE_PVP = LE_QUEST_TAG_TYPE_PVP Nenue@29: local LE_QUEST_TAG_TYPE_PET_BATTLE = LE_QUEST_TAG_TYPE_PET_BATTLE Nenue@29: local LE_QUEST_TAG_TYPE_DUNGEON = LE_QUEST_TAG_TYPE_DUNGEON Nenue@29: local LE_QUEST_TAG_TYPE_PROFESSION = LE_QUEST_TAG_TYPE_PROFESSION Nenue@29: local LE_QUEST_TAG_TYPE_NORMAL = LE_QUEST_TAG_TYPE_NORMAL Nenue@29: Nenue@66: local DEFAULT_STYLE = { Nenue@66: border = {1,1,1}, Nenue@69: textColor = {1,1,1,1}, Nenue@66: x = 0, y = 0, Nenue@66: desaturated = true, Nenue@66: iconMask = "Interface\\Minimap\\UI-Minimap-Background", Nenue@66: borderMask = "Interface\\Minimap\\UI-Minimap-Background", Nenue@66: rewardMark = "Interface\\Minimap\\UI-Minimap-Background", Nenue@66: scaleFactors = {0.25, 0.7, 1}, Nenue@66: iconWidth = 18, Nenue@66: borderWidth = 2, Nenue@66: highlightWidth = 2, Nenue@66: TagSize = 8, Nenue@95: maxAlertLevel = 3, Nenue@66: numberFontObject = 'WorldPlanFont' Nenue@66: } Nenue@66: local MINIMIZED_STYLE = { Nenue@66: hideNumber = true, Nenue@66: hideIcon = true, Nenue@67: iconWidth = 3, Nenue@66: } Nenue@66: local REWARD_TYPE_STYLES = { Nenue@66: [REWARD_CASH] = { Nenue@66: hideNumber = true, Nenue@66: }, Nenue@66: [REWARD_ARTIFACT_POWER] = {}, Nenue@66: [REWARD_GEAR] = { Nenue@66: hideNumber = true, Nenue@66: }, Nenue@69: [REWARD_CURRENCY] = { Nenue@69: textColor = {1,1,0,.5} Nenue@69: }, Nenue@66: [REWARD_REAGENT] = { Nenue@66: Nenue@66: hideNumber = true, Nenue@66: }, Nenue@66: } Nenue@74: local BORDER_SELECTED_BOUNTY = {1, 1, 0, 1 } Nenue@74: local BORDER_CRITERIA = {.25, .5, 1, 1} Nenue@66: Nenue@65: local LE_ITEM_CLASS_WEAPON, LE_ITEM_CLASS_ARMOR, LE_ITEM_CLASS_GEM, LE_ITEM_GEM_ARTIFACTRELIC, LE_ITEM_CLASS_TRADEGOODS = LE_ITEM_CLASS_WEAPON, LE_ITEM_CLASS_ARMOR, LE_ITEM_CLASS_GEM, LE_ITEM_GEM_ARTIFACTRELIC, LE_ITEM_CLASS_TRADEGOODS Nenue@65: Nenue@65: Nenue@40: local STYLE_TYPE_PENDING = 768 Nenue@40: Nenue@31: Nenue@29: -- Pin color/display variables Nenue@40: db.TooltipExtras = db.TooltipExtras or {} -- idiot-proofing Nenue@49: db.PinAlpha = 1 Nenue@29: Nenue@33: local familiars = { Nenue@40: [42159] = 'Nightwatcher Merayl', Nenue@40: [40277] = 'Tiffany Nelson', Nenue@40: [40298] = 'Sir Galveston', Nenue@40: [40282] = 'Grixis Tinypop', Nenue@40: [40278] = 'Robert Craig', Nenue@40: [48195] = 'Aulier', Nenue@40: [41990] = 'Varenne', Nenue@40: [41860] = 'Xorvasc', Nenue@40: [40299] = 'Bodhi Sunwayver', Nenue@40: [42442] = 'Amalia', Nenue@40: [40280] = 'Bredda Tenderhide', Nenue@40: [41687] = 'Odrogg', Nenue@40: [41944] = 'Trapper Jarrun', Nenue@40: [40337] = 'Master Tamer Flummox', Nenue@40: [40279] = 'Durian Strongfruit' Nenue@40: } Nenue@40: local falcosaurs = { Nenue@40: [44895] = {44881, 'Sharptalon Hatchling', 115786}, Nenue@40: [44894] = {44882, 'Bloodgazer Hatchling', 115787}, Nenue@40: [44893] = {44880, 'Direbeak Hatchling', 115785}, Nenue@40: [44892] = {44879, 'Snowfeather Hatchling', 115784}, Nenue@33: } Nenue@33: local familiars_id = 9696 Nenue@40: for questID, name in pairs(familiars) do Nenue@40: db.TooltipExtras[questID] = {{ Nenue@40: achievementID = familiars_id, Nenue@40: name = name Nenue@40: }} Nenue@40: end Nenue@40: for questID, info in pairs(falcosaurs) do Nenue@40: local trackingQuestID, petName, petID = unpack(info) Nenue@33: Nenue@40: db.TooltipExtras[questID] = {{ Nenue@40: questID = trackingQuestID, Nenue@40: pet = petName, Nenue@40: petID = petID Nenue@40: }} Nenue@9: end Nenue@7: Nenue@95: Nenue@95: do Nenue@95: local timeStates = { Nenue@95: {maxSeconds = 60, Nenue@95: r=1, g=0.25, b =0, format = function (minutes) return '|cFFFF4400'.. minutes .. 'm' end, Nenue@95: }, Nenue@95: {maxSeconds = 240, Nenue@95: r=1, g=.5, b=0, format = function(minutes) return '|cFFFF4400'.. floor(minutes/60) .. 'h' end, Nenue@95: }, Nenue@95: {maxSeconds = 1440, Nenue@95: r=1, g=1, b=0, format = function(minutes) return '|cFFFFFF00'.. floor(minutes/60) .. 'h' end, Nenue@95: }, Nenue@95: {maxSeconds = 10081, Nenue@95: r=0, g=1, b=0, Nenue@95: }, -- 7 days + 1 minute Nenue@95: } Nenue@95: -- Generates a timeleft string Nenue@95: function QuestPOI:GetTimeInfo(timeLeft, limit) Nenue@95: for index = 1, limit do Nenue@95: local state = timeStates[index] Nenue@95: if timeLeft <= state.maxSeconds then Nenue@95: local text Nenue@95: if state.format then Nenue@95: text = state.format(timeLeft) Nenue@95: end Nenue@95: return text, index, state Nenue@95: end Nenue@95: end Nenue@95: return Nenue@95: end Nenue@95: end Nenue@95: Nenue@95: Nenue@40: local GetAchievementTooltipExtras = function(info) Nenue@29: Nenue@40: local hasInfo Nenue@40: local achievementID = info.achievementID Nenue@40: local _, name, _, completed, _, _, _, _, _, icon = GetAchievementInfo(achievementID) Nenue@40: if not completed then Nenue@40: Nenue@40: local numItems = GetAchievementNumCriteria(achievementID) Nenue@40: local numNeeded = 0 Nenue@40: local tooltipLines = {} Nenue@40: for i =1, numItems do Nenue@40: local criteriaName, criteriaType, completed, _, _, _, _, subAchievementID = GetAchievementCriteriaInfo(achievementID, i) Nenue@49: --print(GetAchievementCriteriaInfo(achievementID, i)) Nenue@40: Nenue@40: if not completed then Nenue@49: --print('::', criteriaName, completed, subAchievementID) Nenue@40: if criteriaType == 8 then Nenue@40: local _, _, _, completed, _, _, _, _, _, subIcon = GetAchievementInfo(subAchievementID) Nenue@49: --print(' -', criteriaName, completed, subIcon) Nenue@40: if not completed then Nenue@40: local numCompleted = 0 Nenue@40: local numSubItems = GetAchievementNumCriteria(subAchievementID) Nenue@40: local subCriteriaLine Nenue@40: for j = 1, numSubItems do Nenue@40: local subName, _, completed = GetAchievementCriteriaInfo(subAchievementID, j) Nenue@40: Nenue@49: --print(' -',subName, completed) Nenue@40: if completed then Nenue@40: numCompleted = numCompleted + 1 Nenue@40: else Nenue@40: numNeeded = numNeeded + 1 Nenue@40: if subName:match(info.name) then Nenue@40: hasInfo = true Nenue@40: subCriteriaLine = ' |T'..subIcon..':16:16|t ' .. criteriaName Nenue@40: end Nenue@40: end Nenue@40: Nenue@40: end Nenue@40: if subCriteriaLine then Nenue@40: tinsert(tooltipLines, subCriteriaLine .. ' ('..numCompleted..'/'..numSubItems..')') Nenue@40: end Nenue@40: end Nenue@40: elseif criteriaName:match(info.name) and (not completed) then Nenue@40: numNeeded = numNeeded + 1 Nenue@40: tinsert(tooltipLines, criteriaName) Nenue@40: end Nenue@40: end Nenue@40: end Nenue@49: if hasInfo then Nenue@49: WorldMapTooltip:AddLine(" ") Nenue@49: WorldMapTooltip:AddLine("Achievements:") Nenue@49: WorldMapTooltip:AddLine(' |T'..icon..':20:20|t '..name) Nenue@40: for i, line in ipairs(tooltipLines) do Nenue@40: WorldMapTooltip:AddLine(line) Nenue@40: end Nenue@40: end Nenue@40: end Nenue@40: return hasInfo Nenue@40: end Nenue@40: Nenue@40: local GetQuestTooltipExtras = function(info) Nenue@40: local questID = info.questID Nenue@40: local hasInfo Nenue@40: Nenue@40: if info.pet then Nenue@40: local index, guid = C_PetJournal.FindPetIDByName(info.pet) Nenue@40: if not index then Nenue@40: hasInfo = true Nenue@40: WorldMapTooltip:AddLine('Pets:') Nenue@40: WorldMapTooltip:AddLine(' - ' .. info.petName) Nenue@40: Nenue@40: if not IsQuestFlaggedCompleted(questID) then Nenue@40: WorldMapTooltip:AddLine(' Required Quest Flags', 1, 1, 0) Nenue@40: else Nenue@40: WorldMapTooltip:AddLine(' Quest Flags Complete!', 0, 1, 0) Nenue@40: end Nenue@40: Nenue@40: end Nenue@29: end Nenue@29: Nenue@29: end Nenue@29: Nenue@93: function QuestPOI:OnLoad() Nenue@100: --print('|cFF00FF88'..self:GetName()..':OnLoad()|r',db.Config) Nenue@93: self.debugTimer = 4 Nenue@93: self.title = '|cFF0088FF' .. RETRIEVING_DATA..'|r' Nenue@93: self.count = self.Overlay.count Nenue@93: self.timeLabel = self.Overlay.timeLabel Nenue@93: self.Description = self.Overlay.Description Nenue@93: self.updateRate = PIN_REQUEST_DELAY Nenue@93: self.itemName = '|cFF0088FF' .. RETRIEVING_DATA..'|r' Nenue@100: self.checkFilters = true Nenue@100: self.checkCriteria = true Nenue@100: self.checkCursor = true Nenue@100: self.worldQuest = true Nenue@100: self.isNew = true Nenue@93: Nenue@93: self.IconBackdrop:SetVertexColor(0,0,0,1) Nenue@93: self.Overlay:SetPoint('TOPLEFT', self, 'TOPLEFT', 0, 4) Nenue@93: self.Overlay:SetPoint('BOTTOMRIGHT', self, 'BOTTOMRIGHT', 0, -4) Nenue@93: end Nenue@93: Nenue@93: function QuestPOI:OnShow () Nenue@93: if self.isStale then Nenue@93: --print('|cFF00FF00refresh on show') Nenue@93: self:Refresh('POI_ONSHOW_STALE') Nenue@93: end Nenue@95: Nenue@95: if self.questID and IsQuestComplete(self.questID) then Nenue@95: self:Release() Nenue@95: return Nenue@95: end Nenue@95: Nenue@93: self:RegisterEvent('QUEST_TURNED_IN') Nenue@93: self:RegisterEvent('QUEST_LOG_UPDATE') Nenue@93: self:HideOrShowFrames(true) Nenue@93: end Nenue@93: Nenue@93: function QuestPOI:OnEvent(event, questID) Nenue@93: if (self.questID == questID) and IsQuestComplete(self.questID) then Nenue@103: db.log(event .. ' for ' .. self:GetName().. ' triggered.') Nenue@93: self:Release() Nenue@93: end Nenue@93: end Nenue@93: Nenue@93: function QuestPOI:OnHide() Nenue@93: --DEFAULT_CHAT_FRAME:AddMessage('|cFFFFFF00'..self:GetName()..'|r:OnHide()') Nenue@93: self:HideOrShowFrames(false) Nenue@93: -- reset flags Nenue@93: self:SetAlpha(db.PinAlpha) Nenue@93: self.isAnimating = nil Nenue@103: --if db.Config.DebugEnabled then Nenue@103: -- db.log(tostring(self.questID) .. ' ' .. tostring(self.title) .. "\n" .. tostring(REWARD_TYPE_NAMES[self.rewardType]) .. ' ' .. tostring(self.itemName) .. ' ' .. tostring(self.itemNumber) .. "\n|cFFFF4400" .. (self.hideReason or 'NO_MESSAGE') .. "|r\n|cFF00FFFF" .. debugstack(2,3,0) .. '|r') Nenue@103: --end Nenue@93: self.hideReason = nil Nenue@93: end Nenue@40: Nenue@40: function QuestPOI:OnEnter() Nenue@57: if self.filtered and (self.questID ~= GetSuperTrackedQuestID()) then Nenue@49: return Nenue@7: end Nenue@57: WorldMap_HijackTooltip(self.owningFrame); Nenue@56: self:SetFrameLevel(pinBaseIndex+100) Nenue@78: self.Overlay:SetFrameLevel(overlayBaseIndex+100) Nenue@56: Nenue@56: if previousHighlight then Nenue@56: previousHighlight:SetFrameLevel(pinBaseIndex+previousHighlight:GetID()) Nenue@56: previousHighlight.Overlay:SetFrameLevel(overlayBaseIndex+previousHighlight:GetID()) Nenue@56: end Nenue@56: Nenue@56: previousHighlight = self Nenue@56: Nenue@56: Nenue@40: WorldMapTooltip:SetOwner(self, "ANCHOR_RIGHT"); Nenue@49: --print('doing tooltip stuff') Nenue@40: Nenue@40: -- Can't add stuff after, so most of the blizzard tooltip hook is simply copied over Nenue@40: local questID = self.questID Nenue@40: local color = WORLD_QUEST_QUALITY_COLORS[self.rarity] or NORMAL_FONT_COLOR; Nenue@40: Nenue@40: Nenue@40: WorldMapTooltip:SetText(self.title, color.r, color.g, color.b); Nenue@40: QuestUtils_AddQuestTypeToTooltip(WorldMapTooltip, questID, NORMAL_FONT_COLOR); Nenue@40: Nenue@40: if ( self.factionID ) then Nenue@40: local factionName = GetFactionInfoByID(self.factionID); Nenue@40: if ( factionName ) then Nenue@40: if (self.capped) then Nenue@40: WorldMapTooltip:AddLine(factionName, GRAY_FONT_COLOR:GetRGB()); Nenue@40: else Nenue@40: WorldMapTooltip:AddLine(factionName); Nenue@40: end Nenue@40: end Nenue@40: end Nenue@40: Nenue@40: if self.worldQuest then Nenue@40: WorldMap_AddQuestTimeToTooltip(questID); Nenue@40: end Nenue@40: Nenue@40: Nenue@40: for objectiveIndex = 1, self.numObjectives do Nenue@40: local objectiveText, objectiveType, finished = GetQuestObjectiveInfo(questID, objectiveIndex, false); Nenue@40: if ( objectiveText and #objectiveText > 0 ) then Nenue@40: local color = finished and GRAY_FONT_COLOR or HIGHLIGHT_FONT_COLOR; Nenue@40: WorldMapTooltip:AddLine(QUEST_DASH .. objectiveText, color.r, color.g, color.b, true); Nenue@40: end Nenue@40: end Nenue@40: Nenue@40: local percent = C_TaskQuest.GetQuestProgressBarInfo(self.questID); Nenue@40: if ( percent ) then Nenue@40: GameTooltip_InsertFrame(WorldMapTooltip, WorldMapTaskTooltipStatusBar); Nenue@40: WorldMapTaskTooltipStatusBar.Bar:SetValue(percent); Nenue@40: WorldMapTaskTooltipStatusBar.Bar.Label:SetFormattedText(PERCENTAGE_STRING, percent); Nenue@40: end Nenue@40: Nenue@40: if db.TooltipExtras[self.questID] then Nenue@40: for index, info in pairs(db.TooltipExtras[questID]) do Nenue@40: if info.achievementID then Nenue@40: GetAchievementTooltipExtras(info) Nenue@40: end Nenue@40: if info.questID then Nenue@40: GetQuestTooltipExtras(info) Nenue@40: end Nenue@40: end Nenue@40: end Nenue@65: GameTooltip_AddQuestRewardsToTooltip(WorldMapTooltip, questID) Nenue@40: Nenue@40: WorldMapTooltip:Show() Nenue@40: --WorldMapTooltip.recalculatePadding = true; Nenue@40: --print(WorldMapTooltip:GetParent()) Nenue@40: --print(WorldMapTooltip:IsVisible()) Nenue@7: end Nenue@93: Nenue@93: function QuestPOI:OnMouseDown(button) Nenue@100: Nenue@93: if button == 'RightButton' then Nenue@100: Nenue@100: local timers = db.IgnoreTimers Nenue@100: if timers[self.questID] then Nenue@100: timers[self.questID] = nil Nenue@100: else Nenue@100: local tl = TQ_GetQuestTimeLeftMinutes(self.questID) Nenue@100: if tl and (tl ~= 0) then Nenue@100: timers[self.questID] = time() + (tl * 60) Nenue@100: else Nenue@100: timers[self.questID] = 0 Nenue@100: end Nenue@100: end Nenue@100: self:Refresh() Nenue@93: else Nenue@93: TaskPOI_OnClick(self, button) Nenue@93: end Nenue@93: end Nenue@93: Nenue@40: function QuestPOI:OnLeave() Nenue@57: if self.filtered and (self.questID ~= GetSuperTrackedQuestID()) then Nenue@57: return Nenue@57: end Nenue@35: WorldMap_RestoreTooltip() Nenue@40: WorldMapTooltip:Hide(); Nenue@7: end Nenue@7: Nenue@96: Nenue@96: Nenue@93: local updateTime, markTime Nenue@93: function QuestPOI:OnUpdate (sinceLast) Nenue@93: -- control update check intervals Nenue@93: Nenue@95: if self.toAlpha then Nenue@95: if not self.alphaStart then Nenue@95: self.alphaStart = GetTime() Nenue@95: end Nenue@93: Nenue@93: Nenue@95: local alpha = self.icon:GetAlpha() Nenue@95: local alphaMod = ((GetTime()-self.alphaStart) *FADE_TIMING_MULTIPLIER) Nenue@96: Nenue@95: if alpha > self.toAlpha then Nenue@95: alpha = alpha - (sinceLast*FADE_TIMING_MULTIPLIER) Nenue@95: Nenue@95: if (alpha <= self.toAlpha) then Nenue@95: alpha = self.toAlpha Nenue@95: self.toAlpha = nil Nenue@95: elseif (alpha <= 0) then Nenue@95: alpha = 0 Nenue@95: self.toAlpha = nil Nenue@95: end Nenue@95: elseif alpha < self.toAlpha then Nenue@95: alpha = alpha + alphaMod Nenue@95: Nenue@95: if (alpha >= self.toAlpha) then Nenue@95: alpha = self.toAlpha Nenue@95: self.toAlpha = nil Nenue@95: elseif (alpha >= 1) then Nenue@95: alpha = 1 Nenue@95: self.toAlpha = nil Nenue@95: end Nenue@95: Nenue@95: else Nenue@95: self.toAlpha = nil Nenue@95: end Nenue@95: Nenue@95: if not self.toAlpha then Nenue@95: self.alphaStart = nil Nenue@95: else Nenue@95: self.alphaStart = GetTime() Nenue@93: end Nenue@93: Nenue@93: self.icon:SetAlpha(alpha) Nenue@93: self.RewardBorder:SetAlpha(alpha) Nenue@93: end Nenue@93: Nenue@93: self.throttle = (self.throttle or self.updateRate) + sinceLast Nenue@93: if self.throttle >= self.updateRate then Nenue@93: -- factor overtime into the throttle timer Nenue@93: self.throttle = self.throttle - self.updateRate Nenue@93: else Nenue@93: return Nenue@93: end Nenue@93: --@debug@ Nenue@93: if DATA_DEBUG then Nenue@93: self.debugTimer = self.debugTimer - sinceLast Nenue@93: if self.debugTimer >= 0 then Nenue@93: print(self.debugTimer) Nenue@93: return Nenue@93: end Nenue@93: end Nenue@93: --@end-debug@ Nenue@93: Nenue@93: -- query for reward data if it wasn't found in the original scan Nenue@93: Nenue@93: if not self.dataLoaded then Nenue@93: local dataLoaded = self:GetData() Nenue@93: if dataLoaded and not tContains(db.UpdatedPins, self) then Nenue@93: -- self.PendingFade:Stop() Nenue@93: -- scale info from the parent module is needed, so deal with it there Nenue@93: print('|cFF00FF88 queueing for update') Nenue@93: self.isNew = true Nenue@93: tinsert(db.UpdatedPins, self) Nenue@93: else Nenue@93: Nenue@93: --print('|cFFFF4400OnUpdate(|r'..self:GetID()..'|cFFFF4400)|r poll failed') Nenue@93: end Nenue@93: return Nenue@93: end Nenue@93: Nenue@103: if self.isStale then Nenue@103: self:Refresh() Nenue@103: elseif self.maxAlertLevel then Nenue@93: self:UpdateStatus() Nenue@93: end Nenue@93: end Nenue@93: Nenue@93: Nenue@93: function QuestPOI:StartFading() Nenue@95: if not self.toAlpha then Nenue@95: print('setting toAlpha') Nenue@95: self.toAlpha = 1 Nenue@93: self.icon:SetAlpha(0) Nenue@93: self.RewardBorder:SetAlpha(0) Nenue@93: end Nenue@93: end Nenue@93: Nenue@40: -- attempt to pull pin data Nenue@40: function QuestPOI:GetData () Nenue@75: --dprint('|cFF00FF88'..self:GetID()..':GetData()|r') Nenue@40: local questID = self.questID Nenue@40: if not questID then Nenue@75: --dprint('|cFFFF4400bad pin|r', self:GetName()) Nenue@40: return nil Nenue@29: end Nenue@29: Nenue@40: local questTitle, factionID, capped = TQ_GetQuestInfoByQuestID(questID) Nenue@40: -- if the title is nil, then wait and try later Nenue@40: if not questTitle then Nenue@75: --dprint('|cFFBB8844dataLoaded|r = false|cFF00FFFF', self.questId) Nenue@65: return false Nenue@40: else Nenue@40: self.title, self.factionID, self.capped = questTitle, factionID, capped Nenue@93: --print(questTitle, factionID, capped) Nenue@40: -- set tag details Nenue@40: local worldQuestType Nenue@40: self.tagID, self.tagName, worldQuestType, self.rarity, self.isElite, self.tradeskillLineIndex = GetQuestTagInfo(questID); Nenue@40: local tagAtlas Nenue@40: if worldQuestType == LE_QUEST_TAG_TYPE_PET_BATTLE then Nenue@40: tagAtlas = "worldquest-icon-petbattle" Nenue@40: elseif worldQuestType == LE_QUEST_TAG_TYPE_PVP then Nenue@40: tagAtlas = "worldquest-icon-pvp-ffa" Nenue@40: elseif worldQuestType == LE_QUEST_TAG_TYPE_PROFESSION then Nenue@40: self.isKnownProfession = nil Nenue@40: local id = self.tradeskillLineIndex and select(7, GetProfessionInfo(self.tradeskillLineIndex)) Nenue@40: if id then Nenue@40: self.isKnownProfession = true Nenue@100: --print('profession' , self.title, id) Nenue@40: tagAtlas = WORLD_QUEST_ICONS_BY_PROFESSION[id] Nenue@40: end Nenue@40: elseif worldQuestType == LE_QUEST_TAG_TYPE_DUNGEON then Nenue@40: tagAtlas = "worldquest-icon-dungeon" Nenue@40: end Nenue@40: self.worldQuestType = worldQuestType Nenue@40: self.tagAtlas = tagAtlas Nenue@29: Nenue@69: local dataLoaded, rewardType, itemName, itemTexture, itemNumber, quality, xpType, xpName, xpIcon, xpCount = self:UpdateRewards() Nenue@75: --dprint('|cFFBB8844 dataLoaded|r =', dataLoaded, rewardType, itemName, itemTexture, itemNumber, quality) Nenue@65: if dataLoaded then Nenue@65: self.rewardType = rewardType Nenue@65: self.itemName = itemName Nenue@65: self.itemTexture = itemTexture Nenue@65: self.itemNumber = itemNumber Nenue@65: self.itemQuality = quality Nenue@49: self.dataLoaded = true Nenue@48: self.isStale = true Nenue@69: self.xpType, self.xpName, self.xpIcon, self.xpCount = xpType, xpName, xpIcon, xpCount Nenue@95: WorldPlan.dataFlush = true Nenue@40: end Nenue@40: end Nenue@40: Nenue@40: Nenue@65: return self.dataLoaded Nenue@40: end Nenue@40: Nenue@69: local ID_RESOURCES = 1220 Nenue@69: local ID_LEGIONFALL = 1342 Nenue@69: Nenue@65: --- Returns true if data has changed (either from loading in or qualifications changed) Nenue@65: function QuestPOI:UpdateRewards() Nenue@40: local questID = self.questID Nenue@65: if not HaveQuestRewardData(questID) then Nenue@65: C_TaskQuest.RequestPreloadRewardData(questID); Nenue@65: return false; Nenue@29: else Nenue@65: local rewardMoney, rewardAP, rewardHonor Nenue@65: local rewardItems, rewardCurrency = {}, {} Nenue@65: local rewardIcon, rewardName, rewardCount, rewardStyle, rewardType, itemID, quantity, quality Nenue@65: local xpIcon, xpName, xpCount, xpType Nenue@69: local foundPrimary Nenue@29: Nenue@65: if (GetNumQuestLogRewardCurrencies(questID) > 0 or GetNumQuestLogRewards(questID) > 0 or GetQuestLogRewardMoney(questID) > 0 or GetQuestLogRewardArtifactXP(questID) > 0 or GetQuestLogRewardHonor(questID)) then Nenue@65: local money = GetQuestLogRewardMoney(questID) Nenue@65: if money > 0 then Nenue@65: rewardMoney = money Nenue@65: rewardIcon = ICON_MONEY Nenue@65: rewardName = GetMoneyString(money) Nenue@65: rewardCount = floor(money/10000) Nenue@65: rewardType = REWARD_CASH Nenue@65: end Nenue@65: Nenue@65: local artifactXP = GetQuestLogRewardArtifactXP(questID); Nenue@65: if artifactXP > 0 then Nenue@65: rewardAP = artifactXP Nenue@65: rewardIcon = "Interface\\ICONS\\inv_7xp_inscription_talenttome01" Nenue@65: rewardCount = artifactXP Nenue@65: rewardType = REWARD_ARTIFACT_POWER Nenue@75: --dprint(' artifactXP', artifactXP) Nenue@69: foundPrimary = true Nenue@65: end Nenue@65: Nenue@65: local numQuestCurrencies = GetNumQuestLogRewardCurrencies(questID); Nenue@65: for i = 1, numQuestCurrencies do Nenue@69: local name, texture, numItems, currencyID = GetQuestLogRewardCurrencyInfo(i, questID); Nenue@65: local text = BONUS_OBJECTIVE_REWARD_WITH_COUNT_FORMAT:format(texture, numItems, name); Nenue@65: tinsert(rewardCurrency, { Nenue@65: name = name, Nenue@65: texture = texture, Nenue@65: numItems = numItems, Nenue@65: text = text Nenue@65: }) Nenue@69: Nenue@75: --dprint(' currency', i, currencyID, name, " |T"..tostring(texture)..":12:12|t") Nenue@69: if currencyID == ID_RESOURCES then Nenue@69: rewardIcon = texture Nenue@69: rewardCount = numItems Nenue@69: rewardName = name Nenue@69: rewardType = REWARD_CURRENCY Nenue@69: foundPrimary = true Nenue@69: elseif currencyID == ID_LEGIONFALL then Nenue@69: xpIcon = texture Nenue@69: xpCount = numItems Nenue@69: xpName = name Nenue@69: xpType = REWARD_CURRENCY Nenue@69: end Nenue@89: end Nenue@69: Nenue@65: local honorAmount = GetQuestLogRewardHonor(questID); Nenue@65: if honorAmount > 0 then Nenue@89: xpIcon = "Interface\\ICONS\\Achievement_LegionPVPTier4" Nenue@89: xpCount = honorAmount Nenue@89: xpName = HONOR Nenue@89: xpType = HONOR_CURRENCY Nenue@88: -- let items override Nenue@65: end Nenue@65: Nenue@65: local numQuestRewards = GetNumQuestLogRewards(questID); Nenue@65: if numQuestRewards > 0 then Nenue@65: for i = 1, numQuestRewards do Nenue@65: local name, texture, numItems, quality, isUsable, itemID = GetQuestLogRewardInfo(i, questID) Nenue@65: Nenue@65: if itemID then Nenue@65: local itemName, itemLink, itemRarity, itemLevel, itemMinLevel, itemType, itemSubType, itemStackCount, itemEquipLoc, itemTexture, sellPrice, classID, subclassID = GetItemInfo(itemID); Nenue@65: if ( classID == LE_ITEM_CLASS_WEAPON or classID == LE_ITEM_CLASS_ARMOR or (classID == LE_ITEM_CLASS_GEM and subclassID == LE_ITEM_GEM_ARTIFACTRELIC) ) then Nenue@65: rewardType = REWARD_GEAR Nenue@65: rewardIcon = texture Nenue@65: rewardName = name Nenue@65: rewardCount = numItems Nenue@65: foundPrimary = true Nenue@65: elseif IsArtifactPowerItem(itemID) then Nenue@65: rewardType = REWARD_ARTIFACT_POWER Nenue@65: rewardIcon = texture Nenue@65: rewardName = name Nenue@93: rewardCount = self:UpdateArtifactPower(itemLink) Nenue@65: foundPrimary = true Nenue@75: --dprint('is an AP token') Nenue@65: elseif classID == LE_ITEM_CLASS_TRADEGOODS then Nenue@65: rewardType = REWARD_REAGENT Nenue@65: rewardIcon = texture Nenue@65: rewardName = name Nenue@65: rewardCount = numItems Nenue@65: foundPrimary = true Nenue@65: end Nenue@75: --dprint(' reward', i, name, " |T"..tostring(texture)..":12:12|t", quality, isUsable, itemID) Nenue@65: tinsert(rewardItems, { Nenue@65: name = name, Nenue@65: texture = texture, Nenue@65: numItems = numItems, Nenue@65: quality = quality, Nenue@65: isUsable = isUsable Nenue@65: }) Nenue@65: if not foundPrimary then Nenue@75: --print(' -updating primary') Nenue@82: rewardType = REWARD_REAGENT Nenue@65: Nenue@65: rewardIcon = texture Nenue@65: rewardName = name Nenue@65: rewardCount = numItems Nenue@65: end Nenue@65: Nenue@65: end Nenue@65: Nenue@65: end Nenue@65: end Nenue@65: Nenue@75: --dprint(' '..self.questID..':|cFFFFFF00UpdateRewards():', numQuestRewards, rewardType) Nenue@75: --dprint(' ', tostring(self.title), " |T"..tostring(self.itemTexture)..":12:12|t", tostring(self.itemName)) Nenue@65: Nenue@89: if rewardType and ((self.itemNumber ~= rewardCount) or (self.rewardType ~= rewardType) or (self.itemName ~= rewardName) or (self.itemTexture ~= rewardIcon)) then Nenue@67: if DATA_DEBUG and (self.debugTimer <= 0) then Nenue@67: return false Nenue@67: end Nenue@67: Nenue@89: return true, rewardType, rewardName, rewardIcon, rewardCount, quality, xpType, xpName, xpIcon, xpCount Nenue@67: Nenue@65: else Nenue@65: return false Nenue@65: end Nenue@65: end Nenue@40: end Nenue@7: end Nenue@7: Nenue@34: Nenue@93: function QuestPOI:UpdateArtifactPower(rewardLink) Nenue@93: if not (rewardLink or self.rewardLink) then Nenue@75: return Nenue@75: end Nenue@75: Nenue@93: self.rewardLink = rewardLink or self.rewardLink Nenue@49: Nenue@93: local rewardCount Nenue@93: WorldPlanTooltip:SetOwner(self, 'ANCHOR_NONE') Nenue@93: WorldPlanTooltip:SetHyperlink(rewardLink or self.rewardLink) Nenue@93: for i = 1, WorldPlanTooltip:NumLines() do Nenue@93: local line = _G['WorldPlanTooltipTextLeft' .. i] Nenue@93: local text = line and line:GetText() Nenue@95: local multiplier = (text:match('million') and 1000000) or 1 Nenue@95: if text then Nenue@95: text = text:gsub(',', '') Nenue@95: local ap = text:match('([%d]+) '..ARTIFACT_POWER) Nenue@95: if not ap then Nenue@95: ap = text:match('([%d%.]+) million '..ARTIFACT_POWER) Nenue@95: if ap then Nenue@95: ap = tonumber(ap) * 1000000 Nenue@95: end Nenue@95: end Nenue@95: if ap then Nenue@95: rewardCount = tonumber(ap) Nenue@95: end Nenue@69: end Nenue@48: end Nenue@93: return rewardCount Nenue@27: end Nenue@27: Nenue@67: -- Applies position and sizing parameters to the pin data Nenue@66: function QuestPOI:SetAnchor(owner, dX, dY, mapWidth, mapHeight, scaleFactor) Nenue@75: --dprint(self:GetName()..':SetAnchor()', owner, dX, dY, scaleFactor, self.filtered, self.used) Nick@62: if not self.used then Nenue@69: self.hideReason = 'SetAnchor() on an unused frame.' Nenue@93: self:HideOrShowFrames(false) Nick@62: return Nick@62: end Nick@62: Nenue@67: if owner then Nenue@67: self:SetParent(owner) Nenue@67: self.Overlay:SetParent(owner) Nenue@78: self:SetFrameStrata('HIGH') Nenue@78: self:SetFrameLevel(pinBaseIndex + self:GetID()) Nenue@78: self.Overlay:SetFrameStrata('HIGH') Nenue@78: self.Overlay:SetFrameLevel(overlayBaseIndex + self:GetID()) Nenue@74: self.isStale = true Nenue@67: else Nenue@67: owner = self:GetParent() Nenue@67: end Nenue@67: Nenue@74: Nenue@74: if scaleFactor then Nenue@82: print('scaleFactor') Nenue@67: self:SetScale(scaleFactor) Nenue@67: self.Overlay:SetScale(scaleFactor) Nenue@67: self.scaleFactor = scaleFactor Nenue@67: end Nenue@67: Nenue@74: mapWidth = mapWidth or owner:GetWidth() Nenue@74: mapHeight = mapHeight or owner:GetHeight() Nenue@74: dX = dX or self.x Nenue@74: dY = dY or self.y Nenue@74: --print(owner:GetName() or tostring(owner), self:GetName(), owner:GetScale(), scaleFactor) Nenue@74: if (self.x ~= dX) or (self.y ~= dY) or scaleFactor then Nenue@67: Nenue@74: self.x = dX Nenue@74: self.y = dY Nenue@74: local pX = (dX * mapWidth) * (1 / scaleFactor) Nenue@74: local pY = (-dY * mapHeight) * (1 / scaleFactor) Nenue@74: --print('to', pX, pY, self:GetScale()) Nenue@74: self:ClearAllPoints() Nenue@74: self:SetPoint('CENTER', owner, 'TOPLEFT', pX, pY) Nenue@53: end Nick@62: Nick@62: end Nick@62: Nenue@78: -- Non-hieriarchical display states, checked separately from used/filtered states Nenue@100: function QuestPOI:OnCriteria() Nenue@100: self.checkCriteria = nil Nenue@74: local isCriteria, isBounty, isSpellTarget Nenue@93: Nenue@103: print('|cFFFFFF00OnCriteria(' ..self:GetID() .. ')' ) Nenue@93: Nenue@93: for index, bounty in pairs(db.Bounties) do Nenue@93: if (not IsQuestComplete(bounty.questID)) and IsQuestCriteriaForBounty(self.questID, bounty.questID) then Nenue@93: isCriteria = true Nenue@93: if db.selectedBounty == bounty then Nenue@93: isBounty = true Nenue@74: end Nenue@93: --dprint('|cFF00FF88Criteria:|r', self.questID, bounty.questID, isCriteria, isBounty) Nenue@74: end Nenue@74: end Nenue@74: Nenue@100: if (self.isBounty ~= isBounty) or (self.isCriteria ~= isCriteria) then Nenue@75: --wqprint('|cFF00FF00criteria state changed') Nenue@74: self.isBounty = isBounty Nenue@74: self.isCriteria = isCriteria Nenue@74: self.isSpellTarget = isSpellTarget Nenue@74: end Nenue@74: end Nenue@74: Nenue@100: function QuestPOI:OnCursor() Nenue@100: self.checkCursor = nil Nenue@100: self.isSpellTarget = IsQuestIDValidSpellTarget(self.questID) Nenue@100: end Nenue@100: Nenue@35: local cvar_check = { Nenue@35: [REWARD_CASH] = 'worldQuestFilterGold', Nenue@35: [REWARD_ARTIFACT_POWER] = 'worldQuestFilterArtifactPower', Nenue@35: [REWARD_CURRENCY] = 'worldQuestFilterOrderResources', Nenue@35: [REWARD_REAGENT]= 'worldQuestFilterProfessionMaterials', Nenue@35: [REWARD_GEAR] = 'worldQuestFilterEquipment', Nenue@35: } Nenue@8: Nick@64: Nenue@100: function QuestPOI:OnFilters () Nenue@33: local qType = self.worldQuestType Nenue@96: Nenue@96: self.canShow = false Nenue@100: self.checkFilters = nil Nenue@96: Nenue@78: if not TQ_IsActive(self.questID) then Nenue@78: self.hideReason = 'Filter check ended because quest is inactive.' Nenue@78: self.used = nil Nenue@78: self:SetShown(false) Nenue@78: return Nenue@78: end Nenue@69: Nenue@69: if qType == LE_QUEST_TAG_TYPE_PROFESSION then Nenue@57: if not(self.isKnownProfession or db.Config.ShowAllProfessionQuests) then Nenue@78: self.hideReason = 'Failed profession check.' Nenue@78: self.used = nil Nenue@78: self:SetShown(false) Nenue@78: return Nenue@36: end Nenue@36: end Nenue@57: Nenue@78: local filtered Nenue@78: for filterKey, value in pairs(db.UsedFilters) do Nenue@78: if self[filterKey] ~= value then Nenue@78: if not self.filtered then Nenue@78: print('|cFFFF4400filtering', filterKey, value, '~=', self[filterKey], self.title) Nenue@57: end Nenue@78: filtered = true Nenue@57: end Nenue@78: end Nenue@78: if self.rewardType and cvar_check[self.rewardType] then Nenue@78: if not GetCVarBool(cvar_check[self.rewardType]) then Nenue@78: filtered = true Nenue@57: end Nenue@57: end Nenue@78: Nenue@100: print(' '..self.questID..':|cFFFFFF00OnFilters()|r', filtered, self.title) Nenue@78: if self.filtered ~= filtered then Nenue@82: wqprint('|cFF00FF00filter changed') Nenue@78: self.isStale = true Nenue@69: end Nenue@78: Nenue@96: self.canShow = true Nenue@82: self.filtered = filtered Nenue@33: end Nenue@33: Nenue@93: function QuestPOI:Refresh (event) Nenue@93: print('|cFF00FF88Refresh(|r'..self:GetID()..'|cFF00FF88)|r', event, self.title) Nenue@33: Nenue@100: if not self:IsShown() then Nenue@100: print('queued for Refresh') Nenue@100: self.isStale = true Nenue@100: return nil Nenue@103: elseif IsQuestComplete(self.questID) then Nenue@103: self:Release() Nenue@103: return nil Nenue@100: end Nenue@100: if self.checkCriteria then Nenue@100: self:OnCriteria() Nenue@100: end Nenue@100: if self.checkFilters then Nenue@100: self:OnFilters() Nenue@100: end Nenue@100: if self.checkCursor then Nenue@100: self:OnCursor() Nenue@100: end Nenue@93: Nenue@93: local style = DEFAULT_STYLE Nenue@100: if self.filtered or db.IgnoreTimers[self.questID] then Nenue@93: print('choose minimized') Nenue@93: style = MINIMIZED_STYLE Nenue@93: elseif self.dataLoaded then Nenue@93: print('choose reward type') Nenue@93: style = REWARD_TYPE_STYLES[self.rewardType] Nenue@93: else Nenue@93: print('choose default') Nenue@93: end Nenue@93: Nenue@93: local currentWidth = style.iconWidth or DEFAULT_STYLE.iconWidth Nenue@93: local borderWidth = style.borderWidth or DEFAULT_STYLE.borderWidth Nenue@93: local highlightWidth = style.highlightWidth or DEFAULT_STYLE.highlightWidth Nenue@93: local tagSize = style.TagSize or DEFAULT_STYLE.TagSize Nenue@93: local hideIcon = style.hideIcon or DEFAULT_STYLE.hideIcon Nenue@93: local borderColor = style.border or DEFAULT_STYLE.border Nenue@93: local textColor = style.textColor or DEFAULT_STYLE.textColor Nenue@93: local questID = self.questID Nenue@36: local iconBorder = self.RewardBorder Nenue@36: local trackingBorder = self.HighlightBorder Nenue@93: local icon = self.icon Nenue@93: local count = self.count Nenue@93: local hideNumbers = style.hideNumber or DEFAULT_STYLE.hideNumber Nenue@33: Nenue@33: Nenue@93: local tagIcon = self.tagIcon Nenue@93: self.maxAlertLevel = style.maxAlertLevel or DEFAULT_STYLE.maxAlertLevel Nenue@47: Nenue@93: if self.dataLoaded then Nenue@93: if self.isNew then Nenue@95: print('new pin, has data, cue fade') Nenue@93: self:StartFading() Nenue@93: self.isNew = nil Nenue@93: end Nenue@93: else Nenue@95: if not self.toAlpha then Nenue@95: icon:SetAlpha(0) Nenue@95: iconBorder:SetAlpha(0) Nenue@93: end Nenue@93: end Nenue@93: Nenue@93: if self.itemName then Nenue@93: if self.itemNumber and (self.itemNumber > 1) and (not hideNumbers) then Nenue@93: local numberString = self.itemNumber Nenue@93: if self.itemNumber >= 1000000 then Nenue@93: numberString = (floor(self.itemNumber/100000)/10) .. 'M' Nenue@93: elseif self.itemNumber >= 10000 then Nenue@93: numberString = floor(self.itemNumber/1000) .. 'k' Nenue@93: elseif self.itemNumber >= 1000 then Nenue@93: local numeral = floor(self.itemNumber/1000) Nenue@93: local decimal = mod(self.itemNumber, 1000) Nenue@93: numberString = numeral Nenue@93: if decimal > 100 then Nenue@93: numberString = numberString .. '.' .. tostring(floor(decimal/100)) Nenue@93: end Nenue@93: numberString = numberString .. 'k' Nenue@93: end Nenue@93: Nenue@93: self.count:SetText(numberString) Nenue@93: self.count:SetTextColor(unpack(textColor)) Nenue@93: self.count:Show() Nenue@57: else Nenue@93: self.count:SetText(nil) Nenue@93: self.count:Hide() Nenue@93: end Nenue@93: else Nenue@93: self.count:Hide() Nenue@93: end Nenue@93: Nenue@93: if db.Config.ShowVerboseInfo then Nenue@93: self.Description:SetText(self.title .. "\n" .. floor(self.x*100+.5) .. "," .. floor(self.y*100+.5)) Nenue@93: end Nenue@93: Nenue@93: Nenue@93: icon:SetSize(currentWidth, currentWidth) Nenue@93: icon:SetMask(style.iconMask or DEFAULT_STYLE.iconMask) Nenue@93: if self.itemTexture then Nenue@93: --iconBorder:SetTexture(WORLD_QUEST_BORDER) Nenue@93: Nenue@93: if hideIcon then Nenue@93: icon:SetTexture(PENDING_ICON) Nenue@93: icon:SetDesaturated(true) Nenue@93: icon:SetVertexColor(unpack(borderColor)) Nenue@93: else Nenue@93: icon:SetTexture(self.itemTexture) Nenue@93: icon:SetDesaturated(false) Nenue@93: icon:SetVertexColor(1, 1, 1) Nenue@93: end Nenue@93: else Nenue@93: -- Nenue@93: --icon:SetTexture(PENDING_ICON) Nenue@93: --icon:SetDesaturated(true) Nenue@93: --icon:SetVertexColor(unpack(borderColor)) Nenue@93: end Nenue@93: local borderMask = style.borderMask or DEFAULT_STYLE.borderMask Nenue@93: local borderSize = currentWidth + (borderWidth * 2) + (self.isCriteria and 2 or 0) Nenue@93: Nenue@93: Nenue@93: iconBorder:SetSize(borderSize, borderSize) Nenue@93: Nenue@93: iconBorder:SetMask(borderMask) Nenue@93: iconBorder:SetTexture(PENDING_BORDER) Nenue@93: Nenue@93: iconBorder:SetDesaturated(true) Nenue@93: Nenue@93: local highlightSize = borderSize + (highlightWidth * 2) Nenue@93: trackingBorder:SetSize(highlightSize, highlightSize) Nenue@93: trackingBorder:SetMask(borderMask) Nenue@93: trackingBorder:SetTexture(PENDING_BORDER) Nenue@93: Nenue@93: self:SetSize(borderSize, borderSize) Nenue@93: self.IconBackdrop:SetSize(currentWidth, currentWidth) Nenue@93: Nenue@93: Nenue@93: Nenue@93: iconBorder:SetPoint('CENTER', (style.x or 0), (style.y or 0)) Nenue@93: trackingBorder:SetPoint('CENTER', (style.x or 0), (style.y or 0)) Nenue@93: Nenue@93: self.tagIcon:SetShown((not self.filtered) and true or false) Nenue@93: self.tagIcon:SetAtlas(self.tagAtlas) Nenue@93: self.EliteBorder:SetShown(self.isElite and not self.filtered) Nenue@93: Nenue@93: Nenue@93: if self.isBounty then Nenue@103: print('is bounty') Nenue@93: iconBorder:SetVertexColor(trackingBorder:GetVertexColor()) Nenue@93: trackingBorder:SetVertexColor(unpack(BORDER_SELECTED_BOUNTY)) Nenue@93: elseif self.isCriteria then Nenue@103: print('is criteria of a bounty') Nenue@93: iconBorder:SetVertexColor(trackingBorder:GetVertexColor()) Nenue@93: trackingBorder:SetVertexColor(unpack(BORDER_CRITERIA)) Nenue@93: else Nenue@103: print('is nothing') Nenue@93: iconBorder:SetVertexColor(unpack(borderColor)) Nenue@93: trackingBorder:SetVertexColor(0,0,0,.5) Nenue@93: end Nenue@103: self:UpdateStatus() Nenue@93: Nenue@93: if SpellCanTargetQuest() then Nenue@100: if self.isSpellTarget then Nenue@93: icon:SetVertexColor(1,1,1) Nenue@100: self:EnableMouse(false) Nenue@93: else Nenue@100: icon:SetVertexColor(0.5,0.5,0.5,1) Nenue@100: self:EnableMouse(true) Nenue@93: end Nenue@93: else Nenue@100: icon:SetVertexColor(1,1,1) Nenue@93: self:EnableMouse(true) Nenue@93: end Nenue@100: Nenue@93: self.isStale = nil Nenue@93: Nenue@93: -- signal filter info update Nenue@93: WorldPlanSummary.isStale = true Nenue@100: return true Nenue@93: end Nenue@93: Nenue@93: -- Called at static intervals and with Refresh Nenue@93: function QuestPOI:UpdateStatus() Nenue@93: -- update time elements Nenue@93: self.isActive = TQ_IsActive(self.questID) Nenue@95: --print(self.maxAlertLevel) Nenue@95: local border = (self.isBounty or self.isCriteria) and self.RewardBorder or self.HighlightBorder Nenue@93: Nenue@93: if self.isActive then Nenue@100: Nenue@93: local tl = self.alertLevel Nenue@93: local timeLeft = TQ_GetQuestTimeLeftMinutes(self.questID) Nenue@93: if timeLeft > 0 then Nenue@93: Nenue@95: local text, timeState, style = self:GetTimeInfo(timeLeft, self.maxAlertLevel) Nenue@93: if tl ~= timeState then Nenue@93: tl = timeState Nenue@93: self.timeLabel:SetText(text) Nenue@93: end Nenue@93: end Nenue@93: Nenue@93: self.alertLevel = tl Nenue@93: self.timeLabel:SetShown(self.worldQuest and (self.maxAlertLevel >= 1)) Nenue@93: else Nenue@93: self.hideReason = "No longer active." Nenue@93: self:HideOrShowFrames(false) Nenue@93: Nenue@93: end Nenue@93: end Nenue@93: Nenue@93: -- Show/Hide the text overlays associated with the quest pin; they aren't hierarchically linked Nenue@93: function QuestPOI:HideOrShowFrames(isShown) Nenue@93: if not isShown then Nenue@93: -- print('|cFFFFFF00' ..self:GetName()..':HideOrShowFrames()') Nenue@93: -- do not SetShown() here Nenue@93: if not self.hideReason then Nenue@95: self.hideReason = "HideOrShowFrames() called without a reason." Nenue@93: end Nenue@93: end Nenue@93: self.Overlay:SetShown(isShown) Nenue@93: self.count:SetShown(isShown) Nenue@93: self.timeLabel:SetShown(isShown) Nenue@93: end Nenue@93: Nenue@98: function QuestPOI:Release(msg) Nenue@103: print('|cFFFF4400Release('..self:GetID()..')', self.hideReason) Nenue@98: self.hideReason = msg or 'Released by script.' Nenue@103: self:ClearAllPoints() Nenue@98: self:SetShown(false) Nenue@95: self:HideOrShowFrames(false) Nenue@98: Nenue@93: if self.questID then Nenue@93: db.QuestsByID[self.questID] = nil Nenue@93: for _, map in pairs(db.QuestsByZone) do Nenue@93: map[self.questID] = nil Nenue@93: end Nenue@93: self.questID = nil Nenue@93: end Nenue@93: self.isActive = nil Nenue@93: self.complete = nil Nenue@93: self.used = nil Nenue@93: self.dataLoaded = nil Nenue@93: self.rewardType = nil Nenue@93: self.itemTexture = nil Nenue@93: self.itemName = nil Nenue@93: self.itemNumber = nil Nenue@93: self.animating = nil Nenue@93: self.icon:SetAlpha(0) Nenue@93: self.RewardBorder:SetAlpha(0) Nenue@93: self:UnregisterEvent('QUEST_TURNED_IN') Nenue@93: self:UnregisterEvent('QUEST_LOG_UPDATE') Nenue@93: Nenue@100: self.checkCursor = true Nenue@100: self.checkFilters = true Nenue@100: self.checkCriteria = true Nenue@100: Nenue@93: for i, pin in ipairs(db.UsedPins) do Nenue@93: if pin == self then Nenue@95: print('|cFFFF4400cleared from UsedPins|r') Nenue@93: tremove(db.UsedPins, i) Nenue@93: break Nenue@57: end Nenue@47: end Nenue@47: Nenue@93: tinsert(db.FreePins, self) Nenue@93: WorldPlan.dataFlush = true Nenue@95: WorldPlanSummary.isStale = true Nenue@95: Nenue@95: return true Nenue@7: end