local Totems = {} local totemColors = {} local MAX_TOTEMS = MAX_TOTEMS -- CoA: per-class slot count override (different from shaman's 4). local COA_CLASS_TOTEMS = { WITCHDOCTOR = 3, } -- Death Knights untalented ghouls are guardians and are considered totems........... so set it up for them local playerClass = select(2, UnitClass("player")) if( playerClass == "DEATHKNIGHT" ) then MAX_TOTEMS = 1 ShadowUF:RegisterModule(Totems, "totemBar", ShadowUF.L["Guardian bar"], true, "DEATHKNIGHT") else -- CoA: SHAMAN is the vanilla totem class, but CoA custom classes (Witchdoctor, …) also use the -- multi-cast totem bar. Detect via MAX_TOTEMS > 1 (set by FrameXML for totem classes) or the -- HasMultiCastActionBar API (Bartender uses the same probe). Register with class=nil so the -- module is available to any CoA totem class, not just SHAMAN. local hasTotems = (MAX_TOTEMS and MAX_TOTEMS > 1) or (type(HasMultiCastActionBar) == "function" and HasMultiCastActionBar()) or playerClass == "SHAMAN" if COA_CLASS_TOTEMS[playerClass] then MAX_TOTEMS = COA_CLASS_TOTEMS[playerClass] end if( hasTotems ) then ShadowUF:RegisterModule(Totems, "totemBar", ShadowUF.L["Totem bar"], true) else ShadowUF:RegisterModule(Totems, "totemBar", ShadowUF.L["Totem bar"], true, "SHAMAN") end end function Totems:OnEnable(frame) if( not frame.totemBar ) then frame.totemBar = CreateFrame("Frame", nil, frame) frame.totemBar.totems = {} for id=1, MAX_TOTEMS do local totem = ShadowUF.Units:CreateBar(frame) totem:SetFrameLevel(1) totem:SetMinMaxValues(0, 1) totem:SetValue(0) totem.id = MAX_TOTEMS == 1 and 1 or TOTEM_PRIORITIES[id] -- Right-click dismisses the totem in this slot. EnableMouse on the strip -- absorbs clicks here (loses click-to-target on the totem bar only). totem:EnableMouse(true) totem:SetScript("OnMouseUp", function(self, button) if button == "RightButton" and self.have then DestroyTotem(self.id) end end) -- Seconds-remaining text, centred on the bar; updated by totemMonitor. totem.timeText = totem:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") totem.timeText:SetPoint("CENTER", totem, "CENTER", 0, 0) totem.timeText:SetText("") if( id > 1 ) then totem:SetPoint("TOPLEFT", frame.totemBar.totems[id - 1], "TOPRIGHT", 1, 0) else totem:SetPoint("TOPLEFT", frame.totemBar, "TOPLEFT", 0, 0) end table.insert(frame.totemBar.totems, totem) end if( MAX_TOTEMS == 1 ) then totemColors[1] = ShadowUF.db.profile.classColors.PET else totemColors[1] = {r = 1, g = 0, b = 0.4} totemColors[2] = {r = 0, g = 1, b = 0.4} totemColors[3] = {r = 0, g = 0.4, b = 1} totemColors[4] = {r = 0.90, g = 0.90, b = 0.90} end end frame:RegisterNormalEvent("PLAYER_TOTEM_UPDATE", self, "Update") frame:RegisterUpdateFunc(self, "Update") end function Totems:OnDisable(frame) frame:UnregisterAll(self) end function Totems:OnLayoutApplied(frame) if( frame.visibility.totemBar ) then local barWidth = (frame.totemBar:GetWidth() - (MAX_TOTEMS - 1)) / MAX_TOTEMS for _, totem in pairs(frame.totemBar.totems) do if( ShadowUF.db.profile.units[frame.unitType].totemBar.background ) then local color = ShadowUF.db.profile.bars.backgroundColor or ShadowUF.db.profile.units[frame.unitType].totemBar.backgroundColor or totemColors[totem.id] totem.background:SetTexture(ShadowUF.Layout.mediaPath.statusbar) totem.background:SetVertexColor(color.r, color.g, color.b, ShadowUF.db.profile.bars.backgroundAlpha) totem.background:Show() else totem.background:Hide() end totem:SetHeight(frame.totemBar:GetHeight()) totem:SetWidth(barWidth) totem:SetStatusBarTexture(ShadowUF.Layout.mediaPath.statusbar) totem:SetStatusBarColor(totemColors[totem.id].r, totemColors[totem.id].g, totemColors[totem.id].b, ShadowUF.db.profile.bars.alpha) totem:GetStatusBarTexture():SetHorizTile(false) end end end local function totemMonitor(self, elapsed) local time = GetTime() local remaining = self.endTime - time self:SetValue(remaining) if self.timeText then local intSec = remaining > 0 and math.floor(remaining) or 0 if intSec ~= self.lastIntSec then self.lastIntSec = intSec self.timeText:SetText(intSec > 0 and intSec or "") end end if( time >= self.endTime ) then self:SetValue(0) if self.timeText then self.timeText:SetText("") self.lastIntSec = nil end self:SetScript("OnUpdate", nil) end end function Totems:Update(frame) local totalActive = 0 for _, indicator in pairs(frame.totemBar.totems) do local have, name, start, duration = GetTotemInfo(indicator.id) if( have and start > 0 ) then indicator.have = true indicator.endTime = start + duration indicator:SetMinMaxValues(0, duration) indicator:SetValue(indicator.endTime - GetTime()) indicator:SetScript("OnUpdate", totemMonitor) indicator:SetAlpha(1.0) totalActive = totalActive + 1 elseif( indicator.have ) then indicator.have = nil indicator:SetScript("OnUpdate", nil) indicator:SetMinMaxValues(0, 1) indicator:SetValue(0) if indicator.timeText then indicator.timeText:SetText("") indicator.lastIntSec = nil end end end -- Only guardian timers should auto hide, nothing else if( MAX_TOTEMS == 1 ) then ShadowUF.Layout:SetBarVisibility(frame, "totemBar", totalActive > 0) end end