Need help finding a circular Buff/Debuff tracker

Does anyone know of an addon that tracks buffs/debuffs in a circular pattern? I use Raven currently but it can only go in straight lines up/down/left/right. I need one that will track buffs/debuffs around a circular health orb.

I’ve been browsing for hours and haven’t found anything so I thought I’d check here and see if anyone may know of an addon I’m unaware of that can do this. Thanks for any help! :slight_smile:

I don’t know of anything but I’m working on something for you. Should have it by end of day.

Essentially, you’ll get buffs in an inner ring, debuffs in an outer ring - spaced evenly around the ring with options to change the size of the inner ring (outer ring based on inner ring size) and phase the buffs/debuffs the same or opposite one another (as in, if you have 3, you’ll get a triangle pointing up the same for both or one up and one down).

Internet’s back up on my end, but the game is down. I’m fixing some typos I didn’t catch earlier.

This is all the stuff you’ll need to share across the functions.

local f = {}  --  I'll be putting functions here

local parentFrameName  --  I don't know the frame name you want 
                       --  to anchor this to. For now, I'll use the center of
                       --  the screen. When you know the frame name, 
                       --  plug it in here (or just use the middle).
local a = {
  ["name"] = 1, ["icon"] = 2, ["cnt"] = 3, ["dbType"] = 4,
  ["dur"] = 5, ["exp"] = 6, ["src"] = 7, ["canSteal"] = 8,
  ["npPersonal"] = 9, ["spellID"] = 10, ["canApply"] = 11,
  ["bossDB"] = 12, ["castByPlayer"] = 13, ["npAll"] = 14,
  ["unused"] = 15, ["xtra1"] = 16, ["xtra2"] = 17,  ["xtra3"] = 18,
  ["xtra4"] = 19, ["xtra5"] = 20, ["xtra5"] = 21, ["xtra6"] = 22,
  ["xtra7"] = 23, ["xtra8"] = 24, ["xtra9"] = 25, ["xtra10"] = 26,
  ["xtra11"] = 27, ["xtra12"] = 28, ["xtra13"] = 29, ["xtra14"] = 30,
  ["xtra15"] = 31,
  --  note: there is no technical upper limit to how high these numbers
  --  can go -  testing has revealed confirmed data through xtra11
  --  I added a buffer of four additional fields
}
local iconSize, phase, 
      buffs, buffCnt, maxBuffs, buffRadians, buffRadius,
      debuffs, debuffCnt, maxDebuffs, debuffRadians, debuffRadius
    = 24, 1,  
      {}, 0, 0, 0, 200, 
      {}, 0, 0, 0, nil -- not strictly necessary, just a placeholder

This gets the auras for your character (I didn’t do pets).

function f:GetAuras()

  for i = 1, 40 do

    buffs[i] = {UnitBuff("PLAYER", i)}
    if buffs[i][a.name] then
    --	continue
    else
      buffs[i] = nil
    end
    debuffs[i] = {UnitDebuff("PLAYER", i)}
    if debuffs[i][a.name] then
    --	continue
    else
      debuffs[i] = nil
    end
    if buffs[i] or debuffs[i] then
    --	continue
    else
      break
    end

  end

  buffCnt = #buffs
  debuffCnt = #debuffs
  maxBuffs = (((buffCnt > maxBuffs) and buffCnt) or maxBuffs)
  maxDebuffs = (((debuffCnt > maxDebuffs) and debuffCnt) or maxDebuffs) 
  buffRadians = (((buffCnt == 0) and 0) or ((360 / buffCnt) * 0.0174533))
  debuffRadians = (((debuffCnt == 0) and 0) or ((360 / debuffCnt) * 0.0174533))
  debuffRadius = buffRadius + (iconSize * 1.5)

end

This handles creating new buff/debuff frames along the circle.

function f:CircleAuraFrameCreate(seq, buff, auraTable)

  local afp = (_G[parentFrameName] or UI_Parent)
  local aPrefix = ((buff and "CircleBuff") or "CircleDebuff")
  local af = CreateFrame("Frame", aPrefix..seq, afp)
  af:SetFrameStrata("BACKGROUND")
  af:SetHeight(iconSize)
  af:SetWidth(iconSize)
  af.texture = key:CreateTexture()
  af.texture:SetTexture(auraTable[a.icon])
  af.texture:SetAllPoints(af)
  af.auraRadians = ((buff and buffRadians) or debuffRadians)
  af.auraRadius = ((buff and buffRadius) or debuffRadius)
  af.auraCnt = ((buff and buffCnt) or debuffCnt)
  af.absoluteRadians = 4.71239 + (
    af.auraRadians * (((af.auraCnt == 0) and 0) or (af.auraCnt - 1))
  )
  af:SetPoint("CENTER", 
              afp, 
              "CENTER", 
              af.auraRadius * math.cos(af.absoluteRadians), 
              af.auraRadius * math.sin(af.absoluteRadians)
  )
  af:Show()

end

This handles adjusting buff/debuff frames along the circle.

function f:CircleAuraFrameAdjust(seq, buff, auraTable)

  local afp = (_G[parentFrameName] or UI_Parent)
  local aPrefix = ((buff and "CircleBuff") or "CircleDebuff")
  local af = _G[aPrefix..seq]
  af:ClearAllPoints()
  af:SetFrameStrata("BACKGROUND")
  af:SetHeight(iconSize)
  af:SetWidth(iconSize)
  af.texture:SetTexture(auraTable[a.icon])
  af.texture:SetAllPoints(af)
  af.auraRadians = ((buff and buffRadians)or debuffRadians)
  af.auraRadius = ((buff and buffRadius) or debuffRadius)
  af.auraCnt = ((buff and buffCnt) or debuffCnt)
  af.absoluteRadians = 4.71239 + (
    af.auraRadians * (((af.auraCnt == 0) and 0) or (af.auraCnt - 1))
  )
  af:SetPoint("CENTER", 
              afp, 
              "CENTER", 
              (af.auraRadius * math.cos(af.absoluteRadians)), 
              (af.auraRadius * math.sin(af.absoluteRadians))
  )
  af:Show()

end

This handles buffs.

function f:DrawCircleBuffs(true)

  f:DrawCircleAuras(true)

end

This handles debuffs.

function f:DrawCircleDebuffs()

  f:DrawCircleAuras(false)

end

This handles drawing the buff auras on screen (adjusting or creating frames as needed as well as hiding unneeded ones).

function f:DrawCircleAuras(buffAuras)

  local at	= ((buffAuras and buffs)	or debuffs)
  local aMax	= ((buffAuras and maxBuffs	or maxDebuffs)
  local atPrefix	= ((buffAuras and "CircleBuffs") or "CircleDebuffs")

  for seq = 1, aMax do
    if _G[(atPrefix..seq)] then
      if at[seq][a.name] then
        f:CircleAuraFrameAdjust(seq, true, at)
      else
        _G[(atPrefix..seq)]:Hide()
      end
    else
      if at[seq][a.name] then
        f:CircleAuraFrameCreate(seq, true, at)
      else
      --  not necessary to do anything here
      end
    end
  end

end