annotate ObjectiveTracker/BonusObjectiveData.lua @ 59:07ef62fe201f

Re-write of BuffFrame module: - uses secure hooks on blizzard BuffFrame.lua functions to determine needed action - make use of built-in table behavior to reduce unnecessary frame updates
author Nenue
date Thu, 28 Jul 2016 18:27:56 -0400
parents 9480bd904f4c
children
rev   line source
Nenue@27 1 --- ${PACKAGE_NAME}
Nenue@27 2 -- @file-author@
Nenue@27 3 -- @project-revision@ @project-hash@
Nenue@27 4 -- @file-revision@ @file-hash@
Nenue@27 5 -- Created: 4/13/2016 7:48 PM
Nenue@27 6 local B = select(2,...).frame
Nenue@27 7 local T = B:RegisterModule("ObjectiveTracker", _G.VeneerObjectiveWrapper, 'BuffFrame')
Nenue@27 8 local Default, Quest = T.DefaultHandler, T.Quest
Nenue@27 9 local print = B.print('Tracker')
Nenue@27 10 local lprint = B.print('Line')
Nenue@33 11 local iprint = B.print('Info')
Nenue@29 12 local Bonus = T.Bonus
Nenue@27 13
Nenue@29 14 local UnitName, GetRealmName, GetQuestObjectiveInfo, GetTasksTable, GetTaskInfo = UnitName, GetRealmName, GetQuestObjectiveInfo, GetTasksTable, GetTaskInfo
Nenue@29 15 local GetMapNameByID, GetCurrentMapAreaID = GetMapNameByID, GetCurrentMapAreaID
Nenue@38 16 local tinsert, ipairs, pairs, tostring, wipe = tinsert, ipairs, pairs, tostring, table.wipe
Nenue@29 17 local GetQuestProgressBarPercent, PERCENTAGE_STRING, GetTime = GetQuestProgressBarPercent, PERCENTAGE_STRING, GetTime
Nenue@38 18 local TASK_DISPLAY_TEST = 1 -- 1: normal (is nearby or on the map) 2: strict (is nearby) 3: data exists
Nenue@29 19
Nenue@40 20 --- Holds data for recently completed tasks
Nenue@40 21 local completedTasks = {}
Nenue@40 22
Nenue@29 23 --- Returns a tasks table modified to include recently completed objectives
Nenue@29 24 local InternalGetTasksTable = function()
Nenue@38 25 local print = Bonus.print
Nenue@29 26 local char = UnitName("player")
Nenue@29 27 local realm = GetRealmName()
Nenue@29 28 local tasks = GetTasksTable()
Nenue@29 29
Nenue@29 30 for questID, data in pairs(Bonus.Info) do
Nenue@38 31 print('GetTasksTable', questID, #data.objectives)
Nenue@29 32 for i, o in ipairs(data.objectives) do
Nenue@38 33 print('GetTasksTable', questID, i, o.text)
Nenue@29 34 end
Nenue@29 35 end
Nenue@29 36
Nenue@40 37 for questID, data in pairs(completedTasks) do
Nenue@29 38 if questID > 0 then
Nenue@29 39 local found = false
Nenue@29 40 for i = 1, #tasks do
Nenue@29 41 if tasks[i] == questID then
Nenue@29 42 found = true
Nenue@29 43 break
Nenue@29 44 end
Nenue@29 45 end
Nenue@29 46 -- if it's not part of the current table, then try to insert it where it was last found
Nenue@29 47 if not found then
Nenue@29 48 if data.watchIndex < #tasks then
Nenue@29 49 tinsert(tasks, data.watchIndex, data)
Nenue@29 50 else
Nenue@29 51 tinsert(tasks, data)
Nenue@29 52 end
Nenue@29 53 end
Nenue@29 54 end
Nenue@29 55 end
Nenue@29 56 return tasks
Nenue@29 57 end
Nenue@29 58
Nenue@29 59 --- Returns an entry from the composed tasks table if possible, otherwise makes an API pull
Nenue@40 60
Nenue@29 61 local InternalGetTaskInfo = function(questID)
Nenue@29 62 if completedTasks[questID] then
Nenue@40 63 -- if it's a recently completed task, use the information stored for it
Nenue@29 64 return true, true, #completedTasks[questID].objectives
Nenue@29 65 else
Nenue@29 66 return GetTaskInfo(questID)
Nenue@29 67 end
Nenue@29 68 end
Nenue@29 69
Nenue@29 70 --- Same as above but for the objective entries
Nenue@29 71 local InternalGetQuestObjectiveInfo = function(questID, objectiveIndex)
Nenue@29 72 if ( completedTasks[questID] ) then
Nenue@29 73 print('using internal data')
Nenue@29 74 return completedTasks[questID].objectives[objectiveIndex], completedTasks[questID].objectiveType, true;
Nenue@29 75 else
Nenue@29 76 return GetQuestObjectiveInfo(questID, objectiveIndex, false);
Nenue@29 77 end
Nenue@29 78 end
Nenue@29 79
Nenue@29 80 --- end redundant copy of silliness
Nenue@29 81 ------------------------------------------------------------------------------------------
Nenue@29 82
Nenue@29 83 Bonus.Completed = {}
Nenue@29 84 Bonus.POI = {}
Nenue@29 85 Bonus.Scenario = {}
Nenue@29 86 Bonus.QuestBlock = {}
Nenue@29 87 Bonus.WatchInfo = {}
Nenue@38 88
Nenue@38 89 local function CanShowTask(isInArea, isOnMap, existingTask, numObjectives)
Nenue@38 90 if TASK_DISPLAY_TEST == 1 then
Nenue@38 91 return (isInArea)
Nenue@38 92 elseif TASK_DISPLAY_TEST == 2 then
Nenue@38 93 return (isInArea and(isOnMap and existingTask))
Nenue@38 94 elseif TASK_DISPLAY_TEST == 3 then
Nenue@38 95 return true
Nenue@38 96 end
Nenue@38 97 end
Nenue@38 98
Nenue@29 99 function Bonus:GetNumWatched ()
Nenue@38 100
Nenue@38 101 local print = self.print
Nenue@29 102 print(self.name, self)
Nenue@29 103
Nenue@29 104 local tasks = InternalGetTasksTable()
Nenue@29 105 local numWatched = 0
Nenue@29 106 local numAll = 0
Nenue@33 107 local existingTasks = {}
Nenue@38 108 wipe(self.WatchList)
Nenue@38 109 print('|cFF'..self.internalColor..'Bonus.GetNumWatched()|r', #tasks)
Nenue@38 110 print('InternalGetTaskInfo')
Nenue@38 111
Nenue@29 112 for i, questID in ipairs(tasks) do
Nenue@29 113 local isInArea, isOnMap, numObjectives = InternalGetTaskInfo(questID)
Nenue@38 114 local existingTask = self.InfoBlock[questID]
Nenue@29 115 local displayObjectiveHeader = false;
Nenue@40 116 local displayTask = CanShowTask(isInArea, isOnMap, existingTask)
Nenue@40 117 if displayTask then
Nenue@38 118 print('TaskInfo', '|cFF00FF00showable objective list', questID)
Nenue@29 119 self.Info[questID] = self.Info[questID] or {}
Nenue@29 120
Nenue@29 121 local t = self.Info[questID]
Nenue@33 122 if (isOnMap or isInArea) and existingTask then
Nenue@33 123 t.areaID = GetCurrentMapAreaID()
Nenue@33 124 local _
Nenue@33 125 t.mapName, _, _, t.isMicroDungeon, t.microDungeonMapName = GetMapInfo()
Nenue@38 126 print('InternalGetTaskInfo', 'map data', t.areaID, t.mapName)
Nenue@33 127 end
Nenue@29 128
Nenue@29 129 local taskTitle
Nenue@38 130 t.id = questID
Nenue@33 131 t.objectives = {}
Nenue@40 132 local isComplete = true;
Nenue@29 133 for objectiveIndex = 1, numObjectives do
Nenue@29 134 local text, objectiveType, finished, displayAsObjective = InternalGetQuestObjectiveInfo(questID, objectiveIndex, false);
Nenue@29 135 displayObjectiveHeader = displayObjectiveHeader or displayAsObjective;
Nenue@29 136 if not taskTitle then
Nenue@29 137 if objectiveType == 'progressbar' and not text:match('^%d%+\\%d+') then
Nenue@29 138 taskTitle = text
Nenue@29 139 text = ''
Nenue@29 140 end
Nenue@29 141 end
Nenue@29 142
Nenue@29 143
Nenue@38 144 print('TaskObjective', text, objectiveType, finished, displayAsObjective)
Nenue@29 145 t.objectives[objectiveIndex] = t.objectives[objectiveIndex] or {}
Nenue@29 146 local o = t.objectives[objectiveIndex]
Nenue@29 147
Nenue@34 148 o.index = objectiveIndex
Nenue@29 149 o.text = text
Nenue@34 150 o.type = objectiveType
Nenue@29 151 o.finished = finished
Nenue@29 152 o.displayAsObjective = displayAsObjective
Nenue@40 153 isComplete = (isComplete and finished)
Nenue@29 154 end
Nenue@29 155
Nenue@33 156 T.SetRewards(t, questID)
Nenue@33 157
Nenue@29 158 -- didn't get a name from progress bar? what about area name
Nenue@29 159 if not taskTitle then
Nenue@29 160 if isInArea then
Nenue@29 161 taskTitle = GetMapNameByID(GetCurrentMapAreaID())
Nenue@29 162 end
Nenue@29 163 end
Nenue@34 164 t.numObjectives = numObjectives
Nenue@33 165 t.isInArea = isInArea
Nenue@33 166 t.isOnMap = isOnMap
Nenue@33 167 t.existingTask = existingTask
Nenue@33 168 t.questID = questID
Nenue@33 169 t.id = questID
Nenue@33 170 t.taskIndex = i
Nenue@29 171 t.title = taskTitle
Nenue@40 172 t.isComplete = isComplete
Nenue@38 173 self.WatchList[i] = t
Nenue@38 174 elseif existingTask then
Nenue@38 175 print('TaskInfo', '|cFFFF4400hideable task', questID)
Nenue@38 176 existingTask:Hide()
Nenue@29 177 end
Nenue@29 178
Nenue@40 179
Nenue@40 180 print ('TaskInfo', i, '|cFFFFFF00'.. questID..'|r', '('..(isInArea and '|cFF88FF88' or '|cFF666666') .. 'isInArea|r', 'AND', (isOnMap and '|cFF88FF88' or '|cFF666666') .. 'isOnMap|r)', 'OR', (existingTask and '|cFF88FF88' or '|cFF666666') .. 'existingTask|r', (displayTask and '|cFF00FF00show|r' or '|cFFFF4400hide|r'))
Nenue@29 181 end
Nenue@29 182
Nenue@36 183
Nenue@38 184 self.numWatched = #self.WatchList
Nenue@38 185 self.numAll = #existingTasks
Nenue@38 186 return self.numWatched, self.numWatched, self.WatchList
Nenue@29 187 end
Nenue@29 188
Nenue@40 189 Bonus.OnEvent = function(block, event, ...)
Nenue@40 190 if event == 'QUEST_LOG_UPDATE' then
Nenue@40 191 local info = block.info
Nenue@40 192
Nenue@40 193 local isInArea, isOnMap, numObjectives = InternalGetTaskInfo(info.questID)
Nenue@40 194 if not CanShowTask(isInArea, isOnMap, block, numObjectives) then
Nenue@40 195 block:Hide()
Nenue@40 196 end
Nenue@40 197 end
Nenue@40 198 end
Nenue@40 199
Nenue@40 200 Bonus.GetBlock = function(self, index)
Nenue@40 201 local block = Default.GetBlock(self, index)
Nenue@40 202 block:SetScript('OnEvent', self.OnEvent)
Nenue@40 203 block:RegisterEvent('QUEST_LOG_UPDATE')
Nenue@40 204 return block
Nenue@40 205 end
Nenue@40 206
Nenue@29 207 --- info cleanup done when turn-ins are detected
Nenue@33 208 Bonus.OnTurnIn = function(self, block, questID, xp, money)
Nenue@38 209 --[=[
Nenue@33 210 local info = self.Info[questID]
Nenue@33 211 if info.rewardInfo and #info.rewardInfo >= 1 then
Nenue@33 212 for i, reward in ipairs(info.rewardInfo) do
Nenue@29 213 --[[
Nenue@29 214 type = 'item',
Nenue@29 215 index = i ,
Nenue@29 216 name = name,
Nenue@29 217 texture = texture,
Nenue@29 218 count = count,
Nenue@29 219 quality = quality,
Nenue@29 220 isUsable = isUsable
Nenue@29 221 ]]
Nenue@29 222 print(' reward ', i, ' ', reward.type, reward.name, reward.count)
Nenue@29 223
Nenue@29 224 end
Nenue@29 225 end
Nenue@29 226
Nenue@34 227 print('|cFFFF8800'..block:GetName()..':OnTurnIn call', questID, xp, money)
Nenue@34 228 local savedTasks = B.Conf.TasksLog or {}
Nenue@29 229
Nenue@33 230 info.completedTime = GetTime()
Nenue@33 231 info.animate = true
Nenue@34 232 T.SetAnimate(self.updateReasonModule)
Nenue@34 233 savedTasks[questID] = {
Nenue@34 234 id = questID,
Nenue@34 235 title = info.title,
Nenue@34 236 finished = true,
Nenue@34 237 numObjectives = info.numObjectives,
Nenue@34 238 objectives = info.objectives,
Nenue@34 239 rewardInfo = info.rewardInfo,
Nenue@34 240 }
Nenue@34 241 B.Conf.TasksLog = savedTasks
Nenue@34 242
Nenue@34 243 print(' ## CONF TASKLOG ##')
Nenue@34 244 for i, t in pairs(savedTasks[questID]) do
Nenue@34 245 print(' |cFFFFFF00'.. tostring(i)..'|r', t)
Nenue@34 246
Nenue@34 247 end
Nenue@34 248 for o, j in ipairs(savedTasks[questID].objectives) do
Nenue@34 249 print(' |cFF00FFFF#'.. o ..'|r', j.type, j.finished)
Nenue@34 250 end
Nenue@33 251
Nenue@33 252 print('adding', info.title, 'to cache')
Nenue@38 253 --]=]
Nenue@29 254 end
Nenue@29 255
Nenue@29 256 Bonus.GetInfo = function(self, taskIndex)
Nenue@29 257 print(self.name, self)
Nenue@29 258 return self.WatchInfo[taskIndex]
Nenue@29 259 end
Nenue@29 260
Nenue@29 261
Nenue@29 262
Nenue@29 263 --- Update hooks
Nenue@38 264 Bonus.UpdateObjectives = function(handler, block, blockSchema)
Nenue@38 265 block.schema = blockSchema or 'default'
Nenue@38 266 local info = block.info
Nenue@38 267 block.title:SetText(info.title)
Nenue@38 268
Nenue@38 269
Nenue@27 270 Default.UpdateObjectives(handler, block)
Nenue@38 271 return blockSchema
Nenue@27 272 end
Nenue@27 273
Nenue@38 274 Bonus.UpdateLine = function(handler, block, data)
Nenue@27 275 local info = block.info
Nenue@27 276 local print = lprint
Nenue@31 277 local text, attachment = '', nil
Nenue@34 278 if data.type == 'progressbar' then
Nenue@27 279 print(' |cFFFF44DDpercent='..tostring(GetQuestProgressBarPercent(info.questID)))
Nenue@33 280 local percent = 100
Nenue@33 281 if not data.finished then
Nenue@33 282 percent = GetQuestProgressBarPercent(info.questID)
Nenue@33 283 end
Nenue@34 284 data.value = percent
Nenue@34 285 data.maxValue = 100
Nenue@34 286
Nenue@40 287 attachment = T.GetWidget(data, 'StatusBar', info.questID..'-'..data.index)
Nenue@40 288 attachment:SetParent(block)
Nenue@34 289 print(attachment:GetNumPoints())
Nenue@34 290 for i = 1, attachment:GetNumPoints() do
Nenue@34 291 print(' ',attachment:GetPoint(i))
Nenue@34 292 end
Nenue@34 293
Nenue@33 294 attachment.value = percent
Nenue@33 295 attachment.maxValue = 100
Nenue@34 296 attachment.status:SetFormattedText(PERCENTAGE_STRING, percent)
Nenue@38 297 --attachment:SetParent(handler.frame)
Nenue@38 298 --print(attachment.status:GetText())
Nenue@27 299 print(' |cFFFF0022** text:|r', data.text, '|cFFFF0022value:|r', data.value, '|cFFFF0022max:|r', data.maxValue)
Nenue@27 300 end
Nenue@34 301 text = data.text
Nenue@38 302 return text, attachment, 'default'
Nenue@27 303 end
Nenue@27 304
Nenue@33 305 Bonus.Select = function(handler, block)
Nenue@33 306 print(handler, block)
Nenue@33 307 handler:OnTurnIn(block, block.info.questID)
Nenue@27 308 end
Nenue@27 309 Bonus.Remove = function(self)
Nenue@27 310
Nenue@27 311 end