-Indicators = LibStub("AceAddon-3.0"):NewAddon( "Indicators", "AceTimer-3.0");
-local media = LibStub:GetLibrary("LibSharedMedia-3.0");
-local f = {}; -- Indicator objects
-local pad = 2;
-local _;
-local watchedAuras; -- all watched auras
-local indicatorAuras; -- watched auras per indicator
-local auraFilters = {"HELPFUL", "HARMFUL"};
-local DEFAULT_ICON = "Interface\\AddOns\\RaidFrameCustomization\\images\\rhomb";
-
--- global functions used every update
-local GetTime = GetTime;
-local UnitAura = UnitAura;
-local UnitIsUnit = UnitIsUnit;
-local UnitIsConnected = UnitIsConnected;
-local UnitIsDeadOrGhost = UnitIsDeadOrGhost;
-
--- list of important auras TODO try to use spellIDs
-local centerAuras = {
- "Power Word: Shield"
-};
-
-local function dPrint(s)
- DEFAULT_CHAT_FRAME:AddMessage("Indicators: ".. tostring(s));
-end
-
--- Set the appearance of the FontStrings
-local function setupIndicatorAppearance(frame)
- local frameName = frame:GetName();
- if not f[frameName] then return end
- local font = media and media:Fetch('font', Indicators.db.profile.indicatorFont) or STANDARD_TEXT_FONT;
-
- local i, ind;
- for i, ind in ipairs(f[frameName]) do
- ind.text:SetFont(font, Indicators.db.profile["textSize"..i], "");
- ind.icon:SetWidth(Indicators.db.profile["iconSize"..i]);
- ind.icon:SetHeight(Indicators.db.profile["iconSize"..i]);
- if Indicators.db.profile["showIcon"..i] then
- ind.icon:Show();
- else
- ind.icon:Hide();
- end
- end
-end
-
--- Create the FontStrings used for indicators
-local function setupCompactUnitFrame(frame)
- local frameName = frame:GetName();
- local i;
- local positions = {
- "TOPLEFT", "TOPRIGHT", "CENTER", "BOTTOMLEFT", "BOTTOMRIGHT"
- };
- local paddings = {
- {pad, -pad}, {-pad, -pad}, {0, 0}, {pad, pad}, {-pad, pad}
- };
-
- -- Create indicators
- f[frameName] = {};
- for i = 1, 5 do
- f[frameName][i] = {};
- f[frameName][i].text = frame:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall");
- f[frameName][i].text:SetPoint(positions[i], frame, positions[i], paddings[i][1], paddings[i][2]);
- f[frameName][i].icon = frame:CreateTexture(nil, "OVERLAY");
- f[frameName][i].icon:SetPoint(positions[i], frame, positions[i], paddings[i][1], paddings[i][2]);
- end
- setupIndicatorAppearance(frame);
-end
-
--- Get all unit auras
-local function getAuras(unit)
- local unitAuras = {};
- local auraName, icon, count, expires, caster, debuffType, spellId;
- local filter;
-
- -- Get all unit auras
-
- for _, filter in ipairs(auraFilters) do
- local i = 1;
- while true do
- auraName, _, icon, count, debuffType, _, expires, caster, _, _, spellId = UnitAura(unit, i, filter);
- if not spellId then break end
- if watchedAuras[auraName] or watchedAuras[spellId] or watchedAuras[debuffType] then
- local aura = {};
- aura.auraName = auraName;
- aura.spellId = spellId;
- aura.count = count;
- aura.expires = expires;
- aura.mine = UnitIsUnit(caster, "player");
- aura.icon = icon;
- aura.debuffType = debuffType;
- table.insert(unitAuras, aura);
- end
- i = i + 1;
- end
- end
- return unitAuras;
-end
-
--- Check the indicators on a frame and update the times on them
-local function updateIndicator(frame)
- if not frame.unit then return end
- local unit = frame.unit;
- local frameName = frame:GetName();
- local i, ind;
-
- -- Check if the indicator object exists, else create it
- if not f[frameName] then setupCompactUnitFrame(frame) end
- -- Hide if unit is dead/disconnected
- if (not UnitIsConnected(unit)) or UnitIsDeadOrGhost(frame.displayedUnit) then
- for _, ind in pairs(f[frameName]) do
- ind.text:SetText("");
- ind.icon:SetTexture("");
- end
- return;
- end
-
- local unitAuras = getAuras(unit);
- for i, ind in ipairs(f[frameName]) do
- -- try to find matching aura
- local found, aura;
- for _, aura in pairs(unitAuras) do
- if indicatorAuras[i][aura.auraName] or indicatorAuras[i][aura.spellId] or
- indicatorAuras[i][aura.debuffType] then
- found = aura;
- -- break on first matching buff/debuff cast by me
- -- otherwise continue through
- if aura.mine then break end
- end
- end
-
- if found then
- if Indicators.db.profile["mine"..i] and not found.mine then
- -- don't show
- ind.icon:SetTexture("");
- ind.text:SetText("");
- else
- if Indicators.db.profile["showIcon"..i] then
- -- show icon TODO coloring
- if Indicators.db.profile["useDefaultIcon"..i] then
- ind.icon:SetTexture(DEFAULT_ICON);
- else
- ind.icon:SetTexture(found.icon);
- end
- end
- -- TODO make show text into general setting
- -- under which you can select what text to show
- if Indicators.db.profile["showText"..i] then
- -- show text
- local text;
- local remaining = found.expires - GetTime();
- if remaining > 60 then
- text = string.format("%dm", ceil(remaining/60));
- else
- text = string.format("%d", floor(remaining+0.5));
- end
-
- if Indicators.db.profile["stack"..i] and found.count > 0 then
- if text then
- text = found.count.."-"..text;
- else
- text = found.count;
- end
- end
-
- -- colors
- ind.text:SetTextColor(
- Indicators.db.profile["color"..i].r,
- Indicators.db.profile["color"..i].g,
- Indicators.db.profile["color"..i].b,
- Indicators.db.profile["color"..i].a
- );
- if Indicators.db.profile["debuffColor"..i] then
- if found.debuffType then
- if found.debuffType == "Curse" then
- ind.text:SetTextColor(0.6,0,1,1);
- elseif found.debuffType == "Disease" then
- ind.text:SetTextColor(0.6,0.4,0,1);
- elseif found.debuffType == "Magic" then
- ind.text:SetTextColor(0.2,0.6,1,1);
- elseif found.debuffType == "Poison" then
- ind.text:SetTextColor(0,0.6,0,1);
- end
- end
- end
-
- ind.text:SetText(text);
- end
- end
- else
- -- not found, show nothing
- ind.icon:SetTexture("");
- ind.text:SetText("");
- end
- end
-end
-
--- Update all indicators
-function Indicators:UpdateAllIndicators()
- CompactRaidFrameContainer_ApplyToFrames(CompactRaidFrameContainer, "normal", updateIndicator);
-end
-
--- Used to update everything that is affected by the configuration
-function Indicators:RefreshConfig()
- CompactRaidFrameContainer_ApplyToFrames(CompactRaidFrameContainer, "normal", setupIndicatorAppearance);
- -- Format aura strings
- watchedAuras = {};
- indicatorAuras = {};
- local auraName, i;
- for i = 1, 5 do
- indicatorAuras[i] = {};
- for auraName in string.gmatch(Indicators.db.profile["auras"..i], "[^\n]+") do -- Grab each line
- auraName = string.gsub(auraName, "^%s*(.-)%s*$", "%1"); -- Strip any whitespaces
- if tonumber(auraName) then
- watchedAuras[tonumber(auraName)] = true;
- indicatorAuras[i][tonumber(auraName)] = true;
- else
- watchedAuras[auraName] = true;
- indicatorAuras[i][auraName] = true;
- end
- end
- end
-
- self:CancelAllTimers();
- if next(watchedAuras) ~= nil then
- self.updateTimer = self:ScheduleRepeatingTimer("UpdateAllIndicators", 0.15);
- end
-end
-
-function Indicators:OnInitialize()
- self:SetupOptions();
- self.db.RegisterCallback(self, "OnProfileChanged", "RefreshConfig");
- self.db.RegisterCallback(self, "OnProfileCopied", "RefreshConfig");
- self.db.RegisterCallback(self, "OnProfileReset", "RefreshConfig");
-end
-
-function Indicators:OnEnable()
- if self.db.profile.enabled then
- Indicators:RefreshConfig();
- end
-end
-
-function Indicators:OnDisable()
- local frame, ind;
- self:CancelAllTimers();
- for _, frame in pairs(f) do
- for _, ind in pairs(frame) do
- ind.text:SetText("");
- ind.icon:SetTexture("");
- end
- end
-end