view 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
line wrap: on
line source
local B = select(2,...).frame
local wipe, pairs, ipairs, min, max, unpack = table.wipe, pairs, ipairs, min, max, unpack
local tinsert, tostring, format, mod = tinsert, tostring, format, mod
local GetQuestTagInfo, GetQuestLogTitle = GetQuestTagInfo, GetQuestLogTitle
local GetNumQuestLogEntries, GetNumQuestWatches, GetQuestLogCompletionText, IsQuestWatched, IsQuestHardWatched, GetQuestLogSpecialItemInfo, GetQuestLogSpecialItemCooldown = GetNumQuestLogEntries, GetNumQuestWatches, GetQuestLogCompletionText, IsQuestWatched, IsQuestHardWatched, GetQuestLogSpecialItemInfo, GetQuestLogSpecialItemCooldown
local GetNumAutoQuestPopUps, GetAutoQuestPopUp, GetTasksTable, GetNumQuestLogTasks, GetTaskInfo, GetQuestObjectiveInfo = GetNumAutoQuestPopUps, GetAutoQuestPopUp, GetTasksTable, GetNumQuestLogTasks, GetTaskInfo, GetQuestObjectiveInfo
local GetNumQuestLogRewardCurrencies, GetQuestLogRewardCurrencyInfo, GetNumQuestLogRewards, GetQuestLogRewardInfo, GetQuestLogRewardMoney, GetMoneyString = GetNumQuestLogRewardCurrencies, GetQuestLogRewardCurrencyInfo, GetNumQuestLogRewards, GetQuestLogRewardInfo, GetQuestLogRewardMoney, GetMoneyString
local GetNumQuestLeaderBoards, GetAchievementNumCriteria, GetQuestLogLeaderBoard, GetAchievementCriteriaInfo = GetNumQuestLeaderBoards, GetAchievementNumCriteria, GetQuestLogLeaderBoard, GetAchievementCriteriaInfo
local GetQuestWatchIndex, GetQuestLogIndexByID, GetSuperTrackedQuestID, SetSuperTrackedQuestID, GetQuestWatchInfo = GetQuestWatchIndex, GetQuestLogIndexByID, GetSuperTrackedQuestID, SetSuperTrackedQuestID, GetQuestWatchInfo
local QuestHasPOIInfo, GetDistanceSqToQuest, GetQuestFactionGroup = QuestHasPOIInfo, GetDistanceSqToQuest, GetQuestFactionGroup
local GetTrackedAchievements, GetNumTrackedAchievements, GetAchievementInfo = GetTrackedAchievements, GetNumTrackedAchievements, GetAchievementInfo
local GetMoney, floor = GetMoney, floor
local T = B:RegisterModule("ObjectiveTracker", _G.VeneerObjectiveWrapper, 'BuffFrame')
local print = B.print('Info')
local QUEST_TAG_DUNGEON = QUEST_TAG_DUNGEON
local QUEST_TAG_GROUP = QUEST_TAG_GROUP
local QUEST_TAG_ACCOUNT = QUEST_TAG_ACCOUNT
local QUEST_TAG_TCOORDS = QUEST_TAG_TCOORDS
local LE_QUEST_FREQUENCY_DAILY = LE_QUEST_FREQUENCY_DAILY
local LE_QUEST_FREQUENCY_WEEKLY = LE_QUEST_FREQUENCY_WEEKLY
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

local Tracker, Bonus, AutoQuest, Quest, Cheevs = T.DefaultTracker, T.Bonus, T.AutoQuest, T.Quest, T.Cheevs
--------------------------------------------------------------------
--- Tracker-specific data retrieval functions
--------------------------------------------------------------------


local DoQuestRewards= function(t, questID)
  local rewards = {}
  t.numCurrencies = GetNumQuestLogRewardCurrencies(questID)
  for i = 1, t.numCurrencies do
    local name, texture, count = GetQuestLogRewardCurrencyInfo(i, questID)
    tinsert(rewards,{
      type = 'currency',
      index = i,
      name = name,
      texture = texture,
      count = count
    });
  end
  -- items
  t.numItems = GetNumQuestLogRewards(questID)
  for i = 1, t.numItems do
    local name, texture, count, quality, isUsable = GetQuestLogRewardInfo(i, questID)
    tinsert(rewards, {
      type = 'item',
      index = i ,
      name = name,
      texture = texture,
      count = count,
      quality = quality,
      isUsable = isUsable
    });
  end
  -- money

  local money = GetQuestLogRewardMoney(questID)
  if ( money > 0 ) then
    tinsert(rewards, {
      type = 'money',
      name = GetMoneyString(money),
      texture = "Interface\\Icons\\inv_misc_coin_01",
      count = 0,
    });
  end

  if #rewards >= 1 then
    t.rewardInfo = rewards
  end
end


-----------------------------
--- AUTO_QUEST
AutoQuest.LogInfo = {}
AutoQuest.LogBlock = {}
AutoQuest.QuestBlock = {}
AutoQuest.WatchBlock = {}
function AutoQuest:GetNumWatched ()
  print(self.name, self)
  Quest:GetNumWatched()
  self.numWatched = GetNumAutoQuestPopUps()

  return self.numWatched
end
AutoQuest.GetInfo = function(self, popupIndex)


  local questID, type = GetAutoQuestPopUp(popupIndex)
  local questLogIndex = GetQuestLogIndexByID(questID)
  local title, level, suggestedGroup, isHeader, isCollapsed, isComplete, frequency, questID, startEvent, displayQuestID, isOnMap, hasLocalPOI, isTask, isStory = GetQuestLogTitle(questLogIndex)

  self.Info[questID] = self.Info[questID] or {}
  local popup = self.Info[questID]
  popup.title = title
  popup.description = type
  popup.popupType = type
  popup.questID = questID
  popup.questLogIndex = questLogIndex
  popup.popupIndex = popupIndex

  self.Info[questID] = popup
  self.WatchInfo[popupIndex] = popup


  return self.Info[questID]
end

-----------------------------
--- BONUS OBJECTIVE
-- The default UI pops them up as you enter their relevant areas, but the data is actually available at all times.
-- The only requirement is that you've been to said area and progressed any of the objectives.
-- Blizzard deal with this fact by caching any task data collected during session and masking out whatever gets completed.
-- For the addon's module structure to work, GetNumWatched method also invokes a tasks table scan.
-- That composes the table searched by GetInfo().

------------------------------------------------------------------------------------------
--- These functions are copied from Blizzard_BonusObjectiveTracker.lua;
-- It's kind of dumb, but this avoids the risk of code taint.

--- Returns a tasks table modified to include recently completed objectives
local UnitName, GetRealmName = UnitName, GetRealmName
local InternalGetTasksTable = function()
  local savedTasks = T.Conf.TasksLog
  local char = UnitName("player")
  local realm = GetRealmName()
  local tasks = GetTasksTable()

  for questID, data in pairs(Bonus.Info) do

    print('  -- questID:', questID, #data.objectives)
      for i, o in ipairs(data.objectives) do
        print('    --', i, o.text)
      end

  end


  for questID, data in pairs(savedTasks) do
    if questID > 0  then
      local found = false
      for i = 1, #tasks do
        if tasks[i] == questID then
          found = true
          break
        end
      end
      -- if it's not part of the current table, then try to insert it where it was last found
      if not found then
        if data.watchIndex < #tasks then
          tinsert(tasks, data.watchIndex, data)
        else
          tinsert(tasks, data)
        end
      end
    end
  end
  return tasks
end

--- Returns an entry from the composed tasks table if possible, otherwise makes an API pull
local InternalGetTaskInfo = function(questID)
  local completedTasks = T.Conf.TasksLog
  if completedTasks[questID] then
    return true, true, #completedTasks[questID].objectives
  else
    return GetTaskInfo(questID)
  end
end

--- Same as above but for the objective entries
local InternalGetQuestObjectiveInfo = function(questID, objectiveIndex)
  local completedTasks = T.Conf.TasksLog
  if ( completedTasks[questID] ) then
    print('using internal data')
    return completedTasks[questID].objectives[objectiveIndex], completedTasks[questID].objectiveType, true;
  else
    return GetQuestObjectiveInfo(questID, objectiveIndex, false);
  end
end

--- end redundant copy of silliness
------------------------------------------------------------------------------------------

Bonus.Completed = {}
Bonus.POI = {}
Bonus.Scenario = {}
Bonus.QuestBlock = {}
Bonus.WatchInfo = {}
function Bonus:GetNumWatched ()
  print(self.name, self)

  local tasks = InternalGetTasksTable()
  local numWatched = 0
  local numAll = 0
  self.WatchInfo = {}
  print('|cFFFFFF00Bonus.GetNumWatched()|r', #tasks)
  print('  TasksTable pull:')
  for i, questID in ipairs(tasks) do
    local isInArea, isOnMap, numObjectives = InternalGetTaskInfo(questID)
    local existingTask = self.QuestBlock[questID]
    local displayObjectiveHeader = false;
    local test = (isInArea or (isOnMap and existingTask))
    --local test = true
    if test then
      self.Info[questID] = self.Info[questID] or {}

      local t = self.Info[questID]
      self.WatchInfo[i] = t
      t.isInArea = isInArea
      t.isOnMap = isOnMap
      t.existingTask = existingTask
      t.questID = questID
      t.objectives = {}
      t.taskIndex = i


      DoQuestRewards(t, questID)

      local taskTitle
      local taskFinished = true;
      for objectiveIndex = 1, numObjectives do
        local text, objectiveType, finished, displayAsObjective = InternalGetQuestObjectiveInfo(questID, objectiveIndex, false);
        displayObjectiveHeader = displayObjectiveHeader or displayAsObjective;
        if not taskTitle then
          if objectiveType == 'progressbar' and not text:match('^%d%+\\%d+') then
            taskTitle = text
            text = ''
          end
        end


        print('  --', text, objectiveType, finished, displayAsObjective)
        t.objectives[objectiveIndex] = t.objectives[objectiveIndex] or  {}
        local  o = t.objectives[objectiveIndex]

        o.objectiveIndex = objectiveIndex
        o.text = text
        o.objectiveType = objectiveType
        o.finished = finished
        o.displayAsObjective = displayAsObjective
        print('     |cFF00FF88*', objectiveIndex, text)
      end

      -- didn't get a name from progress bar? what about area name
      if not taskTitle then
        if isInArea then
          taskTitle = GetMapNameByID(GetCurrentMapAreaID())
        end
      end
      t.title = taskTitle
    end

    print ('    |cFF00FF88#', i, 'questID', questID, 'inArea', isInArea, 'onMap', isOnMap, 'existing', (existingTask and 'Y' or 'N'), (test and '|cFF00FF00show|r' or '|cFFFF0088hide|r'))
  end


  self.numAll = #tasks
  self.numWatched = #self.WatchInfo
  print('  stats:', self.numAll, 'active tasks,', self.numWatched, 'nearby or animating')
  --return #tasks
  return #self.WatchInfo
end

--- info cleanup done when  turn-ins are detected
Bonus.OnTurnIn = function(self, questID, xp, money)

  if #self.info.rewardInfo >= 1 then
    for i, reward in ipairs(self.info.rewardInfo) do
      --[[
        type = 'item',
        index = i ,
        name = name,
        texture = texture,
        count = count,
        quality = quality,
        isUsable = isUsable
       ]]
      print(' reward ', i, ' ', reward.type, reward.name, reward.count)

    end
  end

  print('|cFFFF8800'..self.name..':OnTurnIn call', questID, xp, money)
  local savedTasks = B.Conf.TasksLog

  self.Info[questID].completedTime = GetTime()
  self.Info[questID].animate = true
  T.SetAnimate(self.watchReasonModule)
  savedTasks[questID] = self.Info[questID]
end

Bonus.GetInfo = function(self, taskIndex)
  print(self.name, self)
  return self.WatchInfo[taskIndex]
end



Cheevs.GetNumWatched = function(self)
  print('|cFF00FF00' .. GetTime())
  Cheevs.trackedCheevs = {GetTrackedAchievements()}
  return GetNumTrackedAchievements()
end
Cheevs.GetInfo = function(self, index)
  local cheevID = Cheevs.trackedCheevs[index]
  local id, name, points, completed, month, day, year, description, flags, icon, rewardText, isGuildAch, wasEarnedByMe, earnedBy = GetAchievementInfo(cheevID)

  self.Info[cheevID] = {}
  local c = self.Info[cheevID]
  c.type = 'Cheevs'
  c.watchIndex = index
  c.cheevID = cheevID
  c.title = name
  c.points, c.completed, c.month, c.day, c.year, c.description, c.flags, c.icon, c.rewardText, c.isGuildAch, c.wasEarnedByMe, c.earnedBy =
  points, completed, month, day, year, description, flags, icon, rewardText, isGuildAch, wasEarnedByMe, earnedBy
  c.numObjectives = GetAchievementNumCriteria(cheevID)
  c.objectives = {}
  for i = 1, c.numObjectives do
    local description, type, completed, quantity, requiredQuantity, characterName, flags, assetID, quantityString, criteriaID = GetAchievementCriteriaInfo(cheevID, i)
    c.objectives[i] = {
      objectiveIndex = i,
      cheevID = cheevID,
      text = description,
      type = type,
      finished = completed,
      value = quantity,
      maxValue = requiredQuantity,
      characterName = characterName,
      flags = flags,
      assetID = assetID,
      quantityString = quantityString,
      criteriaID = criteriaID,
    }
  end
  print('Cheevs.|cFF0088FFGetInfo|r('..index..')', 'obj:', GetAchievementNumCriteria(cheevID), name, description)

  self.WatchInfo[index] = c
  return self.Info[cheevID]
end