view Modules/BuffFrame.lua @ 129:9f2cf5609420 v7.3.0-20171022

- fix Argus world quests not being counted - add "Argus WQ" header in the summary box
author Nenue
date Sun, 22 Oct 2017 18:28:43 -0400
parents ea2c616a3b4f
children 414e37af1b1b
line wrap: on
line source
-- Veneer
-- BuffFrame.lua
-- Created: 7/27/2016 8:08 PM
-- %file-revision%
--[[
  Adds progress bars and cooldown swirls to buffbutton frames

  Known Limitations:
  - Individual BuffButton frames are created upon use, making it difficult to do any sort of securestate priming
  - TempEnchant info returns relative values only, and they don't synchronize with aura events
  - BuffButtons can only be hidden/shown by blizzcode, so functions doing that have to be accounted for
--]]

local BUFFS_PER_ROW = 12
local BUFF_BUTTON_SIZE = 48
local BUFF_BUTTON_SPACING_H = 5
local BUFF_BUTTON_SPACING_V = 14
local BUFF_PROGRESS_SIZE = 4
local BUFF_PROGRESS_INSET = 2
local PROGRESS_ANCHOR = 'BOTTOM'
local PROGRESS_PARENT
local PROGRESS_OFFSET = 1
local BUFF_MAX_DISPLAY = 24
local DEBUFF_MAX_DISPLAY = 12

local BUFF_BUTTON_ZOOM = .15
local BORDER_SIZE_L = 2
local BORDER_SIZE_R = 2
local BORDER_SIZE_U = 2
local BORDER_SIZE_D = 2
local BUFF_FRAMES_X = -230
local BUFF_FRAMES_Y = -4

local COUNT_ANCHOR = 'TOPRIGHT'
local COUNT_INSET = 4
local COUNT_PARENT

local DURATION_ANCHOR = 'BOTTOMLEFT'
local DURATION_INSET = 1
local DURATION_PARENT

VeneerBuffFrameMixin = {
  moduleName = 'Buff Frames',
  anchorPoint = 'TOPRIGHT',
  anchorX = BUFF_FRAMES_X,
  anchorY = BUFF_FRAMES_Y,

  Buttons = {},
  DetectedFrames = {},
  AuraCache = {},
  ValueMasks = {}
}
VeneerBuffFrameButtonMixin = {}
local Facade = VeneerBuffFrameButtonMixin
local plugin = VeneerBuffFrameMixin

local vn = Veneer
local print = DEVIAN_WORKSPACE and function(...) _G.print('BuffFrame', ...) end or function() end
local tprint = DEVIAN_WORKSPACE and function(...) _G.print('Timer', ...) end or function() end

local _G, UIParent = _G, UIParent
local tinsert, tremove, unpack, select, tconcat = table.insert, table.remove, unpack, select, table.concat
local floor, tonumber, format = math.floor, tonumber, string.format
local UnitAura, GetTime, CreateFrame =  UnitAura, GetTime, CreateFrame
local hooksecurefunc = hooksecurefunc

local aurasCache = {}
local skinnedFrames = {}
local pendingFrames = {}
local veneers = {}
local expirationCache = {}
local visibility = {}
local isHooked = {}
local valueMasks

plugin.options = {
  nameString = 'Buff Frames',
  {
    name = 'BuffButtonZoom',
    type = 'slider',
    min = 0,
    max = 100,
    fullwidth = true,
  },
  {
    name = 'BuffBorderLeft',
    type = 'slider',
    min = 0,
    max = 16,
  },
  {
    name = 'BuffBorderLeft',
    type = 'slider',
    min = 0,
    max = 16,
  }
}

local OFFSET_PARALLELS = {
  TOP = {'LEFT', 'RIGHT', 'SetHeight'},
  BOTTOM = {'LEFT', 'RIGHT', 'SetHeight'},
  LEFT = {'TOP', 'BOTTOM', 'SetWidth'},
  RIGHT = {'TOP', 'BOTTOM', 'SetWidth'},
}
local ANCHOR_OFFSET_POINT = {
  TOP = 'BOTTOM',
  TOPLEFT = 'BOTTOMRIGHT',
  TOPRIGHT = 'BOTTOMLEFT',
  LEFT = 'RIGHT',
  RIGHT = 'LEFT',
  CENTER = 'CENTER',
  BOTTOM = 'TOP',
  BOTTOMRIGHT = 'TOPLEFT',
  BOTTOMLEFT = 'TOPRIGHT',
}
local ANCHOR_INSET_DELTA = {
  TOP = {0, -1},
  TOPLEFT = {1, -1},
  TOPRIGHT = {-1,-1},
  LEFT = {1, 0},
  BOTTOMLEFT = {1, 1},
  BOTTOM = {0, 1},
  BOTTOMRIGHT = {-1, 1},
  RIGHT = {-1, 0},
  CENTER = {0, 0},
}

-- Associates skinning elements with said button
local surrogates = {
  ['Show'] = false,
  ['Hide'] = false,
  ['SetText'] = false,
  ['SetVertexColor'] = function(self, region, r, g, b, a)
    if not self.progress then
      return
    end

    region:Hide()
    --tprint('|cFF0088FFborder:SetVertexColor|r', r,g,b,a)
    self.progress.fg:SetColorTexture(r,g,b,a)
    self.border:SetColorTexture(r,g,b,a)
    self.border:Show()
  end,
}
local DoRegionHooks =  function (veneer, region)

  if region then
    --print('hooking', region:GetName())
    region:ClearAllPoints()
    for method, callback in pairs(surrogates) do
      if type(region[method]) == 'function' then

        --print(method, type(callback))
        local func
        if callback then
          hooksecurefunc(region, method, function(self, ...)
            --tprint('|cFF00FFFF'.. region:GetName().. ':', method)
            region:ClearAllPoints()
            callback(veneer, region, ...)
          end)
        else
          hooksecurefunc(region, method, function(self,...)
            --tprint('|cFF0088FF'.. self:GetName().. ':', method)
            self:ClearAllPoints()
            veneer:Show()
            veneer[method](veneer, ...)

            if self:GetName():match('Debuff.+Count') then

              --print('|cFF00FFFF'.. self:GetName().. ':'.. method, '->', veneer:GetName()..':'..method..'(', ...,')')
              --print(veneer:IsVisible(),veneer:GetStringWidth(),veneer:GetText())
              --print(veneer:GetTop(), veneer:GetLeft())
              --print(veneer:GetPoint(1))
            end

          end)
        end
      end
    end
  end
end



function Facade:OnShow()
  print(self:GetName(), 'OnShow')
  self.underlay:Show()
end
function Facade:OnHide()

  print(self:GetName(), 'OnHide')
  self.underlay:Hide()

end

function Facade:OnLoad()

  self.duration = self.progress.duration
  self.count = self.overlay.count
  self.border = self.underlay.bg

  VeneerBuffFrame.ConfigLayers = VeneerBuffFrame.ConfigLayers or {}
  self.configIndex = #VeneerBuffFrame.ConfigLayers
  for i, region in ipairs(self.ConfigLayers) do
    tinsert(VeneerBuffFrame.ConfigLayers, region)
  end

  self.configIndexEnd = #VeneerBuffFrame.ConfigLayers
end

function Facade:Setup()
  self:SetSize(BUFF_BUTTON_SIZE,BUFF_BUTTON_SIZE)

  self.progress[OFFSET_PARALLELS[PROGRESS_ANCHOR][3]](self.progress, BUFF_PROGRESS_SIZE + (BUFF_PROGRESS_INSET * 2))
  --print(BUFF_PROGRESS_SIZE + (BUFF_PROGRESS_INSET * 2))

  self.progress:ClearAllPoints()
  self.progress:SetPoint(ANCHOR_OFFSET_POINT[PROGRESS_ANCHOR], PROGRESS_PARENT or self.border, PROGRESS_ANCHOR,
    (ANCHOR_INSET_DELTA[PROGRESS_ANCHOR][1] * PROGRESS_OFFSET * -1),
    (ANCHOR_INSET_DELTA[PROGRESS_ANCHOR][2] * PROGRESS_OFFSET * -1))
  self.progress:SetPoint(OFFSET_PARALLELS[PROGRESS_ANCHOR][1], self.border, OFFSET_PARALLELS[PROGRESS_ANCHOR][1], 0, 0)
  self.progress:SetPoint(OFFSET_PARALLELS[PROGRESS_ANCHOR][2], self.border, OFFSET_PARALLELS[PROGRESS_ANCHOR][2], 0, 0)

  --print(self.progress:GetPoint(1))
  --print(self.progress:GetPoint(2))
  --print(self.progress:GetPoint(3))
  self.progress:Show()

  self.progress.bg:ClearAllPoints()
  self.progress.bg:SetAllPoints(self.progress)

  self.progress.fg:ClearAllPoints()
  self.progress.fg:SetPoint('BOTTOMLEFT', BUFF_PROGRESS_INSET,BUFF_PROGRESS_INSET)
  self.progress.fg:SetPoint('TOP', 0, -BUFF_PROGRESS_INSET)
  --self.count:ClearAllPoints()
  --self.count:SetPoint('TOPRIGHT', self,'TOPRIGHT', -3, -3)


  self.duration:ClearAllPoints()
  self.duration:SetPoint(DURATION_ANCHOR, DURATION_PARENT or self, DURATION_ANCHOR,
    (ANCHOR_INSET_DELTA[DURATION_ANCHOR][1] * DURATION_INSET),
    (ANCHOR_INSET_DELTA[DURATION_ANCHOR][2] * DURATION_INSET))

  self.count:ClearAllPoints()
  self.count:SetPoint(COUNT_ANCHOR, COUNT_PARENT or self, COUNT_ANCHOR,
    (ANCHOR_INSET_DELTA[COUNT_ANCHOR][1] * COUNT_INSET),
    (ANCHOR_INSET_DELTA[COUNT_ANCHOR][2] * COUNT_INSET))

  self.underlay:SetParent(UIParent)

  self.underlay:SetFrameStrata('BACKGROUND')
  self.border:SetColorTexture(0,0,0,1)
  self.border:SetPoint('TOPLEFT', self, 'TOPLEFT', -BORDER_SIZE_L, BORDER_SIZE_U)
  self.border:SetPoint('BOTTOMRIGHT', self, 'BOTTOMRIGHT', BORDER_SIZE_R, -BORDER_SIZE_D)
  self.border:Show()

  -- play nice with Blizzard's frame locking structure
  FRAMELOCK_STATES.PETBATTLES[self:GetName()] = "hidden"
  FRAMELOCK_STATES.PETBATTLES[self.underlay:GetName()] = "hidden"
end

plugin.defaultSettings = {
    width = 48,
    height = 48,
}

function plugin:AcquireConfigButton(name)
  print('|cFF88FF00Creating config dummy', name,'Veneer')
  local button = self.Buttons[name]
  if not button then
    button = CreateFrame('Frame', name .. 'Veneer', self, 'VeneerBuffTemplate')
    button:Setup()
    button:SetShown(true)
    self.Buttons[name] = button
  end
  return button
end

function plugin:Acquire(name)
  local frame = self.Buttons[name]
  if not frame then
    local target = _G[name]
    local id = target:GetID()
    print('|cFF88FF00Creating', name .. 'Veneer')
    frame = vn:Acquire(target, 'VeneerBuffTemplate')
    frame:Setup()
    self.Buttons[name] = frame
  end
  return frame
end

function plugin:OnLoad()
  print(self:GetName(), 'OnLoad()')
  Veneer:AddHandler(self)
end

function plugin:Setup()
  print(self:GetName(), 'Setup()')
  hooksecurefunc("BuffFrame_Update", function(...) self:OnBuffFrameUpdate(...) end)
  hooksecurefunc("AuraButton_UpdateDuration", function(...) self:OnUpdateDuration(...) end)
  hooksecurefunc("AuraButton_Update", function(...) self:OnAuraButton_Update(...) end)
  hooksecurefunc("BuffFrame_UpdateAllBuffAnchors", function(...) self:OnUpdateAllBuffAnchors(...) end)
  hooksecurefunc("TemporaryEnchantFrame_Update", function(...) self:OnTemporaryEnchantFrameUpdate(...) end)
  for i = 1, 3 do
    self:SetupButton('TempEnchant'..i)
    _G['TempEnchant'..i..'Border']:SetVertexColor(0.5,0,1,1)
  end

  VeneerData.BuffFrame = VeneerData.BuffFrame or {}
  VeneerData.BuffFrame.ValueMasks = VeneerData.BuffFrame.ValueMasks or {}
  valueMasks = VeneerData.BuffFrame.ValueMasks
end

function plugin:SetHidden(region)
  if not self.hiddenRegions[region] then
    self.hiddenRegions[region] = true
    region:SetShown(false)

  end
end

local lastAuditName = ''
local lastAuditIndex = ''
local Audit_OnClick = function(self)

  local facade = self:GetParent()
  local index = self.index
  local name = facade.buffName
  if name then
    DEFAULT_CHAT_FRAME:AddMessage('|cFF00FFFFVeneer|r: Hiding |cFF00FF88'..name..' value'..index..'|r, type /vn buffs reset to undo.')
    valueMasks[name] = valueMasks[name] or {}
    valueMasks[name][index] = false
    print('AuditClick', name, index, false)
  end
end

function plugin:SetupButton (name)
  local frame = _G[name]
  print('|cFFFFFF00Adopting', name)

  local icon = _G[name .. 'Icon']
  local border = _G[name .. 'Border']
  local count = _G[name .. 'Count']
  local duration = _G[name .. 'Duration']
  local facade = self:Acquire(name)
  local offset = BUFF_BUTTON_ZOOM/2

  self.DetectedFrames[frame] = frame
  frame:SetSize(BUFF_BUTTON_SIZE,BUFF_BUTTON_SIZE)
  icon:SetTexCoord(offset, 1 - offset, offset, 1 - offset)


  DoRegionHooks(facade, border)
  if border then
    local color = DebuffTypeColor["none"]
    if aurasCache[frame] and aurasCache[frame][5] then
      color = DebuffTypeColor[aurasCache[frame][5]]
    end
    facade.progress.fg:SetColorTexture(color.r,color.g,color.b)
    facade.border:SetColorTexture(0,0,0,1)
    facade.border:Show()
  else
    facade.border:SetColorTexture(0,0,0,1)
    facade.border:Show()
  end

  if count then
    count:ClearAllPoints()
    hooksecurefunc(count, 'Show', function(self) self:Hide() end)
    if count:GetText() then
      facade.count:SetText(count:GetText())
    end
  end
  if duration then
    duration:ClearAllPoints()
  end

  hooksecurefunc(frame, "Hide", function(frame)
    facade:Hide()
  end)

  hooksecurefunc(frame, 'Show', function(frame)
    facade:Show()
  end)

  hooksecurefunc(frame, 'SetShown', function(frame, isShown)
    facade:SetShown(isShown)
  end)

  facade.Audit = facade.Audit or {}
  for i = 1, 3 do
    local button = CreateFrame('Button', nil, facade, 'VeneerBuffAuditTemplate')
    button.index = i
    button:RegisterForClicks('AnyUp')
    button:SetScript('OnClick', Audit_OnClick)
    button:SetScript('OnEvent', Audit_OnEvent)
    button:RegisterEvent('POWER_REGEN_ENABLED')
    button:SetPoint('TOPLEFT', 0, (i-1) * 16 * -1)
    facade.Audit[i] = button
  end

  facade.IsAcquired = true
  facade:SetParent(UIParent)
  facade:SetAllPoints(frame)
  facade:SetFrameStrata('MEDIUM')
end


--- Set widgets to reflect the passed parameters
local values = {}
function plugin:UpdateButton (name, duration, expires)
  local frame = _G[name]
  local facade = self:Acquire(name)
  -- is it a new button?
  if not self.DetectedFrames[frame] then
    print('|cFFFF4400detected', name)
    self:SetupButton(name)
  end
  --[[
  if frame.count then
    frame.count:SetText('test')
    frame.count:Show()
  end
    --]]

  local name, rank, icon, count, dispelType, duration, expires, caster, isStealable, nameplateShowPersonal, spellID, canApplyAura, isBossDebuff, _, nameplateShowAll, timeMod, value1, value2, value3 = UnitAura(frame.unit, frame:GetID(), frame.filter)
  values[1] = value1
  values[2] = value2
  values[3] = value3

  facade.buffName = name

  if expires and duration then
    if duration ~= 0 then
      local startTime = (expires - duration)
      local endTime = expires or 0
      print('|cFF0088FF'..frame:GetName()..'|r', duration, expires)
      facade.progress:Show()
      facade.elapsed = 0
      facade.progress:SetScript('OnUpdate', function(self, elapsed)
        facade.elapsed = facade.elapsed + elapsed

        local w = floor(facade.progress:GetWidth()+.5) - (BUFF_PROGRESS_INSET*2)
        local t = GetTime()
        local progress = (t - startTime) / duration

        local nw = (w - (w * progress))
        if facade.elapsed >= 0.25 then

          --tprint(t, startTime, floor(progress*100), w * progress, nw, w)
          facade.elapsed = 0.25 - facade.elapsed
        end
        if (progress >= 1) or not frame:IsVisible() then
          facade.startTime = nil
          self:Hide()
          self:SetScript('OnUpdate', nil)
        else
          self.fg:SetWidth(nw)
        end


      end)

      --facade.cooldown:Show()
      --facade.cooldown:SetCooldown(startTime, duration)
    else
      print('|cFF00FF88'..frame:GetName()..'|r', 'duration zero')
      facade.progress:SetScript('OnUpdate', nil)
      facade.progress:Hide()
      --facade.cooldown:Hide()
    end

    if count and count > 1 then
      facade.count:SetText(count)
      facade.count:Show()
      frame.count:ClearAllPoints()
    else
      facade.count:Hide()
    end

    for i, button in ipairs(facade.Audit) do
      local isShown = (values[i] and true)
      if valueMasks[name] and valueMasks[name][i] ~= nil then
        print(':: use value mask', name, i)
        isShown = (values[i] == 1) and true or false
      end

      facade.Audit[i]:SetShown(isShown)
      facade.Audit[i].Value:SetText(values[i])
    end


  else
    facade.progress:Hide()
    --facade.cooldown:SetCooldown(0,0)
    --facade.cooldown:Hide()
    print('|cFF88FF00'..frame:GetName()..'|r', 'nil duration')
  end
  facade:Show()
end


--- Provides the number of changed indices for use in deciding between partial and full veneer updates
function plugin:ButtonHasChanged (frame, ...)
  aurasCache[frame] = aurasCache[frame] or {}
  local hasChange = 0
  local numVals = select('#',...)
  for i = 1,   numVals do
    local arg = select(i, ...)
    if aurasCache[frame][i] ~= arg then
      hasChange = hasChange + 1
    end
    aurasCache[frame][i] = arg
  end
  return hasChange
end

function plugin:OnAuraButton_Update (name, index, filter)
  local bName = name..index
  local frame = _G[bName]
  if frame and frame:IsShown() then
    -- if the name or expirationTime changed

      if not skinnedFrames[bName] then
        tinsert(pendingFrames, bName)
      end
      expirationCache[name] = frame.expirationTime
      self:UpdateButton(bName)


  end
end

function plugin:OnUpdateAllBuffAnchors ()

  --BuffButton1
  --DebuffButton1
  --todo: separate frame groups and iterate over them at appropriate times
  if BuffButton1 then

    TempEnchant1:SetPoint('TOPRIGHT', BuffButton1, 'TOPRIGHT', BuffButton1:GetWidth()+4, 0)
  end

  local lastBuff, topBuff
  local numBuffs = 0
  local numColumns = 1
  local maxColumn = 1
  local limit = self.configMode and  BUFF_MAX_DISPLAY or BUFF_ACTUAL_DISPLAY
  for i = 1, limit do
    local name = 'BuffButton'..i
    local buff = _G[name] or self.Buttons[name]
    print(i, name, buff)
    if buff then
      numBuffs = numBuffs + 1
      buff:ClearAllPoints()
      if mod(numBuffs,BUFFS_PER_ROW) == 1 then
        if numBuffs == 1 then
          buff:SetPoint('TOPRIGHT', UIParent, 'TOPRIGHT', BUFF_FRAMES_X, BUFF_FRAMES_Y)
          plugin.currentTop = buff
        else
          buff:SetPoint('TOPRIGHT', topBuff, 'BOTTOMRIGHT', 0, -BUFF_BUTTON_SPACING_V)
        end
        numColumns = 1
        topBuff = buff
      else
        buff:SetPoint('TOPRIGHT', lastBuff, 'TOPLEFT', -BUFF_BUTTON_SPACING_H, 0)
        numColumns = numColumns + 1
      end
      if numColumns > maxColumn then
        maxColumn = numColumns
        plugin.currentLeft = buff
      end
      lastBuff = buff
    end
  end

  numBuffs = 0
  limit = self.configMode and DEBUFF_MAX_DISPLAY or DEBUFF_ACTUAL_DISPLAY
  local lastDebuff
  local topDebuff = topBuff
  for i = 1, limit do
    local name = 'DebuffButton'..i
    local debuff = _G[name] or self.Buttons[name]
    print(i, name, debuff)
    if debuff then
      numBuffs = numBuffs + 1
      if mod(numBuffs, BUFFS_PER_ROW) == 1 then

          if topDebuff then
            debuff:SetPoint('TOPRIGHT', topDebuff, 'BOTTOMRIGHT',  0, -BUFF_BUTTON_SPACING_V)
          else
            debuff:SetPoint('TOPRIGHT', UIParent, 'TOPRIGHT', BUFF_FRAMES_X, BUFF_FRAMES_Y)
          end
          topDebuff = debuff

      else
        debuff:SetPoint('TOPRIGHT', lastDebuff, 'TOPLEFT', -BUFF_BUTTON_SPACING_H, 0)
      end
      lastDebuff = debuff

    end
  end

  if lastBuff then
    plugin.currentBottom = lastBuff
  end

  self.Background:ClearAllPoints()
  self.Background:SetPoint('TOPRIGHT', plugin.currentTop, 'TOPRIGHT', 4, 4)
  self.Background:SetPoint('BOTTOM', plugin.currentBottom, 'BOTTOM', 0, -4)
  self.Background:SetPoint('LEFT', plugin.currentLeft, 'LEFT', -4, 0)
end
function plugin:UpdateConfigLayers (configMode)
  self:SetShown(configMode)
  self.configMode = configMode
  for i = 1, BUFF_MAX_DISPLAY do
    local name = 'BuffButton' .. i
    local button = self:AcquireConfigButton(name)
    if not button.IsAcquired then
      button.underlay.bg:SetColorTexture(0,1,0,0.5)
    end
  end
  for i = 1, DEBUFF_MAX_DISPLAY do
    local name = 'DebuffButton' .. i
    local button = self:AcquireConfigButton(name)
    if not button.IsAcquired then
      button.underlay.bg:SetColorTexture(1,0,0,0.5)
    end
  end
  self:OnUpdateAllBuffAnchors()
end
function plugin:OnUpdateDuration (frame, timeLeft)
  local veneer = self:Acquire(frame:GetName())
  local hours =  floor(timeLeft/3600)
  local minutes = floor(mod(timeLeft, 3600)/60)
  local seconds = floor(mod(timeLeft, 60))
  local timeString = '%ds'
  if timeLeft > 3600 then
    timeString = format('%d:%02d', hours, minutes)
  elseif timeLeft > 60 then
    timeString = format('%d:%02d', minutes, seconds)
  else
    timeString = format('%d', seconds)
  end

  if timeLeft < 10 then
    if not veneer.duration.getHuge then
      veneer.duration.getHuge = true
      veneer.duration:SetTextColor(1,.5,0,1)
    end
  else
    if veneer.duration.getHuge then
      veneer.duration.getHuge = nil
      veneer.duration:SetTextColor(1,1,1,1)
    end
  end

  veneer.duration:SetText(timeString)
end


-- Obtains the first instance of Tenchant use

function plugin:OnTemporaryEnchantFrameUpdate (...)
  local numVals = select('#', ...)
  local numItems = numVals / 4
  if numItems >= 1 then
    for itemIndex = numItems, 1, -1 do
      local name = 'TempEnchant'..itemIndex
      local frame = _G[name]
      local hasEnchant, timeRemaining, enchantCharges = select((4 * (itemIndex -1)) + 1, ...)


      if hasEnchant then
        local endTime = floor(GetTime()*1000) + timeRemaining


        --print(endTime)
        if endTime ~= expirationCache[frame] then
          if expirationCache[frame] then
            print(endTime, expirationCache[frame], endTime - expirationCache[frame])
          end
          expirationCache[frame] = endTime
          print('push tempenchant timer update', timeRemaining / 1000, GetTime()+(timeRemaining/1000))
          self:UpdateButton(frame, timeRemaining/1000, GetTime()+(timeRemaining/1000))
        end
      else
        self:Acquire(name):Hide()
      end
    end
  end
end

function plugin:OnBuffFrameUpdate () end


-- The TempEnchant frames are hardcoded in the base FrameXML, so get them now