-- Indicators.lua local pairs, ipairs = pairs, ipairs; local floor = math.floor; local GetTime = GetTime; local UnitAura = UnitAura; local UnitIsDeadOrGhost, UnitIsConnected = UnitIsDeadOrGhost, UnitIsConnected; local CTimerAfter = C_Timer.After; local Settings = OmaRFSettings; local majorAuras = Settings.MajorAuras; local indSize = Settings.IndSize; local positions = nil; local watchedAuras = nil; local updaters = {}; local updating = {}; local auraFilters = {"HELPFUL", "HARMFUL"}; local M = {}; OmaRFIndicators = M; function M.SetupIndicators(frame) if not watchedAuras then watchedAuras = Settings.Character["WatchedAuras"]; positions = Settings.Character.Positions; end frame.inds = CreateFrame("Frame", nil, frame); frame.inds:SetAllPoints(); frame.inds:Hide(); for _, pos in pairs(positions) do frame.inds[pos] = frame.inds:CreateTexture(nil, "OVERLAY"); frame.inds[pos]:SetPoint(pos, frame.inds, pos); frame.inds[pos]:SetWidth(indSize); frame.inds[pos]:SetHeight(indSize); frame.inds[pos]:SetTexture("Interface\\AddOns\\OmaRF\\images\\rhomb"); frame.inds[pos]:SetVertexColor(1, 0, 0); frame.inds[pos]:Hide(); frame.inds[pos].text = frame.inds:CreateFontString(nil, "OVERLAY", "GameFontHighlight"); frame.inds[pos].text:SetPoint("BOTTOMRIGHT", frame.inds[pos], "BOTTOMRIGHT"); frame.inds[pos].text:Hide(); end frame.major = CreateFrame("Frame", nil, frame); frame.major:SetPoint("TOPLEFT", frame, "TOPLEFT", 4, -indSize + 4); frame.major:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT"); for i = 1,3 do frame.major[i] = frame.major:CreateTexture(nil, "OVERLAY"); if i == 1 then frame.major[i]:SetPoint("TOPLEFT", frame.major, "TOPLEFT"); else frame.major[i]:SetPoint("TOPLEFT", frame.major[i-1], "TOPRIGHT"); end frame.major[i]:SetWidth(indSize*2); frame.major[i]:SetHeight(indSize*2); frame.major[i]:Hide(); frame.major[i].text = frame.major:CreateFontString(nil, "OVERLAY", "GameFontHighlight"); frame.major[i].text:SetPoint("BOTTOMRIGHT", frame.major[i], "BOTTOMRIGHT"); frame.major[i].text:Hide(); frame.major[i].stack = frame.major:CreateFontString(nil, "OVERLAY", "GameFontHighlight"); frame.major[i].stack:SetPoint("TOPLEFT", frame.major[i], "TOPLEFT"); frame.major[i].stack:Hide(); end end local function remaining(text, expires, current) if expires == 0 then text:SetText(""); return false; end local remain = expires - current; if remain > 8 then text:SetText(""); else text:SetText(floor(remain+0.5)); end return true; end local function updateIndicators(frame, unit) if not frame:IsShown() or not UnitIsConnected(unit) or UnitIsDeadOrGhost(unit) then updating[frame] = nil; return; end local needUpdate = false; local current = GetTime(); for _, pos in pairs(positions) do local ind = frame.inds[pos]; if ind.expires ~= nil then needUpdate = remaining(ind.text, ind.expires, current) or needUpdate; end end for i = 1,3 do local ind = frame.major[i]; if ind.expires ~= nil then needUpdate = remaining(ind.text, ind.expires, current) or needUpdate; end end if needUpdate then CTimerAfter(0.16, updaters[frame]); else updating[frame] = nil; end end function M.CheckIndicators(frame, unit) for _, pos in pairs(positions) do frame.inds[pos].expires = nil; frame.inds[pos]:Hide(); frame.inds[pos].text:Hide(); end for i = 1,3 do frame.major[i].expires = nil; frame.major[i]:Hide(); frame.major[i].text:Hide(); frame.major[i].stack:Hide(); end local name, icon, count, expires, caster, id; local showInds, showMajors, needUpdate = false, false, false; local majorPos = 1; local alert = false; -- color the whole bar local current = GetTime(); for _, filter in ipairs(auraFilters) do local i = 1; while true do name, _, icon, count, _, _, expires, caster, _, _, id = UnitAura(unit, i, filter); if not id then break end local pos = watchedAuras[id] or watchedAuras[name]; if pos and caster == "player" then needUpdate = remaining(frame.inds[pos].text, expires, current); frame.inds[pos].expires = expires; frame.inds[pos]:Show(); frame.inds[pos].text:Show(); showInds = true; end local major = majorAuras[id] or majorAuras[name]; if major and majorPos <= 3 then needUpdate = remaining(frame.major[majorPos].text, expires, current); frame.major[majorPos].expires = expires; frame.major[majorPos]:SetTexture(icon); frame.major[majorPos]:Show(); frame.major[majorPos].text:Show(); if count > 1 then frame.major[majorPos].stack:SetText(count); frame.major[majorPos].stack:Show(); end if major.bar then alert = true; end showMajors = true; majorPos = majorPos + 1; end i = i + 1; end end if showInds or showMajors then frame.inds:Show(); frame.major:Show(); if needUpdate and not updating[frame] then updating[frame] = true; -- race? -- create a function for updating the indicator local func = updaters[frame]; if not func then func = function() updateIndicators(frame, unit) end; updaters[frame] = func; end CTimerAfter(0.16, func); end else frame.inds:Hide(); frame.major:Hide(); end return alert; end