(1) You're doing checkups on tables that may not exist. If you don't intend to add tables for every class and spec, anyone else using your addon that is not a destruction warlock will get errors.
(2) What's the point in your holder frame and not just using the AuraTrack frame you already created to show your auras?
(3) You don't need to upvalue the global environment just to grab a few functions. This process is quick and painless and only happens once on login anyway.
(4) Unless there's a specific reason why you're using a set max of 6 auras, you can use a frame factory / frame pool to spawn your trackers instead of creating them on load. I'll show you an example of how this works with the native implementation already in the UI.
Lua Code:
-- Upvalue variables
local GetSpellInfo = GetSpellInfo;
local UnitAura = UnitAura;
-- Local variables
local size = 40;
local point = {"CENTER", UIParent, "CENTER", 0, -110};
local gap = 2;
local buffIDList = {
["WARLOCK"] = {
[3] = { -- Destruction
235156,
215165,
119899,
},
},
};
-- AuraTrack
local AuraTrack = CreateFrame("Frame", "AuraTrack", UIParent);
AuraTrack.numTotalObjects = 0;
AuraTrack:SetPoint(unpack(point));
AuraTrack:RegisterEvent("ACTIVE_TALENT_GROUP_CHANGED");
AuraTrack:RegisterEvent("PLAYER_LOGIN");
AuraTrack:RegisterEvent("ADDON_LOADED");
AuraTrack:SetScript("OnEvent", function(self, event, ...)
self[event](self, ...);
end);
function AuraTrack:UNIT_AURA(...)
-- Release all the currently active objects
-- See the :ResetTracker function for what it does to individual objects.
self:ReleaseAll();
-- Get the buffs to track for the current spec
-- Assert a table exists for the player's class and spec
local buffIDs = self.buffIDList;
if buffIDs then
-- Iterate over buff IDs
local prevButton;
for i, buffID in pairs(buffIDs) do
local spellName = GetSpellInfo(buffID);
local _, _, icon, count, _, duration, expires = UnitAura(..., spellName);
if duration and duration > 0 then
-- Acquire a button from the object pool
local button = self:Acquire();
-- Assign your stuff
button.spellID = buffID; -- not sure this is necessary with this approach.
button.cd:SetCooldown(expires - duration, duration);
button.icon:SetTexture(icon);
button.count:SetText((count and count > 0) and count or "");
-- Show and set the point for the button
button:Show();
if prevButton then
button:SetPoint("LEFT", prevButton, "RIGHT", gap, 0);
else
button:SetPoint("LEFT");
end
-- Reference this button so the next one knows where to anchor
prevButton = button;
end
end
end
-- Update width to match active objects.
-- numActiveObjects is provided by the object pool mixin.
self:SetSize(((size + gap) * self.numActiveObjects) - gap, size);
end
-- Update spec and the buff table when the spec actually changes
function AuraTrack:ACTIVE_TALENT_GROUP_CHANGED()
local _, class = UnitClass("player");
local spec = GetSpecialization();
self.buffIDList = buffIDList[class] and buffIDList[class][spec];
end
function AuraTrack:ADDON_LOADED(...)
if ... == "MyAuraTracker" then
self.ADDON_LOADED = nil;
self:UnregisterEvent("ADDON_LOADED");
self:RegisterUnitEvent("UNIT_AURA", "player");
end
end
function AuraTrack:PLAYER_LOGIN()
-- Run the spec check on login
self:ACTIVE_TALENT_GROUP_CHANGED();
self:UnregisterEvent("PLAYER_LOGIN");
self.PLAYER_LOGIN = nil;
end
-- Related to creating and recycling active trackers
function AuraTrack:CreateTracker()
-- This counter is only here to generate non-garbage frame names
self.numTotalObjects = self.numTotalObjects + 1;
local id = self.numTotalObjects;
local button = CreateFrame("Frame", "$parentButton"..id, self);
button:Hide();
button:SetSize(size, size);
local cd = CreateFrame("Cooldown", "$parentCooldown", button, "CooldownFrameTemplate");
cd:SetAllPoints(button);
local icon = button:CreateTexture(nil, "BORDER");
icon:SetAllPoints(button);
local count = button:CreateFontString(nil, "OVERLAY");
count:SetFontObject(NumberFontNormal);
count:SetPoint("TOP", button, "BOTTOM", 0, -2);
button.cd = cd;
button.icon = icon;
button.count = count;
return button;
end
function AuraTrack:ResetTracker(button)
button.spellID = nil;
button:ClearAllPoints();
button:Hide();
end
-- Mix in the object pool functions
Mixin(AuraTrack, ObjectPoolMixin);
-- Give the object pool creation and resetting functions
AuraTrack:OnLoad(AuraTrack.CreateTracker, AuraTrack.ResetTracker);