view Modules/ArtifactPower.lua @ 97:5476337198ec

- apply default anchors when docking modules - Arifact Power tracker: totals AP items in bags and bank, and forecasts progress on each weapon. Requires user to shift-click each weapon at least once to get initial XP data.
author Nenue
date Mon, 16 Jan 2017 20:24:12 -0500
parents
children dadddb8a551f
line wrap: on
line source
-- Veneer
-- ArtifactPower.lua
-- Created: 1/15/2017 11:44 PM
-- %file-revision%
--

local print = DEVIAN_WORKSPACE and function(...) print('VnAP', ...) end or nop
VeneerArtifactPowerMixin = {

  anchorPoint = 'TOP',
  anchorFrom = 'TOP',
}
local ap = VeneerArtifactPowerMixin
local BAGS_TO_SCAN = {BACKPACK_CONTAINER }
local TOOLTIP_NAME = 'VeneerAPScanner'

function ap:OnLoad()
  self:RegisterEvent('BAG_UPDATE') -- use to obtain bag IDs to scan
  self:RegisterEvent('BAG_UPDATE_DELAYED') -- use to trigger actual scan activity
  self:RegisterEvent('BANKFRAME_OPENED')  -- determine when bank info is available
  self:RegisterEvent('BANKFRAME_CLOSED')  -- " " "
  self:RegisterEvent('ARTIFACT_UPDATE')    -- when artifact data has changed
  self:RegisterEvent('ARTIFACT_UPDATE_XP') -- when artifact xp has changed (but not necessarily data)
  self:RegisterEvent('MODIFIER_STATE_CHANGED')
  self:RegisterEvent('PLAYER_REGEN_ENABLED')
  self:RegisterEvent('PLAYER_REGEN_DISABLED')
  Veneer:AddHandler(self, self.anchorPoint, true)
  SLASH_VENEER_AP1 = "/vap"
  SLASH_VENEER_AP2 = "/veneerap"
  SlashCmdList.VENEER_AP = function()
    self:Show()
  end

  self.tooltip = CreateFrame('GameTooltip', TOOLTIP_NAME, self, 'GameTooltipTemplate')

end

local defaultSettings = {
}

function ap:Setup()
  print(self:GetName()..':Setup()')
  local guid = UnitGUID('player')
  VeneerData.ArtifactPower = VeneerData.ArtifactPower or defaultSettings
  VeneerData.ArtifactPower[guid] = VeneerData.ArtifactPower[guid] or {}
  self.profile = VeneerData.ArtifactPower[guid]
  self.profile.bagslots = self.profile.bagslots or {}
  self.profile.artifacts = self.profile.artifacts or {}
  self:GetCurrentArtifact(true)
  self.updateSummary = true

  -- Bagnon compatibility
  -- todo: ArkInventory, Elv, etc
  if IsAddOnLoaded('Bagnon') then
    local oToggleAllBags = ToggleAllBags
    ToggleAllBags =  function()
      print('|cFFFF0088ToggleAllBags')
      oToggleAllBags()
      if BagnonFrameinventory:IsShown() then
        self:Show()
      else
        self.enabled = nil
        self:Hide()
      end
    end
  else
    hooksecurefunc("OpenBackpack", function()
      self:Show()
    end)
    hooksecurefunc("CloseBackpack", function()
      self.enabled = nil
      self:Hide()
    end)
  end


end
local UNDERLIGHT_ANGLER_ID = 133755
function ap:GetCurrentArtifact(newItem)
  if not self.profile then
    return
  end
  local artifacts = self.profile.artifacts
  local itemID, altItemID, name, texture, currentXP, pointsSpent, _, _, artifactAppearanceID, appearanceModID, itemAppearanceID, altItemAppearanceID, altOnTop = C_ArtifactUI:GetArtifactInfo()


  if itemID then




    print('updating', itemID, name,  currentXP, pointsSpent, pointsAvailable, adjustedXP)
    table.wipe(artifacts[itemID])
    artifacts[itemID] = artifacts[itemID] or {}
    artifacts[itemID].name = name
    artifacts[itemID].texture = texture
    artifacts[itemID].currentXP = currentXP
    artifacts[itemID].level = pointsSpent
  end


  self:Update()
end
function ap:QueueBag(containerID)
  containerID = tonumber(containerID)
  if not containerID then
    return
  end

  if not tContains(BAGS_TO_SCAN, containerID) then
    print(' queueing', containerID, type(containerID), #BAGS_TO_SCAN , 'in line')
    BAGS_TO_SCAN[#BAGS_TO_SCAN + 1] = containerID
  end
end

function ap:OnShow()
  self.enabled = true
  self:Update()
  Veneer:DynamicReanchor()
end
function ap:OnHide()
  Veneer:DynamicReanchor()
end

function ap:OnEnter()

  GameTooltip:SetOwner(self, 'ANCHOR_CURSOR')

  GameTooltip:AddLine(self.bagAP)
  GameTooltip:AddLine(self.bankAP)

end

function ap:OnEvent(event, ...)
  print(self:GetName()..':OnEvent()', event, ...)
  if event == 'BAG_UPDATE' then
    local containerID = ...
    self:QueueBag(containerID)
  elseif event == 'PLAYER_BANKSLOTS_CHANGED' then
    self:QueueBag(BANK_CONTAINER)
  elseif event == 'BAG_UPDATE_DELAYED' then
    self:ScanAllBags()
  elseif event == 'BANKFRAME_OPENED' then
    self.bankAccess = true
    self:QueueBag(BANK_CONTAINER)
    for i = 1, GetNumBankSlots() do
      self:QueueBag(i+NUM_BAG_SLOTS)
    end
    self:ScanAllBags()
  elseif event == 'BANKFRAME_CLOSED' then
    self.bankAccess = false
    self:Update()
  elseif event == 'ARTIFACT_UPDATE' then
    self:GetCurrentArtifact(...)
  elseif event == 'ARTIFACT_UPDATE_XP' then
    self:GetCurrentArtifact(...)
    self:Update()
  elseif event == 'MODIFIER_STATE_CHANGED' then
    self:Update()
  elseif event == 'PLAYER_REGEN_ENABLED' then
    if self.enabled then
      self:Show()
    end

  elseif event == 'PLAYER_REGEN_DISABLED' then
    self:Hide()
  end
end

function ap:OnMouseDown()
  self.enabled = nil
  self:Hide()
end

function ap:Update()
  if not self:IsShown() then
    return
  end
  print('|cFF00FFFFUpdate()|r')

  local bankText, bagText
  if not (self.bankAP and self.bagAP) then
    bankText = '|cFFFF0000Open bank frame to count all AP|r '
  else
    bankText = '|cFFFFFFFFAP:|r' .. tostring(self.bagAP + self.bankAP) .. ' |cFFFFFF00('..tostring(self.bankAP)..' banked)|r'
  end
  self.SummaryHeader:SetText(bankText)

  -- Artifact icons, in no particular order
  local equippedID = C_ArtifactUI.GetEquippedArtifactInfo()
  local numButtons = 0
  local lastFrame
  for itemID, artifact in pairs(self.profile.artifacts) do
    print(artifact.name, artifact.texture, artifact.currentXP)
    numButtons = numButtons + 1
    local button = self.Artifact[numButtons]

    button:SetID(itemID)
    for k,v in pairs(artifact) do
      --print('::',k,v)
      button[k] = v
    end


    local pointsAvailable = button.level
    local cost = C_ArtifactUI.GetCostForPointAtRank(pointsAvailable)
    local adjustedXP = button.currentXP
    if itemID ~= UNDERLIGHT_ANGLER_ID then
      adjustedXP = adjustedXP +   (self.bankAP or 0) + (self.bagAP or 0)
      print('not UL angler', adjustedXP)
    else
      print('UL angler', adjustedXP)
    end

    while adjustedXP >= cost do
      pointsAvailable = pointsAvailable + 1
      adjustedXP = adjustedXP - cost
      print(pointsAvailable, '-', cost, '=', adjustedXP)
      cost = C_ArtifactUI.GetCostForPointAtRank(pointsAvailable)
    end
    button.adjustedXP = adjustedXP
    button.actualLevel = pointsAvailable

    button.isEquipped = (equippedID == itemID)
    button.relativeFrame = lastFrame
    button:Update()
    lastFrame = button
    button:Show()
  end
  for i = numButtons+1, #self.Artifact do
    print('hide', i)
    self.Artifact[i]:Hide()
  end



  self:SetWidth(64*3+ 16)
  self:SetHeight(8 + self.SummaryHeader:GetHeight() + 64)
  self:Reanchor()

end

function ap:ScanBag(id)
  print('|cFF00FFFFScanBag()|r', id, IsBagOpen(id), GetContainerNumSlots(id))
  local numSlots = GetContainerNumSlots(id)
  local requiresUpdate
  if numSlots == 0 then
    return nil
  end


  self.profile.bagslots[id] = self.profile.bagslots[id] or {}
  table.wipe(self.profile.bagslots[id])
  local bagData = self.profile.bagslots[id]
  bagData.totalAP = 0
  for slotID = 1, numSlots do
    local texture, count, locked, quality, readable, lootable, link = GetContainerItemInfo(id, slotID)
    local itemID = GetContainerItemID(id, slotID)

    if link then
      self.tooltip:SetOwner(self, 'ANCHOR_NONE')
      self.tooltip:SetHyperlink(link)
      self.tooltip:Show()
      local numLines = self.tooltip:NumLines()
      if numLines >= 3 then
        local subText = _G[TOOLTIP_NAME .. 'TextLeft2']:GetText()
        if subText and subText:match(ARTIFACT_POWER) then
          for i = 3, numLines do
            local text = _G[TOOLTIP_NAME .. 'TextLeft'.. i]:GetText()
            if text and text:match(ARTIFACT_POWER) then
              text = text:gsub('[,%D]', '')
              print(link, '-', tonumber(text))
              local itemAP = tonumber(text)
              if itemAP then
                bagData.numItems = (bagData.numItems or 0) + 1
                bagData.totalAP = (bagData.totalAP or 0) + itemAP
                bagData.items = bagData.items or {}
                if not bagData.items[itemID] then
                  requiresUpdate = true
                  bagData.numUnique = (bagData.numUnique or 0) + 1
                end
                bagData.items[itemID] = (bagData.items[itemAP] or 0) + 1
              end
            end
          end
        end
      end
    end

    if self.profile.artifacts[itemID] then
      print('artfiact weapon', itemID, link, id, slotID)
      self.profile.artifacts[itemID].containerID = id
      self.profile.artifacts[itemID].slotID = slotID
    end

  end

  return requiresUpdate
end

function ap:ScanAllBags()
  print('|cFFFF0088ScanAllBags()|r')

  local bagID = tremove(BAGS_TO_SCAN, 1)
  while bagID do
    self.updateSummary = self:ScanBag(bagID) or self.updateSummary
    bagID = tremove(BAGS_TO_SCAN, 1)
  end

  if self.updateSummary then
    print('tripped updater')
    self.bankAP = 0
    self.bagAP = 0
    for id, bagData in pairs(self.profile.bagslots) do
      print(id, GetBagName(id), bagData.totalAP)
      id = tonumber(id)
      if bagData.totalAP then
        if (id == BANK_CONTAINER) or (id >= 5) then
          self.bankAP = self.bankAP + bagData.totalAP
        else
          self.bagAP = self.bagAP + bagData.totalAP
        end
      end

    end
    self.lastUpdate = GetTime()
    self:Update()
  end
  self.updateSummary = nil
end

VeneerArtifactButtonMixin = {}
function VeneerArtifactButtonMixin:Update()

  if self.actualLevel ~= self.level then
    self.Level:SetText(self.actualLevel)
    self.Level:SetTextColor(0,1,0)
    self.CurrentXP:SetText(self.adjustedXP)
    self.CurrentXP:SetTextColor(0,1,0)
  else
    self.Level:SetText(self.level, 1, 1, 1)
    self.Level:SetTextColor(1,1,1)
    self.CurrentXP:SetText(self.currentXP)
    self.CurrentXP:SetTextColor(1,1,0)
  end

  if self.isEquipped then
    self:SetNormalTexture([[Interface\Buttons\ButtonHilight-Square]])
    self:GetNormalTexture():SetBlendMode('ADD')
    self:GetNormalTexture():SetVertexColor(0,1,0)
  else
    self:SetNormalTexture(nil, 'ADD')
  end

  self:ClearAllPoints()
  if self.relativeFrame then
    self:SetPoint('BOTTOMLEFT', self.relativeFrame, 'BOTTOMRIGHT', 4, 0)
  else
    self:SetPoint('BOTTOMLEFT', 4, 4)
  end



  self.Icon:SetTexture(self.texture)
  self.Name:SetText(self.name)
  self:SetSize(64,64)
end

function VeneerArtifactButtonMixin:OnEnter()
  GameTooltip:SetOwner(self, 'ANCHOR_CURSOR')
  GameTooltip:SetText(self.name)
  GameTooltip:AddLine(self.currentXP, 1, 1, 0)
  if self.adjustedXP ~= self.currentXP then
    GameTooltip:AddLine(self.adjustedXP, 0, 1, 1)
  end


  GameTooltip:Show()
end
function VeneerArtifactButtonMixin:OnLeave()
  if GameTooltip:IsOwned(self) then
    GameTooltip:Hide()
  end
end

function VeneerArtifactButtonMixin:OnClick(button, down)
  if self.isEquipped then
    SocketInventoryItem(16)
  else
    SocketContainerItem(self.containerID, self.slotID)
  end
end