changeset 65:02f1d3bce558

Update for Legion Patch 7.2 - Massively improved performance footprint via 7.2 API changes and some major optimization of POI update triggers - Removed AP token caching until reliable mechanisms for detecting AK shifts can be resolved.
author Nenue
date Wed, 29 Mar 2017 13:45:41 -0400
parents 876c3f0bfd0e
children e43e10c5576b
files QuestPOI.lua WorldPlan.toc WorldQuests.lua
diffstat 3 files changed, 236 insertions(+), 85 deletions(-) [+]
line wrap: on
line diff
--- a/QuestPOI.lua	Thu Mar 23 05:26:51 2017 -0400
+++ b/QuestPOI.lua	Wed Mar 29 13:45:41 2017 -0400
@@ -2,6 +2,8 @@
 -- QuestPOI.lua
 -- Created: 10/1/2016 7:21 PM
 -- %file-revision%
+-- Big TODOs:
+-- -- generate frames using `WorldMap_GetOrCreateTaskPOI' to remove tainting issues
 --
 local _, db = ...
 local TQ_GetQuestInfoByQuestID = C_TaskQuest.GetQuestInfoByQuestID
@@ -21,6 +23,8 @@
 local GetQuestLogRewardMoney, GetQuestLogRewardCurrencyInfo, GetMoneyString = GetQuestLogRewardMoney, GetQuestLogRewardCurrencyInfo, GetMoneyString
 local SpellCanTargetQuest, GetCVarBool = SpellCanTargetQuest, GetCVarBool
 local SetSuperTrackedQuestID = SetSuperTrackedQuestID
+local HaveQuestRewardData = HaveQuestRewardData
+
 
 local pairs, ipairs, tinsert, unpack, select = pairs, ipairs, tinsert, unpack, select
 local floor, mod, tostring, tonumber, GetSuperTrackedQuestID = floor, mod, tostring, tonumber, GetSuperTrackedQuestID
@@ -54,6 +58,7 @@
 local REWARD_GEAR = WORLD_QUEST_REWARD_TYPE_FLAG_EQUIPMENT
 local REWARD_CURRENCY = WORLD_QUEST_REWARD_TYPE_FLAG_ORDER_RESOURCES
 local REWARD_REAGENT = WORLD_QUEST_REWARD_TYPE_FLAG_MATERIALS
+local REWARD_HONOR = WORLD_QUEST_REWARD_TYPE_FLAG_HONOR
 
 local LE_QUEST_TAG_TYPE_PVP = LE_QUEST_TAG_TYPE_PVP
 local LE_QUEST_TAG_TYPE_PET_BATTLE = LE_QUEST_TAG_TYPE_PET_BATTLE
@@ -67,6 +72,9 @@
 local LE_QUEST_TAG_TYPE_PROFESSION = LE_QUEST_TAG_TYPE_PROFESSION
 local LE_QUEST_TAG_TYPE_NORMAL = LE_QUEST_TAG_TYPE_NORMAL
 
+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
+
+
 local STYLE_TYPE_PENDING = 768
 
 
@@ -265,7 +273,7 @@
       end
     end
   end
-  WorldMap_AddQuestRewardsToTooltip(questID)
+  GameTooltip_AddQuestRewardsToTooltip(WorldMapTooltip, questID)
 
   WorldMapTooltip:Show()
   --WorldMapTooltip.recalculatePadding = true;
@@ -292,18 +300,11 @@
   local questTitle, factionID, capped = TQ_GetQuestInfoByQuestID(questID)
   -- if the title is nil, then wait and try later
   if not questTitle then
-    if not self.isPending then
-      C_TaskQuest.RequestPreloadRewardData(questID)
-      self.isPending = true
-    end
-    dprint('|cFFBB8844isPending=true|r|cFF00FFFF', self.questId)
+    dprint('|cFFBB8844dataLoaded|r = false|cFF00FFFF', self.questId)
+    return false
   else
     self.title, self.factionID, self.capped = questTitle, factionID, capped
-    dprint('|cFFBB8844  data|r|cFF00FFFF', (self.isPending and '|cFFFF4400delayed|r' or '|cFF00FF00success|r'), self.title, '|r', self.factionID)
-    if self.dataLoaded then
-      dprint('  |cFFFF4400overwriting data|r')
-    end
-
+    dprint(questTitle, factionID, capped)
     -- set tag details
     local worldQuestType
     self.tagID, self.tagName, worldQuestType, self.rarity, self.isElite, self.tradeskillLineIndex = GetQuestTagInfo(questID);
@@ -326,35 +327,163 @@
     self.worldQuestType = worldQuestType
     self.tagAtlas = tagAtlas
 
-    self:SetRewardInfo()
-
-    -- force throttle on success
-    --qprint('  |cFF00FFFF'..questID..'|r hasUpdate:', hasUpdate, 'isPending:', isPending, 'isShown', self:IsShown())
-    --qprint('  ', 'rewardType:', self.rewardType, 'tag:', self.tagID)
-    qprint('  ', tostring(self.title), " |T"..tostring(self.itemTexture)..":12:12|t", tostring(self.itemName))
-
-    if self.itemTexture and self.itemName and self.title then
+    local dataLoaded, rewardType, itemName, itemTexture, itemNumber, quality = self:UpdateRewards()
+    dprint('|cFFBB8844  dataLoaded|r =', dataLoaded, rewardType, itemName, itemTexture, itemNumber, quality)
+    if dataLoaded then
+      self.rewardType = rewardType
+      self.itemName = itemName
+      self.itemTexture = itemTexture
+      self.itemNumber = itemNumber
+      self.itemQuality = quality
       self.dataLoaded = true
-      self.isPending = nil
-      self.throttle = 1
-      self.updateRate = PIN_REFRESH_DELAY
       self.isStale = true
     end
   end
 
   self.isCriteria = WorldMapFrame.UIElementsFrame.BountyBoard:IsWorldQuestCriteriaForSelectedBounty(questID)
 
-  return self.isStale, self.isPending
+  return self.dataLoaded
 end
 
-function QuestPOI:SetRewardInfo()
+--- Returns true if data has changed (either from loading in or qualifications changed)
+function QuestPOI:UpdateRewards()
   local questID = self.questID
-  if not HaveQuestData(questID) then
-    self.isPending = true
+  if not HaveQuestRewardData(questID) then
+    C_TaskQuest.RequestPreloadRewardData(questID);
+    return false;
   else
+    local rewardMoney, rewardAP, rewardHonor
+    local rewardItems, rewardCurrency = {}, {}
+    local rewardIcon, rewardName, rewardCount, rewardStyle, rewardType, itemID, quantity, quality
+    local xpIcon, xpName, xpCount, xpType
 
-    local rewardIcon, rewardName, rewardCount, rewardStyle, rewardType, itemID, quantity, quality
-    -- set reward category
+    if (GetNumQuestLogRewardCurrencies(questID) > 0 or GetNumQuestLogRewards(questID) > 0 or GetQuestLogRewardMoney(questID) > 0 or GetQuestLogRewardArtifactXP(questID) > 0 or GetQuestLogRewardHonor(questID)) then
+      local money = GetQuestLogRewardMoney(questID)
+      if money > 0 then
+        rewardMoney = money
+        rewardIcon = ICON_MONEY
+        rewardName = GetMoneyString(money)
+        rewardCount = floor(money/10000)
+        rewardType = REWARD_CASH
+      end
+
+      local artifactXP = GetQuestLogRewardArtifactXP(questID);
+      if artifactXP > 0 then
+        rewardAP = artifactXP
+        rewardIcon = "Interface\\ICONS\\inv_7xp_inscription_talenttome01"
+        rewardCount = artifactXP
+        rewardType = REWARD_ARTIFACT_POWER
+        qprint('  artifactXP', artifactXP)
+      end
+
+      local numQuestCurrencies = GetNumQuestLogRewardCurrencies(questID);
+      for i = 1, numQuestCurrencies do
+        local name, texture, numItems = GetQuestLogRewardCurrencyInfo(i, questID);
+        local text = BONUS_OBJECTIVE_REWARD_WITH_COUNT_FORMAT:format(texture, numItems, name);
+        tinsert(rewardCurrency, {
+          name = name,
+          texture = texture,
+          numItems = numItems,
+          text = text
+        })
+        qprint('  currency', i, name, " |T"..tostring(texture)..":12:12|t")
+        rewardIcon = texture
+        rewardCount = numItems
+        rewardName = name
+        rewardType = REWARD_CURRENCY
+      end
+      local honorAmount = GetQuestLogRewardHonor(questID);
+      if honorAmount > 0 then
+        xpIcon = "Interface\\ICONS\\Achievement_LegionPVPTier4"
+        xpCount = honorAmount
+        xpName = HONOR
+        xpType = HONOR_CURRENCY
+      end
+
+      local numQuestRewards = GetNumQuestLogRewards(questID);
+      if numQuestRewards > 0 then
+        local foundPrimary
+        for i = 1, numQuestRewards do
+          local name, texture, numItems, quality, isUsable, itemID = GetQuestLogRewardInfo(i, questID)
+
+          if itemID then
+            local itemName, itemLink, itemRarity, itemLevel, itemMinLevel, itemType, itemSubType, itemStackCount, itemEquipLoc, itemTexture, sellPrice, classID, subclassID = GetItemInfo(itemID);
+
+
+            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
+              rewardType = REWARD_GEAR
+              rewardIcon = texture
+              rewardName = name
+              rewardCount = numItems
+              foundPrimary = true
+            elseif IsArtifactPowerItem(itemID) then
+              rewardType = REWARD_ARTIFACT_POWER
+              rewardIcon = texture
+              rewardName = name
+              rewardCount = 1
+              foundPrimary = true
+
+              WorldPlanTooltip:SetOwner(self, 'ANCHOR_NONE')
+              WorldPlanTooltip:SetHyperlink(itemLink)
+              for i = 1, WorldPlanTooltip:NumLines() do
+                local line = _G['WorldPlanTooltipTextLeft' .. i]
+                local text = line and line:GetText()
+                local ap = text and text:gsub(',', ''):match('(%d+) '..ARTIFACT_POWER)
+                if ap then
+                  rewardCount = tonumber(ap)
+                  print(ap)
+                end
+
+              end
+
+              if WorldPlanTooltipTextLeft2 then
+                local text = WorldPlanTooltipTextLeft2:GetText()
+              end
+
+              print('is an AP token')
+            elseif classID == LE_ITEM_CLASS_TRADEGOODS then
+              rewardType = REWARD_REAGENT
+              rewardIcon = texture
+              rewardName = name
+              rewardCount = numItems
+              foundPrimary = true
+            end
+
+
+            qprint('  reward', i, name, " |T"..tostring(texture)..":12:12|t", quality, isUsable, itemID)
+            tinsert(rewardItems, {
+              name = name,
+              texture = texture,
+              numItems = numItems,
+              quality = quality,
+              isUsable = isUsable
+            })
+            if not foundPrimary then
+              rewardType = REWARD_GEAR
+
+              rewardIcon = texture
+              rewardName = name
+              rewardCount = numItems
+            end
+
+          end
+
+        end
+      end
+
+      qprint('  '..self.questID..':|cFFFFFF00SetRewardInfo():', numQuestRewards, rewardType)
+      qprint('  ', tostring(self.title), " |T"..tostring(self.itemTexture)..":12:12|t", tostring(self.itemName))
+
+      if (self.itemNumber ~= rewardCount) or (self.rewardType ~= rewardType) or (self.itemName ~= rewardName) or (self.itemTexture ~= rewardIcon) then
+        return true, rewardType, rewardName, rewardIcon, rewardCount, quality
+      else
+        return false
+      end
+    end
+
+
+
+    --[[ set reward category
     local numRewards = GetNumQuestLogRewards(questID)
     local numCurrency = GetNumQuestLogRewardCurrencies(questID)
     local money = GetQuestLogRewardMoney(questID)
@@ -364,31 +493,9 @@
       rewardName, rewardIcon, rewardCount = GetQuestLogRewardCurrencyInfo(1, questID)
       rewardType = REWARD_CURRENCY
     elseif money >= 1 then
-      rewardIcon = ICON_MONEY
       rewardName = GetMoneyString(money)
-      rewardType = REWARD_CASH
     end
-
-  qprint('  '..self.questID..':|cFFFFFF00SetRewardInfo():', numRewards, rewardType)
-    self.itemNumber = tonumber(rewardCount or self.itemNumber)
-    self.rewardType = rewardType
-    self.quality = quality
-
-    self.itemTexture = rewardIcon or self.itemTexture
-    self.itemName = rewardName or self.itemName
-
-    -- flag unresolved info
-    if not (rewardIcon and rewardName) then
-      self.isPending = true
-      self.isStale = nil
-      --WorldPlan:print('|cFFFFFF00'..tostring(self.title)..'|r waiting on texture info')
-    else
-      if (rewardIcon and rewardName) and self.isPending then
-        --WorldPlan:print('|cFF00FF00'..tostring(self.title)..'|r has info', rewardIcon, rewardName)
-        self.isStale = true
-      end
-      self.isPending = nil
-    end
+    --]]
 
   end
 end
@@ -442,7 +549,7 @@
   self.isAnimating = nil
 end
 
--- different from owningFrame
+-- Places the pin and triggers display
 function QuestPOI:SetAnchor(owner, dX, dY, mapWidth, mapHeight)
   wqprint(self:GetName()..':SetAnchor()', owner, dX, dY, self.filtered, self.used)
   if not self.used then
@@ -460,13 +567,19 @@
     if not (mapHeight and mapWidth) then
       mapWidth, mapHeight = owner:GetSize()
       end
-    local pX = (dX * mapWidth)
-    local pY = (-dY * mapHeight)
-    self.x = dX
-    self.y = dY
-    self:SetPoint('CENTER', owner, 'TOPLEFT', pX, pY)
+    if (self.x ~= dY) or (self.y ~= dY) then
+      self.x = dX
+      self.y = dY
+      local pX = (dX * mapWidth)
+      local pY = (-dY * mapHeight)
+      self:SetPoint('CENTER', owner, 'TOPLEFT', pX, pY)
+    end
   else
-    self:SetPoint('CENTER')
+    if self.x or self.y then
+      self.x = nil
+      self.y = nil
+      self:SetPoint('CENTER')
+    end
   end
 
   self:ShowFrames()
@@ -499,7 +612,6 @@
 
 function QuestPOI:OnLoad()
   qprint('|cFF00FF88'..self:GetName()..':OnLoad()|r',db.Config)
-  self:RegisterEvent('SUPER_TRACKED_QUEST_CHANGED')
 
   self.title = '|cFF0088FF' .. RETRIEVING_DATA..'|r'
   self.isPending = true
@@ -522,12 +634,6 @@
 end
 
 
-function QuestPOI:OnEvent(event, ...)
-  if event == 'SUPER_TRACKED_QUEST_CHANGED' then
-    self.isStale = true
-  end
-end
-
 function QuestPOI:OnUpdate (sinceLast)
   -- control update check intervals
   self.throttle = (self.throttle or self.updateRate) + sinceLast
@@ -548,7 +654,7 @@
 
   -- query for reward data if it wasn't found in the original scan
   local questID = self.questID
-  if self.isPending then
+  if not self.dataLoaded then
     --print('|cFFFF4400'..self:GetID()..':|r polling reward info')
     if not (self.isAnimating) then
       self.PendingFade:Play()
@@ -608,7 +714,7 @@
 
 
 
-  local styleType = (self.isPending and STYLE_TYPE_PENDING) or self.rewardType
+  local styleType = (self.dataLoaded and self.rewardType) or STYLE_TYPE_PENDING
   local style,subStyle =  self:GetTypeInfo(self.rewardType)
   if (self.filtered or (not self.dataLoaded)) and (self.questID ~= GetSuperTrackedQuestID()) then
     subStyle = style.minimized
@@ -634,7 +740,11 @@
 
     if self.itemNumber then
       local numberString = self.itemNumber
-      if self.itemNumber >= 1000 then
+      if self.itemNumber >= 1000000 then
+        numberString = (floor(self.itemNumber/100000)/10) .. 'M'
+      elseif self.itemNumber >= 10000 then
+        numberString = floor(self.itemNumber/1000) .. 'k'
+      elseif self.itemNumber >= 1000 then
         local numeral = floor(self.itemNumber/1000)
         local decimal = mod(self.itemNumber, 1000)
         numberString = numeral
@@ -740,7 +850,6 @@
       self.isStale = true
       print('  '..self.questID..':|cFFFFFF00CheckFilterRules()|r ', canShow, filtered, self.title)
     end
-
     self.filtered = filtered
   end
 
--- a/WorldPlan.toc	Thu Mar 23 05:26:51 2017 -0400
+++ b/WorldPlan.toc	Wed Mar 29 13:45:41 2017 -0400
@@ -1,4 +1,4 @@
-## Interface: 70100
+## Interface: 70200
 ## Title: WorldPlan
 ## Notes: World Quest planning helper
 ## Author: Krakyn
--- a/WorldQuests.lua	Thu Mar 23 05:26:51 2017 -0400
+++ b/WorldQuests.lua	Wed Mar 29 13:45:41 2017 -0400
@@ -35,7 +35,9 @@
 local REWARD_CURRENCY = WORLD_QUEST_REWARD_TYPE_FLAG_ORDER_RESOURCES
 local REWARD_REAGENT = WORLD_QUEST_REWARD_TYPE_FLAG_MATERIALS
 
-
+local numShown = 0
+local numLoaded = 0
+local isDataLoaded
 local numPins = 0
 local NumPinFrames = 1
 Module.TasksByID = {}
@@ -72,6 +74,31 @@
   hooksecurefunc("WorldMapFrame_UpdateMap", InternalDoRefresh)
   WorldMapFrame.UIElementsFrame.BountyBoard:SetSelectedBountyChangedCallback(InternalDoRefresh);
   WorldMapFrame.UIElementsFrame.ActionButton:SetOnCastChangedCallback(InternalDoRefresh);
+
+  self.Status = CreateFrame('Frame', nil, self)
+  self.Status:SetPoint('TOPLEFT', WorldMapPOIFrame, 'TOPLEFT', 0, 0)
+  self.Status:SetPoint('BOTTOMRIGHT', WorldMapPOIFrame, 'TOPRIGHT', 0, -4)
+  self.Status.t = self.Status:CreateTexture(nil, 'OVERLAY')
+  self.Status.b = self.Status:CreateTexture(nil, 'BACKGROUND')
+  self.Status.b:SetColorTexture(0,0,0,.25)
+  self.Status.b:SetAllPoints(self.Status)
+  self.Status.t:SetColorTexture(1,1,1,.5)
+  self.Status.t:SetPoint('TOP')
+  self.Status.t:SetPoint('BOTTOM')
+  self.Status.t:SetPoint('LEFT')
+  local translationEnd, translationStart
+  self.Status:SetScript('OnUpdate', function(status)
+    local translateTo
+    if numLoaded < numShown then
+      translateTo = numLoaded/numShown * status:GetWidth()
+      status.t:SetWidth(translateTo)
+    else
+      translateTo = numShown * status:GetWidth()
+      status.t:SetWidth(translateTo)
+    end
+
+
+  end)
 end
 
 function Module:OnConfigUpdate()
@@ -160,7 +187,7 @@
     self.isStale = true
   end
 end
-
+local superTrackedQuestID
 function Module:OnEvent (event, ...)
 
   print('|cFFFFFF00'..self:GetName()..':OnEvent() '..event..'|r', GetTime(), ...)
@@ -181,10 +208,7 @@
       self:ReleasePin(db.QuestsByID[questID])
       rprint('|cFFFF4400release|r', questID)
     end
-  elseif event == 'SKILL_LINES_CHANGED' then
-    self:Refresh()
-  elseif event == 'CURRENT_SPELL_CAST_CHANGED' then
-
+  elseif event == 'SKILL_LINES_CHANGED' or event == 'CURRENT_SPELL_CAST_CHANGED' then
     self:Refresh()
   elseif event == 'ARTIFACT_UPDATE' then
     local ak = C_ArtifactUI.GetArtifactKnowledgeMultiplier()
@@ -196,6 +220,14 @@
       end
       self:Refresh()
     end
+  elseif event == 'SUPER_TRACKED_QUEST_CHANGED' then
+    if superTrackedQuestID and db.QuestsByID[superTrackedQuestID] then
+      db.QuestsByID[superTrackedQuestID].isStale = true
+    end
+    local newID = GetSuperTrackedQuestID()
+    if newID and db.QuestsByID[newID] then
+      db.QuestsByID[newID].isStale = true
+    end
   end
 end
 
@@ -253,14 +285,14 @@
   end
 
   if (not pin.dataLoaded) then
-    pin:GetData()
+    local dataLoaded = pin:GetData()
+    isDataLoaded = (isDataLoaded and dataLoaded)
     WorldPlan.dataFlush = true
   end
 
   pin.isActive = TQ_IsActive(questID)
 
   pin:CheckFilterRules()
-  pin.isStale = true
   rprint(pin:GetID(), pin.filtered, pin.used)
 
   return pin
@@ -475,6 +507,8 @@
   print('|cFFFFFF00'..self:GetName()..':Cleanup()|r')
   rprint('|cFFFFFF00'..self:GetName()..':Cleanup()|r')
   --local showQuestPOI = db.Config.EnablePins
+  numShown = 0
+  numLoaded = 0
   for questID, pin in pairs(db.QuestsByID) do
     local oV = pin:IsShown()
     if pin.used then
@@ -483,6 +517,11 @@
         print('|cFF00FF00cleanup +|r', questID, pin.title)
       end
       pin:SetShown(true)
+      numShown = numShown + 1
+      if pin.dataLoaded then
+        numLoaded = numLoaded + 1
+      end
+
     else
       if oV == true then
         print('|cFFFF4400 -|r', questID, pin.title)
@@ -491,6 +530,11 @@
     end
   end
 
+  if numShown > numLoaded then
+    self.Status:Show()
+  end
+
+
   self.isStale = nil
   self.sizesDirty = nil
 end
@@ -517,17 +561,13 @@
   rprint('|cFF00FF00update|r', pin.questID, pin.title)
 
   if x and y then
-    pin.x = x
-    pin.y = y
     pin:SetFrameLevel(PinBaseIndex+pin:GetID())
     pin.owningFrame = WorldMapFrame
-    pin:SetAnchor(WorldMapPOIFrame, pin.x, pin.y, self.hostWidth, self.hostHeight)
+    pin:SetAnchor(WorldMapPOIFrame, x, y, self.hostWidth, self.hostHeight)
     --tinsert(self.UsedPositions, pin)
   end
-  if self:IsVisible() then
+  if self:IsVisible() and pin.isStale then
     pin:Refresh()
-  else
-    pin.isStale = true
   end
   if mapID then
     if not db.QuestsByZone[mapID] then
@@ -545,6 +585,7 @@
 end
 
 function Module:UpdateAnchors ()
+
   wipe(self.UsedPositions)
   print('  |cFF00FF00'..self:GetName()..':UpdateAnchors()')
   self.hostWidth, self.hostHeight = WorldMapPOIFrame:GetSize()
@@ -556,7 +597,8 @@
   if isMicroDungeon then
     return
   end
-
+  -- starts as true
+  isDataLoaded = true
 
   numPins = 0
   local taskInfo = TQ_GetQuestsForPlayerByMapID(self.currentMapID)
@@ -575,4 +617,3 @@
   end
 end
 
-