view Modules/ArtifactPower.lua @ 99:74d6d97a2d24 v7.1.5-r100

- artifact progress visualizations, green for current, blue for attainable - force fishing artifact to list last - support for fishing artifact power
author Nenue
date Fri, 20 Jan 2017 19:40:55 -0500
parents dadddb8a551f
children f32b63c93275
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 = {
  numItems = 0,
  Tokens = {},
  ItemButtons = {},
  anchorPoint = 'TOP',
  anchorFrom = 'TOP',
}
local ap = VeneerArtifactPowerMixin
local BAGS_TO_SCAN = {BACKPACK_CONTAINER }
local TOOLTIP_NAME = 'VeneerAPScanner'
local POINT_COSTS = {
  100, 300, 325, 350, 375,
  400, 425, 450, 525, 625,
  750, 875, 1000, 6840, 8830,
  11280, 14400, 18620, 24000, 30600,
  39520, 50880, 64800, 82500, 105280,
  138650, 182780, 240870, 325520, 417560,
  546000, 718200, 946660, 1245840, 1635200,
  191500, 2010000, 2110000, 2215000, 2325000,
  2440000, 2560000, 2690000, 2825000, 2965000,
  3115000, 3270000, 3435000, 3605000, 3785000,
  3975000, 4175000, 4385000, 4605000
}

local FRAME_LIST = {'ContainerFrame1', 'BankFrame'}
local BAG_FRAMES = {'ContainerFrame1'}
local BANK_FRAMES = {'BankFrame'}

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_XP_UPDATE') -- when artifact xp has changed (but not necessarily data)
  self:RegisterEvent('PLAYER_REGEN_ENABLED')
  self:RegisterEvent('PLAYER_REGEN_DISABLED')
  self:RegisterEvent('PLAYER_ENTERING_WORLD')
  Veneer:AddHandler(self, self.anchorPoint, true)
  SLASH_VENEER_AP1 = "/vap"
  SLASH_VENEER_AP2 = "/veneerap"
  SlashCmdList.VENEER_AP = function(arg)
    if arg == 'fishing' then
      if VeneerData.ArtifactPower.EnableFishing then
        VeneerData.ArtifactPower.EnableFishing = nil
      else
        VeneerData.ArtifactPower.EnableFishing = true
      end
      self:Print('Show Underlight Angler:', (VeneerData.ArtifactPower.EnableFishing and 'ON' or 'OFF'))
      self:Update()

    else
      self:Show()
    end
  end

  self.tooltip = CreateFrame('GameTooltip', TOOLTIP_NAME, self, 'GameTooltipTemplate')
  tinsert(UISpecialFrames, self:GetName())


end

local addonCompatibility = {
  ['Bagnon'] = {
    BagFrames = {'BagnonFrameinventory'},
    BankFrames = {'BagnonFramebank'},
    PostHooks = {'ToggleAllBags', 'ToggleBackpack' },
    MethodClass = 'Bagnon',
    MethodHooks = {'BANK_OPENED', 'BANKFRAME_CLOSED'}
  }
}


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.updateSummary = true

  local DoTryToShow = function()
    self:TryToShow()
  end
  hooksecurefunc("OpenBackpack", DoTryToShow)
  hooksecurefunc("CloseBackpack", DoTryToShow)

  -- Bagnon compatibility
  -- todo: ArkInventory, Elv, etc
  for addon, args in pairs(addonCompatibility) do
    if IsAddOnLoaded(addon) then
      for _, name in ipairs(args.BagFrames) do
        tinsert(FRAME_LIST, name)
        tinsert(BAG_FRAMES, name)
      end
      for _, name in ipairs(args.BankFrames) do
        tinsert(FRAME_LIST, name)
        tinsert(BAG_FRAMES, name)
      end
      for _, name in ipairs(args.PostHooks) do
        local oFunc = _G[name]
        _G[name] = function(...)
          print('|cFFFF0088' .. name .. '|r', ...)
          oFunc(...)
          self:TryToShow()
        end
      end
      local frame = _G[args.MethodClass]
      if frame then
        for _, name in ipairs(args.MethodHooks) do
          hooksecurefunc(frame, name, DoTryToShow)
        end
      end
    end
  end
end

local UNDERLIGHT_ANGLER_ID = 133755
function ap:SetArtifact(itemID, name, texture, currentXP, pointsSpent)
  print('|cFF00FF00SetArtifact()|r')
  if not self.profile then
    return
  end
  local artifacts = self.profile.artifacts


  if itemID then

    self.currentEquipped = itemID

    artifacts[itemID] = artifacts[itemID] or {}
    table.wipe(artifacts[itemID])
    local artifact = artifacts[itemID]

    artifact.name = name
    artifact.texture = texture
    artifact.currentXP = currentXP
    artifact.level = pointsSpent
    local cost = C_ArtifactUI.GetCostForPointAtRank(pointsSpent)
    artifact.cost = cost

    local pointsAvailable = pointsSpent
    local actualCost = cost
    local actualXP = currentXP
    while actualXP >= actualCost do
      pointsAvailable = pointsAvailable + 1
      actualXP = actualXP - actualCost
      print(pointsAvailable, '-', actualCost, '=', actualXP)
      actualCost = C_ArtifactUI.GetCostForPointAtRank(pointsAvailable)
    end
    print('updating', itemID, name,  currentXP, pointsSpent, pointsAvailable, actualXP)
    artifact.actualXP = actualXP
    artifact.actualLevel = pointsAvailable
    artifact.actualCost = actualCost

  end
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:Reanchor()
  if Veneer then
    Veneer:DynamicReanchor()
  end
end

function ap:OnShow()
  print('|cFFFFFF00OnShow()|r')
  self.enabled = true
  self:ScanAllBags()
  self:Reanchor()
  if not self.postShowSetup then
    self.postShowSetup = true
    hooksecurefunc("HideUIPanel", function() self:TryToShow() end)
  end
end
function ap:OnHide()
  print('|cFF88FF00OnHide()|r')
  self:Reanchor()
end
function ap:OnEnter()

  GameTooltip:SetOwner(self, 'ANCHOR_CURSOR')


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

end

function ap:TryToShow()

  print('|cFFFFFF00TryToShow()')

  if not InCombatLockdown() then
    for _, name in ipairs(FRAME_LIST) do
      --print(name, (_G[name] and _G[name]:IsShown()))
      if _G[name] and _G[name]:IsShown() then
        if self:IsShown() then
          self:Update()
        else
          self:Show()
        end
        return
      end
    end
  end


  self:Hide()
end


function ap:OnEvent(event, ...)
  print('|cFF00FF88OnEvent()', event, ...)
  if event == 'PLAYER_ENTERING_WORLD' then
    self:TryToShow()
  elseif event == 'BAG_UPDATE' then
    local containerID = ...
    self:QueueBag(containerID)
  elseif event == 'PLAYER_BANKSLOTS_CHANGED' then
    self:ScanAllBags()
  elseif event == 'BAG_UPDATE_DELAYED' then
    if not self.firstHit then
      self.firstHit = true
    else
      self:ScanAllBags()
    end
  elseif event == 'BANKFRAME_OPENED' then
    self.bankAccess = true
    self:ScanAllBags()
  elseif event == 'BANKFRAME_CLOSED' then
    self.bankAccess = nil
  elseif event == 'ARTIFACT_UPDATE' then
    local newItem = ...
    if newItem then
      local itemID, _, name, texture, currentXP, pointsSpent = C_ArtifactUI:GetArtifactInfo()
      self:SetArtifact(itemID, name, texture, currentXP, pointsSpent)
      self:ScanAllBags(self.bankAccess)
    end
  elseif event == 'ARTIFACT_XP_UPDATE' then
    local itemID, _, name, texture, currentXP, pointsSpent = C_ArtifactUI:GetEquippedArtifactInfo()
    self:SetArtifact(itemID, name, texture, currentXP, pointsSpent)
    self:ScanAllBags(self.bankAccess)
  elseif event == 'PLAYER_REGEN_ENABLED' then
    if self.enabled then
      if self.queuedScan then
        self:ScanAllBags(self.backAccess)
      else
        self:TryToShow()
      end
    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
    print('|cFFFF4400Update()|r')
    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
    if (self.bagAP + self.bankAP) == 0 then
      bankText = '|cFFFF4400No Artifact Power tokens on hand|r'
    else
      if self.bagAP and (self.bagAP > 0) then
        bankText = '|cFFFFFFFF' .. tostring(self.bagAP) .. '|r'
      end
      if self.bankAP and (self.bankAP > 0) then
        bankText = (bankText and (bankText .. ' | ') or '') .. '|cFFFFFF00'..tostring(self.bankAP)..'|r'
      end
    end
  end
  if self.fishingAP and self.fishingAP >= 1 then
    bankText = (bankText and (bankText .. ' ') or '') .. '|cFF0088FF' .. tostring(self.fishingAP) .. ' fishing AP|r'
  end

  self.SummaryHeader:SetText(bankText)

  -- Artifact icons, in no particular order
  self.equippedID = C_ArtifactUI.GetEquippedArtifactInfo()
  local numButtons = 0
  local lastFrame = self
  local fishingID, fishingData
  local index, button
  for itemID, artifact in pairs(self.profile.artifacts) do
    if (itemID == UNDERLIGHT_ANGLER_ID)  then
      if VeneerData.ArtifactPower.EnableFishing then
        fishingID = itemID
        fishingData = artifact
      end

    else
      numButtons = numButtons + 1
      button = self.Artifact[numButtons]
      button.relativeFrame = lastFrame
      lastFrame = button:SetButton(itemID, artifact, numButtons, (self.equippedID == itemID))
    end

  end

  if fishingData then
    numButtons = numButtons + 1
    local button = self.Artifact[numButtons]
    button.relativeFrame = lastFrame
    button:SetButton(fishingID, fishingData, numButtons, self.equippedID == fishingID)
  end

  for i = numButtons+ 1, #self.Artifact do
    print('hide', i)
    self.Artifact[i]:Hide()
  end

  self:UpdateItemButtons()


  self:SetWidth(64*numButtons + 4 * (numButtons+1))
  self:SetHeight(12 + self.SummaryHeader:GetHeight() + 64)
  self:Reanchor()

end


function ap:UpdateItemButtons()
  print('|cFF00FFFFUpdateItemButtons()|r')
  local lastFrame, upFrame
  local numButtons = 0
  for index, button in ipairs(self.Tokens) do
    if button.numItems >= 1 then
      if button.itemName then
        self:SetItemAction(button)
      end

      button:ClearAllPoints()
      numButtons = numButtons + 1
      print(index, button:GetID(), button.Icon:GetTexture())
      if numButtons == 1 then
        button:SetPoint('TOPLEFT', self, 'BOTTOMLEFT', 0, -2)
        upFrame = button
      elseif mod(numButtons,8) == 1 then
        button:SetPoint('TOPLEFT', upFrame, 'BOTTOMLEFT', 0, -2)
        upFrame = button
      else
        button:SetPoint('TOPLEFT', lastFrame, 'TOPRIGHT', 2, 0)
      end
      button.Count:SetText(button.numItems)
      lastFrame = button
      button:Show()
    else

      button:Hide()
    end

  end

end

function ap:SetItemAction(button, name)
  name = name or self.itemName
  if InCombatLockdown() then
    self.itemName = name
    return
  else
      button:SetAttribute('*type*','item')
    button:SetAttribute('*item*', name)
  end
end

function ap:GetItemButton(itemID, texture, itemAP)
  print('|cFF00FFFFGetItemButton()|r', itemID, texture, itemAP)
  local button = self.ItemButtons[itemID]
  if not button then
    button = CreateFrame('Button', 'VeneerAPToken'..itemID, self, 'VeneerItemButton')
    button:SetPushedTexture([[Interface\Buttons\UI-Quickslot-Depress]])
    button:SetHighlightTexture([[Interface\Buttons\ButtonHilight-Square]],"ADD")
    button:SetID(itemID)
    button.numItems = 0
    button.Icon:SetTexture(texture)
    button.Label:SetText(itemAP)
    button:RegisterForClicks("AnyUp")
    self:SetItemAction(button, GetItemInfo(itemID))

    print('  created')
    self.ItemButtons[itemID] = button
    self.numItems = self.numItems +  1
  end

  button.numItems = button.numItems + 1
  return button
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
  bagData.fishingAP = 0
  bagData.items = bagData.items or {}
  table.wipe(bagData.items)

  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
                requiresUpdate = true
                bagData.numItems = (bagData.numItems or 0) + 1
                bagData.totalAP = (bagData.totalAP or 0) + itemAP
                bagData.items[itemID] = (bagData.items[itemID] or 0) + 1


                local itemButton = self:GetItemButton(itemID, texture, itemAP)
              end
            end
          end
        end
        local fishingText = _G[TOOLTIP_NAME .. 'TextLeft3']:GetText()
        if fishingText and fishingText:match('fishing artifact') then
          local fishingAP = fishingText:match("%d+")
          fishingAP = tonumber(fishingAP)
          if fishingAP then
            bagData.fishingItems = (bagData.fishingItems or 0) + 1
            bagData.fishingAP = (bagData.fishingAP or 0) + fishingAP
            bagData.items[itemID] = (bagData.items[itemID] or 0) + 1
            local itemButton = self:GetItemButton(itemID, texture, fishingAP)
            print(fishingAP, bagData.fishingAP)
          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

end

local BAG_SLOTS = {0, 1, 2, 3, 4 }
local BANK_SLOTS = {-1, 5, 6,7, 8, 9, 10, 11, 12}
local ItemCounts = {}
function ap:ScanAllBags()
  if InCombatLockdown() then
    self.queuedScan = true
    return
  end
  self.queuedScan = nil

  print('|cFFFF0088ScanAllBags()|r')

  for _, button in ipairs(self.Tokens) do
    button.numItems = 0
  end


  for _, bagID in ipairs(BAG_SLOTS) do
    self:ScanBag(bagID)
  end

  if self.bankAccess then
    for _, bagID in ipairs(BANK_SLOTS) do
      self:ScanBag(bagID)
    end
  end

  self.bankAP = 0
  self.bagAP = 0
  self.fishingAP = 0

  table.wipe(ItemCounts)
  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
    if bagData.fishingAP then
      self.fishingAP = self.fishingAP + bagData.fishingAP
    end

  end
  self.lastUpdate = GetTime()
  self:TryToShow()
end

VeneerArtifactButtonMixin = {}

function VeneerArtifactButtonMixin:SetButton(itemID, artifact, index, equipped)
  print(itemID, index)
  print(artifact.name, artifact.texture, artifact.currentXP)
  self:SetID(itemID)
  for k,v in pairs(artifact) do
    --print('::',k,v)
    self[k] = v
  end

  -- this can change between artifact parses
  local potentialPoints = self.actualLevel
  local totalAP = (itemID ~= UNDERLIGHT_ANGLER_ID) and ((self:GetParent().bankAP or 0) + (self:GetParent().bagAP or 0)) or (self:GetParent().fishingAP or 0)
  print(totalAP)
  local potentialXP = self.actualXP + totalAP

  self.potentialXP = potentialXP
  local potentialCost = C_ArtifactUI.GetCostForPointAtRank(potentialPoints)
  while potentialXP >= potentialCost do
    potentialXP = potentialXP - potentialCost
    potentialPoints = potentialPoints + 1
    print('inc estimate', potentialXP, potentialPoints)
    potentialCost = C_ArtifactUI.GetCostForPointAtRank(potentialPoints)
  end
  self.potentialCost = potentialCost
  self.potentialLevel = potentialPoints
  self.potentialAdjustedXP = potentialXP


  if index ~= 1 then
    self:ClearAllPoints()
    self:SetPoint('TOPLEFT', self.relativeFrame, 'TOPRIGHT', 4, 0)
  else
    self:ClearAllPoints()
    self:SetPoint('TOPLEFT', self.relativeFrame, 'TOPLEFT', 4, -4)
  end

  self.isEquipped = equipped
  self:Update()
  self:Show()
  return self
end

function VeneerArtifactButtonMixin:Update()

  local r, g, b = 1, 1, 1
  local lR, lG, lB = 1, 1, 0
  local levelText = self.level
  local xpValue = self.currentXP
  local costValue = self.cost
  if self.actualLevel ~= self.level then
    levelText, r,g,b = self.actualLevel, 0,1,0
    xpValue, costValue, lR, lG, lB = self.actualXP, self.actualCost, 0, 1, 0
  elseif self.potentialLevel ~= self.level then
    levelText, r, g, b = self.potentialLevel, 0,1,1
    xpValue, costValue, lR, lG, lB = self.potentialAdjustedXP, self.potentialCost, 0,1,0

  end

  if xpValue >= 100000 then
    xpValue = tostring(floor(xpValue/1000))..'k'
  elseif xpValue > 1000 then
    xpValue = tostring(floor(xpValue/100)/10)..'k'
  end
  if costValue >= 100000 then
    costValue = tostring(floor(costValue/1000))..'k'
  elseif costValue >= 1000 then
    costValue = tostring(floor(costValue/100)/10)..'k'
  end


  self.Level:SetText(levelText)
  self.Level:SetTextColor(r, g, b)
  self.CurrentXP:SetText(xpValue)
  self.CurrentXP:SetTextColor(lR, lG, lB)

  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

  local currentProgress = (self.currentXP < self.cost) and (self.currentXP / self.cost) or 1
  if self.level <= 53 then

    self.CurrentProgress.animateFrom = self.CurrentProgress:GetHeight() or 1
    self.CurrentProgress.animateTo = currentProgress * self:GetHeight()
    self.CurrentProgress:Show()
  else
    self.CurrentProgress:Hide()
  end

  if self.potentialXP > self.currentXP then
    local projectedProgress = (self.potentialAdjustedXP < self.potentialCost) and (self.potentialXP / self.potentialCost) or 1

    if (projectedProgress > currentProgress) then
      self.AdjustedProgress:SetPoint('BOTTOM', self.CurrentProgress, 'TOP')
      projectedProgress = projectedProgress - currentProgress

    else
      self.AdjustedProgress:SetPoint('BOTTOM', self, 'BOTTOM')
    end
    print('show potential', currentProgress, projectedProgress)
    self.AdjustedProgress.animateFrom = self.AdjustedProgress:GetHeight() or 1
    self.AdjustedProgress.animateTo = projectedProgress * self:GetHeight()

    self.AdjustedProgress:Show()
  else
    self.AdjustedProgress:Hide()
  end


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


function VeneerArtifactButtonMixin:AnimateProgress(region)
  local cTime = GetTime()
  if not region.animateStart then
    region.animateStart = cTime
  end
  local progressTo, progressFrom = region.animateTo, region.animateFrom
    local elapsed = cTime - region.animateStart
  if elapsed >= .5 then
    region:SetHeight(progressTo)
    region.animateTo = nil
    region.animateStart = nil
    region.animateFrom = nil
  else
    local progress = elapsed / .5
    local height = (progressFrom + (progressTo - progressFrom) * progress)
    --print(self:GetName(), progressTo, progressFrom, (progressTo - progressFrom), ceil(progress*10)/10, ceil(height))
    region:SetHeight(height)
  end
end

function VeneerArtifactButtonMixin:OnUpdate(sinceLast)
  if self.CurrentProgress.animateTo then
    self:AnimateProgress(self.CurrentProgress)
  end

  if self.AdjustedProgress.animateTo then
    self:AnimateProgress(self.AdjustedProgress)
  end

end

function VeneerArtifactButtonMixin:OnEnter()
  GameTooltip:SetOwner(self, 'ANCHOR_CURSOR')
  GameTooltip:SetText(self.name)
  GameTooltip:AddLine(tostring(self.currentXP) .. ' / '..tostring(self.cost), 1, 1, 0)
  if self.potentialXP > self.currentXP then
    GameTooltip:AddLine(tostring(self.potentialXP) .. ' potential XP', 0, 1, 1)
    if self.potentialAdjustedXP ~= self.potentialXP then
      GameTooltip:AddLine(tostring(self.potentialAdjustedXP) .. ' / ' .. tostring(self.potentialCost).. ' after', 0, 1, 0)
    end
  end
  if self.actualLevel ~= self.level then
    GameTooltip:AddLine(tostring(self.actualLevel - self.level) .. ' points unlocked', 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