Nenue@0: local B = select(2,...).frame Nenue@23: local wipe, pairs, ipairs, min, max, unpack = table.wipe, pairs, ipairs, min, max, unpack Nenue@23: local tinsert, tostring, format, mod = tinsert, tostring, format, mod Nenue@18: local GetQuestTagInfo, GetQuestLogTitle = GetQuestTagInfo, GetQuestLogTitle Nenue@18: local GetNumQuestLogEntries, GetNumQuestWatches, GetQuestLogCompletionText, IsQuestWatched, IsQuestHardWatched, GetQuestLogSpecialItemInfo, GetQuestLogSpecialItemCooldown = GetNumQuestLogEntries, GetNumQuestWatches, GetQuestLogCompletionText, IsQuestWatched, IsQuestHardWatched, GetQuestLogSpecialItemInfo, GetQuestLogSpecialItemCooldown Nenue@18: local GetNumAutoQuestPopUps, GetAutoQuestPopUp, GetTasksTable, GetNumQuestLogTasks, GetTaskInfo, GetQuestObjectiveInfo = GetNumAutoQuestPopUps, GetAutoQuestPopUp, GetTasksTable, GetNumQuestLogTasks, GetTaskInfo, GetQuestObjectiveInfo Nenue@18: local GetNumQuestLogRewardCurrencies, GetQuestLogRewardCurrencyInfo, GetNumQuestLogRewards, GetQuestLogRewardInfo, GetQuestLogRewardMoney, GetMoneyString = GetNumQuestLogRewardCurrencies, GetQuestLogRewardCurrencyInfo, GetNumQuestLogRewards, GetQuestLogRewardInfo, GetQuestLogRewardMoney, GetMoneyString Nenue@0: local GetNumQuestLeaderBoards, GetAchievementNumCriteria, GetQuestLogLeaderBoard, GetAchievementCriteriaInfo = GetNumQuestLeaderBoards, GetAchievementNumCriteria, GetQuestLogLeaderBoard, GetAchievementCriteriaInfo Nenue@16: local GetQuestWatchIndex, GetQuestLogIndexByID, GetSuperTrackedQuestID, SetSuperTrackedQuestID, GetQuestWatchInfo = GetQuestWatchIndex, GetQuestLogIndexByID, GetSuperTrackedQuestID, SetSuperTrackedQuestID, GetQuestWatchInfo Nenue@18: local QuestHasPOIInfo, GetDistanceSqToQuest, GetQuestFactionGroup = QuestHasPOIInfo, GetDistanceSqToQuest, GetQuestFactionGroup Nenue@18: local GetTrackedAchievements, GetNumTrackedAchievements, GetAchievementInfo = GetTrackedAchievements, GetNumTrackedAchievements, GetAchievementInfo Nenue@22: local GetMoney, floor = GetMoney, floor Nenue@22: local T = B:RegisterModule("ObjectiveTracker", _G.VeneerObjectiveWrapper, 'BuffFrame') Nenue@22: local print = B.print('Info') Nenue@18: local QUEST_TAG_DUNGEON = QUEST_TAG_DUNGEON Nenue@18: local QUEST_TAG_GROUP = QUEST_TAG_GROUP Nenue@18: local QUEST_TAG_ACCOUNT = QUEST_TAG_ACCOUNT Nenue@18: local QUEST_TAG_TCOORDS = QUEST_TAG_TCOORDS Nenue@18: local LE_QUEST_FREQUENCY_DAILY = LE_QUEST_FREQUENCY_DAILY Nenue@18: local LE_QUEST_FREQUENCY_WEEKLY = LE_QUEST_FREQUENCY_WEEKLY Nenue@18: local FACTION_ALLIANCE, LE_QUEST_FACTION_HORDE, FACTION_HORDE, LE_QUEST_FACTION_HORDE = FACTION_ALLIANCE, LE_QUEST_FACTION_HORDE, FACTION_HORDE, LE_QUEST_FACTION_HORDE Nenue@0: Nenue@22: local Tracker, Bonus, AutoQuest, Quest, Cheevs = T.DefaultTracker, T.Bonus, T.AutoQuest, T.Quest, T.Cheevs Nenue@0: -------------------------------------------------------------------- Nenue@0: --- Tracker-specific data retrieval functions Nenue@0: -------------------------------------------------------------------- Nenue@13: Nenue@13: Nenue@22: local DoQuestRewards= function(t, questID) Nenue@22: local rewards = {} Nenue@22: t.numCurrencies = GetNumQuestLogRewardCurrencies(questID) Nenue@22: for i = 1, t.numCurrencies do Nenue@22: local name, texture, count = GetQuestLogRewardCurrencyInfo(i, questID) Nenue@22: tinsert(rewards,{ Nenue@22: type = 'currency', Nenue@22: index = i, Nenue@22: name = name, Nenue@22: texture = texture, Nenue@22: count = count Nenue@22: }); Nenue@22: end Nenue@22: -- items Nenue@22: t.numItems = GetNumQuestLogRewards(questID) Nenue@22: for i = 1, t.numItems do Nenue@22: local name, texture, count, quality, isUsable = GetQuestLogRewardInfo(i, questID) Nenue@22: tinsert(rewards, { Nenue@22: type = 'item', Nenue@22: index = i , Nenue@22: name = name, Nenue@22: texture = texture, Nenue@22: count = count, Nenue@22: quality = quality, Nenue@22: isUsable = isUsable Nenue@22: }); Nenue@22: end Nenue@22: -- money Nenue@22: Nenue@22: local money = GetQuestLogRewardMoney(questID) Nenue@22: if ( money > 0 ) then Nenue@22: tinsert(rewards, { Nenue@22: type = 'money', Nenue@22: name = GetMoneyString(money), Nenue@22: texture = "Interface\\Icons\\inv_misc_coin_01", Nenue@22: count = 0, Nenue@22: }); Nenue@22: end Nenue@22: Nenue@22: if #rewards >= 1 then Nenue@22: t.rewardInfo = rewards Nenue@22: end Nenue@22: end Nenue@22: Nenue@22: Nenue@13: ----------------------------- Nenue@13: --- AUTO_QUEST Nenue@16: AutoQuest.LogInfo = {} Nenue@16: AutoQuest.LogBlock = {} Nenue@16: AutoQuest.QuestBlock = {} Nenue@16: AutoQuest.WatchBlock = {} Nenue@19: function AutoQuest:GetNumWatched () Nenue@19: print(self.name, self) Nenue@21: Quest:GetNumWatched() Nenue@19: self.numWatched = GetNumAutoQuestPopUps() Nenue@21: Nenue@19: return self.numWatched Nenue@16: end Nenue@16: AutoQuest.GetInfo = function(self, popupIndex) Nenue@16: Nenue@22: Nenue@16: local questID, type = GetAutoQuestPopUp(popupIndex) Nenue@23: local questLogIndex = GetQuestLogIndexByID(questID) Nenue@21: local title, level, suggestedGroup, isHeader, isCollapsed, isComplete, frequency, questID, startEvent, displayQuestID, isOnMap, hasLocalPOI, isTask, isStory = GetQuestLogTitle(questIndex) Nenue@16: Nenue@22: self.Info[questID] = self.Info[questID] or {} Nenue@22: local popup = self.Info[questID] Nenue@22: popup.title = title Nenue@22: popup.description = type Nenue@22: popup.popupType = type Nenue@22: popup.questID = questID Nenue@23: popup.questLogIndex = questLogIndex Nenue@22: popup.popupIndex = popupIndex Nenue@22: Nenue@22: self.Info[questID] = popup Nenue@22: self.WatchInfo[popupIndex] = popup Nenue@16: Nenue@16: Nenue@16: return self.Info[questID] Nenue@13: end Nenue@13: Nenue@13: ----------------------------- Nenue@14: --- BONUS OBJECTIVE Nenue@21: -- The default UI pops them up as you enter their relevant areas, but the data is actually available at all times. Nenue@21: -- The only requirement is that you've been to said area and progressed any of the objectives. Nenue@21: -- Blizzard deal with this fact by caching any task data collected during session and masking out whatever gets completed. Nenue@21: -- For the addon's module structure to work, GetNumWatched method also invokes a tasks table scan. Nenue@21: -- That composes the table searched by GetInfo(). Nenue@14: Nenue@21: ------------------------------------------------------------------------------------------ Nenue@21: --- These functions are copied from Blizzard_BonusObjectiveTracker.lua; Nenue@21: -- It's kind of dumb, but this avoids the risk of code taint. Nenue@21: Nenue@21: --- Returns a tasks table modified to include recently completed objectives Nenue@22: local UnitName, GetRealmName = UnitName, GetRealmName Nenue@21: local InternalGetTasksTable = function() Nenue@23: local savedTasks = T.Conf.TasksLog Nenue@22: local char = UnitName("player") Nenue@22: local realm = GetRealmName() Nenue@21: local tasks = GetTasksTable() Nenue@22: Nenue@22: for questID, data in pairs(Bonus.Info) do Nenue@22: Nenue@22: print(' -- questID:', questID, #data.objectives) Nenue@22: for i, o in ipairs(data.objectives) do Nenue@22: print(' --', i, o.text) Nenue@22: end Nenue@22: Nenue@22: end Nenue@22: Nenue@22: Nenue@23: for questID, data in pairs(savedTasks) do Nenue@21: if questID > 0 then Nenue@21: local found = false Nenue@21: for i = 1, #tasks do Nenue@21: if tasks[i] == questID then Nenue@21: found = true Nenue@21: break Nenue@21: end Nenue@21: end Nenue@21: -- if it's not part of the current table, then try to insert it where it was last found Nenue@21: if not found then Nenue@21: if data.watchIndex < #tasks then Nenue@21: tinsert(tasks, data.watchIndex, data) Nenue@21: else Nenue@21: tinsert(tasks, data) Nenue@21: end Nenue@21: end Nenue@21: end Nenue@21: end Nenue@21: return tasks Nenue@21: end Nenue@21: Nenue@21: --- Returns an entry from the composed tasks table if possible, otherwise makes an API pull Nenue@21: local InternalGetTaskInfo = function(questID) Nenue@22: local completedTasks = T.Conf.TasksLog Nenue@21: if completedTasks[questID] then Nenue@21: return true, true, #completedTasks[questID].objectives Nenue@21: else Nenue@21: return GetTaskInfo(questID) Nenue@21: end Nenue@21: end Nenue@21: Nenue@21: --- Same as above but for the objective entries Nenue@21: local InternalGetQuestObjectiveInfo = function(questID, objectiveIndex) Nenue@22: local completedTasks = T.Conf.TasksLog Nenue@21: if ( completedTasks[questID] ) then Nenue@22: print('using internal data') Nenue@21: return completedTasks[questID].objectives[objectiveIndex], completedTasks[questID].objectiveType, true; Nenue@21: else Nenue@21: return GetQuestObjectiveInfo(questID, objectiveIndex, false); Nenue@21: end Nenue@21: end Nenue@21: Nenue@21: --- end redundant copy of silliness Nenue@21: ------------------------------------------------------------------------------------------ Nenue@21: Nenue@21: Bonus.Completed = {} Nenue@21: Bonus.POI = {} Nenue@21: Bonus.Scenario = {} Nenue@14: Bonus.QuestBlock = {} Nenue@22: Bonus.WatchInfo = {} Nenue@19: function Bonus:GetNumWatched () Nenue@19: print(self.name, self) Nenue@22: Nenue@21: local tasks = InternalGetTasksTable() Nenue@21: local numWatched = 0 Nenue@21: local numAll = 0 Nenue@21: self.WatchInfo = {} Nenue@16: print('|cFFFFFF00Bonus.GetNumWatched()|r', #tasks) Nenue@22: print(' TasksTable pull:') Nenue@16: for i, questID in ipairs(tasks) do Nenue@21: local isInArea, isOnMap, numObjectives = InternalGetTaskInfo(questID) Nenue@21: local existingTask = self.QuestBlock[questID] Nenue@21: local displayObjectiveHeader = false; Nenue@22: local test = (isInArea or (isOnMap and existingTask)) Nenue@22: --local test = true Nenue@22: if test then Nenue@21: self.Info[questID] = self.Info[questID] or {} Nenue@21: Nenue@21: local t = self.Info[questID] Nenue@21: self.WatchInfo[i] = t Nenue@21: t.isInArea = isInArea Nenue@21: t.isOnMap = isOnMap Nenue@21: t.existingTask = existingTask Nenue@21: t.questID = questID Nenue@21: t.objectives = {} Nenue@21: t.taskIndex = i Nenue@21: Nenue@22: Nenue@22: DoQuestRewards(t, questID) Nenue@22: Nenue@22: local taskTitle Nenue@21: local taskFinished = true; Nenue@21: for objectiveIndex = 1, numObjectives do Nenue@21: local text, objectiveType, finished, displayAsObjective = InternalGetQuestObjectiveInfo(questID, objectiveIndex, false); Nenue@21: displayObjectiveHeader = displayObjectiveHeader or displayAsObjective; Nenue@22: if not taskTitle then Nenue@22: if objectiveType == 'progressbar' and not text:match('^%d%+\\%d+') then Nenue@22: taskTitle = text Nenue@22: text = '' Nenue@22: end Nenue@22: end Nenue@22: Nenue@22: Nenue@21: print(' --', text, objectiveType, finished, displayAsObjective) Nenue@21: t.objectives[objectiveIndex] = t.objectives[objectiveIndex] or {} Nenue@21: local o = t.objectives[objectiveIndex] Nenue@21: Nenue@21: o.objectiveIndex = objectiveIndex Nenue@21: o.text = text Nenue@21: o.objectiveType = objectiveType Nenue@21: o.finished = finished Nenue@21: o.displayAsObjective = displayAsObjective Nenue@21: print(' |cFF00FF88*', objectiveIndex, text) Nenue@21: end Nenue@22: Nenue@22: -- didn't get a name from progress bar? what about area name Nenue@22: if not taskTitle then Nenue@22: if isInArea then Nenue@22: taskTitle = GetMapNameByID(GetCurrentMapAreaID()) Nenue@22: end Nenue@22: end Nenue@22: t.title = taskTitle Nenue@14: end Nenue@22: Nenue@22: print (' |cFF00FF88#', i, 'questID', questID, 'inArea', isInArea, 'onMap', isOnMap, 'existing', (existingTask and 'Y' or 'N'), (test and '|cFF00FF00show|r' or '|cFFFF0088hide|r')) Nenue@14: end Nenue@21: Nenue@21: Nenue@21: self.numAll = #tasks Nenue@21: self.numWatched = #self.WatchInfo Nenue@22: print(' stats:', self.numAll, 'active tasks,', self.numWatched, 'nearby or animating') Nenue@21: --return #tasks Nenue@22: return #self.WatchInfo Nenue@22: end Nenue@22: Nenue@22: --- info cleanup done when turn-ins are detected Nenue@22: Bonus.OnTurnIn = function(self, questID, xp, money) Nenue@22: print('|cFFFF8800'..self.name..':OnTurnIn call', questID, xp, money) Nenue@23: local savedTasks = B.Conf.TasksLog Nenue@22: Nenue@23: self.Info[questID].completedTime = GetTime() Nenue@23: self.Info[questID].animate = true Nenue@23: T.SetAnimate(self.watchReason) Nenue@23: savedTasks[questID] = self.Info[questID] Nenue@14: end Nenue@16: Nenue@16: Bonus.GetInfo = function(self, taskIndex) Nenue@19: print(self.name, self) Nenue@21: return self.WatchInfo[taskIndex] Nenue@16: end Nenue@16: Nenue@1: Nenue@6: Nenue@0: Cheevs.GetNumWatched = function(self) Nenue@21: print('|cFF00FF00' .. GetTime()) Nenue@0: Cheevs.trackedCheevs = {GetTrackedAchievements()} Nenue@0: return GetNumTrackedAchievements() Nenue@0: end Nenue@0: Cheevs.GetInfo = function(self, index) Nenue@0: local cheevID = Cheevs.trackedCheevs[index] Nenue@0: local id, name, points, completed, month, day, year, description, flags, icon, rewardText, isGuildAch, wasEarnedByMe, earnedBy = GetAchievementInfo(cheevID) Nenue@0: Nenue@0: self.Info[cheevID] = {} Nenue@0: local c = self.Info[cheevID] Nenue@0: c.type = 'Cheevs' Nenue@0: c.watchIndex = index Nenue@0: c.cheevID = cheevID Nenue@0: c.title = name Nenue@0: c.points, c.completed, c.month, c.day, c.year, c.description, c.flags, c.icon, c.rewardText, c.isGuildAch, c.wasEarnedByMe, c.earnedBy = Nenue@0: points, completed, month, day, year, description, flags, icon, rewardText, isGuildAch, wasEarnedByMe, earnedBy Nenue@0: c.numObjectives = GetAchievementNumCriteria(cheevID) Nenue@0: c.objectives = {} Nenue@0: for i = 1, c.numObjectives do Nenue@0: local description, type, completed, quantity, requiredQuantity, characterName, flags, assetID, quantityString, criteriaID = GetAchievementCriteriaInfo(cheevID, i) Nenue@0: c.objectives[i] = { Nenue@21: objectiveIndex = i, Nenue@8: cheevID = cheevID, Nenue@0: text = description, Nenue@0: type = type, Nenue@0: finished = completed, Nenue@14: value = quantity, Nenue@14: maxValue = requiredQuantity, Nenue@0: characterName = characterName, Nenue@0: flags = flags, Nenue@0: assetID = assetID, Nenue@0: quantityString = quantityString, Nenue@0: criteriaID = criteriaID, Nenue@0: } Nenue@0: end Nenue@3: print('Cheevs.|cFF0088FFGetInfo|r('..index..')', 'obj:', GetAchievementNumCriteria(cheevID), name, description) Nenue@0: Nenue@0: self.WatchInfo[index] = c Nenue@0: return self.Info[cheevID] Nenue@0: end