annotate ObjectiveTracker/ObjectiveInfo.lua @ 37:e84d645c8ab8

- revised the tracker update function to build its complete data list up front and use the values as points of comparison for determining possible out of place blocks, which will be iterated over afterward to remove what wasn't re-used - also entailed revising the exact role of global event handlers and function hooks, limiting their directions of communication so one doesn't end up calling the other multiple or inifinity times - schema handling polish
author Nenue
date Mon, 18 Apr 2016 07:56:23 -0400
parents 4b3da1b221de
children
rev   line source
Nenue@0 1 local B = select(2,...).frame
Nenue@23 2 local wipe, pairs, ipairs, min, max, unpack = table.wipe, pairs, ipairs, min, max, unpack
Nenue@23 3 local tinsert, tostring, format, mod = tinsert, tostring, format, mod
Nenue@18 4 local GetQuestTagInfo, GetQuestLogTitle = GetQuestTagInfo, GetQuestLogTitle
Nenue@18 5 local GetNumQuestLogEntries, GetNumQuestWatches, GetQuestLogCompletionText, IsQuestWatched, IsQuestHardWatched, GetQuestLogSpecialItemInfo, GetQuestLogSpecialItemCooldown = GetNumQuestLogEntries, GetNumQuestWatches, GetQuestLogCompletionText, IsQuestWatched, IsQuestHardWatched, GetQuestLogSpecialItemInfo, GetQuestLogSpecialItemCooldown
Nenue@18 6 local GetNumAutoQuestPopUps, GetAutoQuestPopUp, GetTasksTable, GetNumQuestLogTasks, GetTaskInfo, GetQuestObjectiveInfo = GetNumAutoQuestPopUps, GetAutoQuestPopUp, GetTasksTable, GetNumQuestLogTasks, GetTaskInfo, GetQuestObjectiveInfo
Nenue@18 7 local GetNumQuestLogRewardCurrencies, GetQuestLogRewardCurrencyInfo, GetNumQuestLogRewards, GetQuestLogRewardInfo, GetQuestLogRewardMoney, GetMoneyString = GetNumQuestLogRewardCurrencies, GetQuestLogRewardCurrencyInfo, GetNumQuestLogRewards, GetQuestLogRewardInfo, GetQuestLogRewardMoney, GetMoneyString
Nenue@0 8 local GetNumQuestLeaderBoards, GetAchievementNumCriteria, GetQuestLogLeaderBoard, GetAchievementCriteriaInfo = GetNumQuestLeaderBoards, GetAchievementNumCriteria, GetQuestLogLeaderBoard, GetAchievementCriteriaInfo
Nenue@16 9 local GetQuestWatchIndex, GetQuestLogIndexByID, GetSuperTrackedQuestID, SetSuperTrackedQuestID, GetQuestWatchInfo = GetQuestWatchIndex, GetQuestLogIndexByID, GetSuperTrackedQuestID, SetSuperTrackedQuestID, GetQuestWatchInfo
Nenue@18 10 local QuestHasPOIInfo, GetDistanceSqToQuest, GetQuestFactionGroup = QuestHasPOIInfo, GetDistanceSqToQuest, GetQuestFactionGroup
Nenue@18 11 local GetTrackedAchievements, GetNumTrackedAchievements, GetAchievementInfo = GetTrackedAchievements, GetNumTrackedAchievements, GetAchievementInfo
Nenue@22 12 local GetMoney, floor = GetMoney, floor
Nenue@22 13 local T = B:RegisterModule("ObjectiveTracker", _G.VeneerObjectiveWrapper, 'BuffFrame')
Nenue@22 14 local print = B.print('Info')
Nenue@18 15 local QUEST_TAG_DUNGEON = QUEST_TAG_DUNGEON
Nenue@18 16 local QUEST_TAG_GROUP = QUEST_TAG_GROUP
Nenue@18 17 local QUEST_TAG_ACCOUNT = QUEST_TAG_ACCOUNT
Nenue@18 18 local QUEST_TAG_TCOORDS = QUEST_TAG_TCOORDS
Nenue@18 19 local LE_QUEST_FREQUENCY_DAILY = LE_QUEST_FREQUENCY_DAILY
Nenue@18 20 local LE_QUEST_FREQUENCY_WEEKLY = LE_QUEST_FREQUENCY_WEEKLY
Nenue@18 21 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 22
Nenue@22 23 local Tracker, Bonus, AutoQuest, Quest, Cheevs = T.DefaultTracker, T.Bonus, T.AutoQuest, T.Quest, T.Cheevs
Nenue@0 24 --------------------------------------------------------------------
Nenue@0 25 --- Tracker-specific data retrieval functions
Nenue@0 26 --------------------------------------------------------------------
Nenue@13 27
Nenue@13 28
Nenue@22 29 local DoQuestRewards= function(t, questID)
Nenue@22 30 local rewards = {}
Nenue@22 31 t.numCurrencies = GetNumQuestLogRewardCurrencies(questID)
Nenue@22 32 for i = 1, t.numCurrencies do
Nenue@22 33 local name, texture, count = GetQuestLogRewardCurrencyInfo(i, questID)
Nenue@22 34 tinsert(rewards,{
Nenue@22 35 type = 'currency',
Nenue@22 36 index = i,
Nenue@22 37 name = name,
Nenue@22 38 texture = texture,
Nenue@22 39 count = count
Nenue@22 40 });
Nenue@22 41 end
Nenue@22 42 -- items
Nenue@22 43 t.numItems = GetNumQuestLogRewards(questID)
Nenue@22 44 for i = 1, t.numItems do
Nenue@22 45 local name, texture, count, quality, isUsable = GetQuestLogRewardInfo(i, questID)
Nenue@22 46 tinsert(rewards, {
Nenue@22 47 type = 'item',
Nenue@22 48 index = i ,
Nenue@22 49 name = name,
Nenue@22 50 texture = texture,
Nenue@22 51 count = count,
Nenue@22 52 quality = quality,
Nenue@22 53 isUsable = isUsable
Nenue@22 54 });
Nenue@22 55 end
Nenue@22 56 -- money
Nenue@22 57
Nenue@22 58 local money = GetQuestLogRewardMoney(questID)
Nenue@22 59 if ( money > 0 ) then
Nenue@22 60 tinsert(rewards, {
Nenue@22 61 type = 'money',
Nenue@22 62 name = GetMoneyString(money),
Nenue@22 63 texture = "Interface\\Icons\\inv_misc_coin_01",
Nenue@22 64 count = 0,
Nenue@22 65 });
Nenue@22 66 end
Nenue@22 67
Nenue@22 68 if #rewards >= 1 then
Nenue@22 69 t.rewardInfo = rewards
Nenue@22 70 end
Nenue@22 71 end
Nenue@22 72
Nenue@22 73
Nenue@13 74 -----------------------------
Nenue@13 75 --- AUTO_QUEST
Nenue@16 76 AutoQuest.LogInfo = {}
Nenue@16 77 AutoQuest.LogBlock = {}
Nenue@16 78 AutoQuest.QuestBlock = {}
Nenue@16 79 AutoQuest.WatchBlock = {}
Nenue@19 80 function AutoQuest:GetNumWatched ()
Nenue@19 81 print(self.name, self)
Nenue@21 82 Quest:GetNumWatched()
Nenue@19 83 self.numWatched = GetNumAutoQuestPopUps()
Nenue@21 84
Nenue@19 85 return self.numWatched
Nenue@16 86 end
Nenue@16 87 AutoQuest.GetInfo = function(self, popupIndex)
Nenue@16 88
Nenue@22 89
Nenue@16 90 local questID, type = GetAutoQuestPopUp(popupIndex)
Nenue@23 91 local questLogIndex = GetQuestLogIndexByID(questID)
Nenue@25 92 local title, level, suggestedGroup, isHeader, isCollapsed, isComplete, frequency, questID, startEvent, displayQuestID, isOnMap, hasLocalPOI, isTask, isStory = GetQuestLogTitle(questLogIndex)
Nenue@16 93
Nenue@22 94 self.Info[questID] = self.Info[questID] or {}
Nenue@22 95 local popup = self.Info[questID]
Nenue@22 96 popup.title = title
Nenue@22 97 popup.description = type
Nenue@22 98 popup.popupType = type
Nenue@22 99 popup.questID = questID
Nenue@23 100 popup.questLogIndex = questLogIndex
Nenue@22 101 popup.popupIndex = popupIndex
Nenue@22 102
Nenue@22 103 self.Info[questID] = popup
Nenue@22 104 self.WatchInfo[popupIndex] = popup
Nenue@16 105
Nenue@16 106
Nenue@16 107 return self.Info[questID]
Nenue@13 108 end
Nenue@13 109
Nenue@13 110 -----------------------------
Nenue@14 111 --- BONUS OBJECTIVE
Nenue@21 112 -- The default UI pops them up as you enter their relevant areas, but the data is actually available at all times.
Nenue@21 113 -- The only requirement is that you've been to said area and progressed any of the objectives.
Nenue@21 114 -- Blizzard deal with this fact by caching any task data collected during session and masking out whatever gets completed.
Nenue@21 115 -- For the addon's module structure to work, GetNumWatched method also invokes a tasks table scan.
Nenue@21 116 -- That composes the table searched by GetInfo().
Nenue@14 117
Nenue@21 118 ------------------------------------------------------------------------------------------
Nenue@21 119 --- These functions are copied from Blizzard_BonusObjectiveTracker.lua;
Nenue@21 120 -- It's kind of dumb, but this avoids the risk of code taint.
Nenue@21 121
Nenue@21 122 --- Returns a tasks table modified to include recently completed objectives
Nenue@22 123 local UnitName, GetRealmName = UnitName, GetRealmName
Nenue@21 124 local InternalGetTasksTable = function()
Nenue@23 125 local savedTasks = T.Conf.TasksLog
Nenue@22 126 local char = UnitName("player")
Nenue@22 127 local realm = GetRealmName()
Nenue@21 128 local tasks = GetTasksTable()
Nenue@22 129
Nenue@22 130 for questID, data in pairs(Bonus.Info) do
Nenue@22 131
Nenue@22 132 print(' -- questID:', questID, #data.objectives)
Nenue@22 133 for i, o in ipairs(data.objectives) do
Nenue@22 134 print(' --', i, o.text)
Nenue@22 135 end
Nenue@22 136
Nenue@22 137 end
Nenue@22 138
Nenue@22 139
Nenue@23 140 for questID, data in pairs(savedTasks) do
Nenue@21 141 if questID > 0 then
Nenue@21 142 local found = false
Nenue@21 143 for i = 1, #tasks do
Nenue@21 144 if tasks[i] == questID then
Nenue@21 145 found = true
Nenue@21 146 break
Nenue@21 147 end
Nenue@21 148 end
Nenue@21 149 -- if it's not part of the current table, then try to insert it where it was last found
Nenue@21 150 if not found then
Nenue@21 151 if data.watchIndex < #tasks then
Nenue@21 152 tinsert(tasks, data.watchIndex, data)
Nenue@21 153 else
Nenue@21 154 tinsert(tasks, data)
Nenue@21 155 end
Nenue@21 156 end
Nenue@21 157 end
Nenue@21 158 end
Nenue@21 159 return tasks
Nenue@21 160 end
Nenue@21 161
Nenue@21 162 --- Returns an entry from the composed tasks table if possible, otherwise makes an API pull
Nenue@21 163 local InternalGetTaskInfo = function(questID)
Nenue@22 164 local completedTasks = T.Conf.TasksLog
Nenue@21 165 if completedTasks[questID] then
Nenue@21 166 return true, true, #completedTasks[questID].objectives
Nenue@21 167 else
Nenue@21 168 return GetTaskInfo(questID)
Nenue@21 169 end
Nenue@21 170 end
Nenue@21 171
Nenue@21 172 --- Same as above but for the objective entries
Nenue@21 173 local InternalGetQuestObjectiveInfo = function(questID, objectiveIndex)
Nenue@22 174 local completedTasks = T.Conf.TasksLog
Nenue@21 175 if ( completedTasks[questID] ) then
Nenue@22 176 print('using internal data')
Nenue@21 177 return completedTasks[questID].objectives[objectiveIndex], completedTasks[questID].objectiveType, true;
Nenue@21 178 else
Nenue@21 179 return GetQuestObjectiveInfo(questID, objectiveIndex, false);
Nenue@21 180 end
Nenue@21 181 end
Nenue@21 182
Nenue@21 183 --- end redundant copy of silliness
Nenue@21 184 ------------------------------------------------------------------------------------------
Nenue@21 185
Nenue@21 186 Bonus.Completed = {}
Nenue@21 187 Bonus.POI = {}
Nenue@21 188 Bonus.Scenario = {}
Nenue@14 189 Bonus.QuestBlock = {}
Nenue@22 190 Bonus.WatchInfo = {}
Nenue@19 191 function Bonus:GetNumWatched ()
Nenue@19 192 print(self.name, self)
Nenue@22 193
Nenue@21 194 local tasks = InternalGetTasksTable()
Nenue@21 195 local numWatched = 0
Nenue@21 196 local numAll = 0
Nenue@21 197 self.WatchInfo = {}
Nenue@16 198 print('|cFFFFFF00Bonus.GetNumWatched()|r', #tasks)
Nenue@22 199 print(' TasksTable pull:')
Nenue@16 200 for i, questID in ipairs(tasks) do
Nenue@21 201 local isInArea, isOnMap, numObjectives = InternalGetTaskInfo(questID)
Nenue@21 202 local existingTask = self.QuestBlock[questID]
Nenue@21 203 local displayObjectiveHeader = false;
Nenue@22 204 local test = (isInArea or (isOnMap and existingTask))
Nenue@22 205 --local test = true
Nenue@22 206 if test then
Nenue@21 207 self.Info[questID] = self.Info[questID] or {}
Nenue@21 208
Nenue@21 209 local t = self.Info[questID]
Nenue@21 210 self.WatchInfo[i] = t
Nenue@21 211 t.isInArea = isInArea
Nenue@21 212 t.isOnMap = isOnMap
Nenue@21 213 t.existingTask = existingTask
Nenue@21 214 t.questID = questID
Nenue@21 215 t.objectives = {}
Nenue@21 216 t.taskIndex = i
Nenue@21 217
Nenue@22 218
Nenue@22 219 DoQuestRewards(t, questID)
Nenue@22 220
Nenue@22 221 local taskTitle
Nenue@21 222 local taskFinished = true;
Nenue@21 223 for objectiveIndex = 1, numObjectives do
Nenue@21 224 local text, objectiveType, finished, displayAsObjective = InternalGetQuestObjectiveInfo(questID, objectiveIndex, false);
Nenue@21 225 displayObjectiveHeader = displayObjectiveHeader or displayAsObjective;
Nenue@22 226 if not taskTitle then
Nenue@22 227 if objectiveType == 'progressbar' and not text:match('^%d%+\\%d+') then
Nenue@22 228 taskTitle = text
Nenue@22 229 text = ''
Nenue@22 230 end
Nenue@22 231 end
Nenue@22 232
Nenue@22 233
Nenue@21 234 print(' --', text, objectiveType, finished, displayAsObjective)
Nenue@21 235 t.objectives[objectiveIndex] = t.objectives[objectiveIndex] or {}
Nenue@21 236 local o = t.objectives[objectiveIndex]
Nenue@21 237
Nenue@21 238 o.objectiveIndex = objectiveIndex
Nenue@21 239 o.text = text
Nenue@21 240 o.objectiveType = objectiveType
Nenue@21 241 o.finished = finished
Nenue@21 242 o.displayAsObjective = displayAsObjective
Nenue@21 243 print(' |cFF00FF88*', objectiveIndex, text)
Nenue@21 244 end
Nenue@22 245
Nenue@22 246 -- didn't get a name from progress bar? what about area name
Nenue@22 247 if not taskTitle then
Nenue@22 248 if isInArea then
Nenue@22 249 taskTitle = GetMapNameByID(GetCurrentMapAreaID())
Nenue@22 250 end
Nenue@22 251 end
Nenue@22 252 t.title = taskTitle
Nenue@14 253 end
Nenue@22 254
Nenue@22 255 print (' |cFF00FF88#', i, 'questID', questID, 'inArea', isInArea, 'onMap', isOnMap, 'existing', (existingTask and 'Y' or 'N'), (test and '|cFF00FF00show|r' or '|cFFFF0088hide|r'))
Nenue@14 256 end
Nenue@21 257
Nenue@21 258
Nenue@21 259 self.numAll = #tasks
Nenue@21 260 self.numWatched = #self.WatchInfo
Nenue@22 261 print(' stats:', self.numAll, 'active tasks,', self.numWatched, 'nearby or animating')
Nenue@21 262 --return #tasks
Nenue@22 263 return #self.WatchInfo
Nenue@22 264 end
Nenue@22 265
Nenue@22 266 --- info cleanup done when turn-ins are detected
Nenue@22 267 Bonus.OnTurnIn = function(self, questID, xp, money)
Nenue@25 268
Nenue@25 269 if #self.info.rewardInfo >= 1 then
Nenue@25 270 for i, reward in ipairs(self.info.rewardInfo) do
Nenue@25 271 --[[
Nenue@25 272 type = 'item',
Nenue@25 273 index = i ,
Nenue@25 274 name = name,
Nenue@25 275 texture = texture,
Nenue@25 276 count = count,
Nenue@25 277 quality = quality,
Nenue@25 278 isUsable = isUsable
Nenue@25 279 ]]
Nenue@25 280 print(' reward ', i, ' ', reward.type, reward.name, reward.count)
Nenue@25 281
Nenue@25 282 end
Nenue@25 283 end
Nenue@25 284
Nenue@22 285 print('|cFFFF8800'..self.name..':OnTurnIn call', questID, xp, money)
Nenue@23 286 local savedTasks = B.Conf.TasksLog
Nenue@22 287
Nenue@23 288 self.Info[questID].completedTime = GetTime()
Nenue@23 289 self.Info[questID].animate = true
Nenue@25 290 T.SetAnimate(self.watchReasonModule)
Nenue@23 291 savedTasks[questID] = self.Info[questID]
Nenue@14 292 end
Nenue@16 293
Nenue@16 294 Bonus.GetInfo = function(self, taskIndex)
Nenue@19 295 print(self.name, self)
Nenue@21 296 return self.WatchInfo[taskIndex]
Nenue@16 297 end
Nenue@16 298
Nenue@1 299
Nenue@6 300
Nenue@0 301 Cheevs.GetNumWatched = function(self)
Nenue@21 302 print('|cFF00FF00' .. GetTime())
Nenue@0 303 Cheevs.trackedCheevs = {GetTrackedAchievements()}
Nenue@0 304 return GetNumTrackedAchievements()
Nenue@0 305 end
Nenue@0 306 Cheevs.GetInfo = function(self, index)
Nenue@0 307 local cheevID = Cheevs.trackedCheevs[index]
Nenue@0 308 local id, name, points, completed, month, day, year, description, flags, icon, rewardText, isGuildAch, wasEarnedByMe, earnedBy = GetAchievementInfo(cheevID)
Nenue@0 309
Nenue@0 310 self.Info[cheevID] = {}
Nenue@0 311 local c = self.Info[cheevID]
Nenue@0 312 c.type = 'Cheevs'
Nenue@0 313 c.watchIndex = index
Nenue@0 314 c.cheevID = cheevID
Nenue@0 315 c.title = name
Nenue@0 316 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 317 points, completed, month, day, year, description, flags, icon, rewardText, isGuildAch, wasEarnedByMe, earnedBy
Nenue@0 318 c.numObjectives = GetAchievementNumCriteria(cheevID)
Nenue@0 319 c.objectives = {}
Nenue@0 320 for i = 1, c.numObjectives do
Nenue@0 321 local description, type, completed, quantity, requiredQuantity, characterName, flags, assetID, quantityString, criteriaID = GetAchievementCriteriaInfo(cheevID, i)
Nenue@0 322 c.objectives[i] = {
Nenue@21 323 objectiveIndex = i,
Nenue@8 324 cheevID = cheevID,
Nenue@0 325 text = description,
Nenue@0 326 type = type,
Nenue@0 327 finished = completed,
Nenue@14 328 value = quantity,
Nenue@14 329 maxValue = requiredQuantity,
Nenue@0 330 characterName = characterName,
Nenue@0 331 flags = flags,
Nenue@0 332 assetID = assetID,
Nenue@0 333 quantityString = quantityString,
Nenue@0 334 criteriaID = criteriaID,
Nenue@0 335 }
Nenue@0 336 end
Nenue@3 337 print('Cheevs.|cFF0088FFGetInfo|r('..index..')', 'obj:', GetAchievementNumCriteria(cheevID), name, description)
Nenue@0 338
Nenue@0 339 self.WatchInfo[index] = c
Nenue@0 340 return self.Info[cheevID]
Nenue@0 341 end