local ElkBuffBar = {} function ElkBuffBar:Init() BuffFrame:Hide() TemporaryEnchantFrame:Hide() self.frame = ElkBuffBarFrame self.frame:ClearAllPoints() self.frame.owner = self self.frame:SetScript("OnEvent", function() this.owner:OnEvent() end) self.frame:RegisterEvent("ADDON_LOADED") self.tooltip = ElkBuffTooltip self.numBuffButtons = 0 self.numBuffsShown = 0 self.UpdateTime = 0 self.FlashTime = 0 self.FlashState = 0 self.Layout = {} self.old_hasMainHandEnchant = nil self.old_mainHandName = "" self.old_mainHandExpiration = 0 self.old_mainHandCharges = 0 self.old_hasOffHandEnchant = nil self.old_offHandName = "" self.old_offHandExpiration = 0 self.old_offHandCharges = 0 self.compost = AceLibrary("Compost-2.0") if (IsAddOnLoaded("ItemDB_Money")) then EquipCompare_RegisterExclusion("^ElkBuffButton") end end function ElkBuffBar:OnEvent() if event == "ADDON_LOADED" and arg1 == "ElkBuffBar" then self.frame:UnregisterEvent("ADDON_LOADED") self:InitSettings() self.frame:RegisterEvent("PLAYER_AURAS_CHANGED") self.frame:SetScript("OnUpdate", function() this.owner:OnUpdate(arg1) end) self.frame:SetScript("OnLeave", function() this.owner:StopMoving() end) SLASH_ELKBUFFBAR1 = "/ebb" SLASH_ELKBUFFBAR2 = "/elkbuffbar" SlashCmdList["ELKBUFFBAR"] = function(msg) ElkBuffBarFrame.owner:SlashCommandHandler(msg) end elseif event == "PLAYER_AURAS_CHANGED" then self:UpdateBuffs() end end function ElkBuffBar:InitSettings() if not ElkBuffBarOptions then ElkBuffBarOptions = { ["width"] = 250, ["height"] = 20, ["scale"] = 1, ["anchor"] = "TOPRIGHT", ["locked"] = nil, ["alpha"] = 1, ["icon"] = "LEFT", ["sort"] = "DEFAULT", ["timer"] = "DEFAULT", ["invert"] = nil, ["spacing"] = 0, ["group"] = 5, ["dbcolor"] = true, } end if not ElkBuffBarOptions.width then ElkBuffBarOptions.width = 250 end if not ElkBuffBarOptions.height then ElkBuffBarOptions.height = 20 end if not ElkBuffBarOptions.scale then ElkBuffBarOptions.scale = 1 end if not ElkBuffBarOptions.anchor then ElkBuffBarOptions.anchor = "TOPRIGHT" end if not ElkBuffBarOptions.alpha then ElkBuffBarOptions.alpha = 1 end if not ElkBuffBarOptions.icon then ElkBuffBarOptions.icon = "LEFT" end if not ElkBuffBarOptions.sort then ElkBuffBarOptions.sort = "DEFAULT" end if not ElkBuffBarOptions.timer then ElkBuffBarOptions.timer = "DEFAULT" end if not ElkBuffBarOptions.spacing then ElkBuffBarOptions.spacing = 0 end if not ElkBuffBarOptions.group then ElkBuffBarOptions.group = 5 end if not ElkBuffBarOptions.dbcolor then ElkBuffBarOptions.dbcolor = true end if not ElkBuffBarOptions.x then ElkBuffBarOptions.x = floor(GetScreenWidth() * .5 / (GetCVar("uiscale") * ElkBuffBarOptions.scale)) end if not ElkBuffBarOptions.y then ElkBuffBarOptions.y = floor(GetScreenHeight() * .5 / (GetCVar("uiscale") * ElkBuffBarOptions.scale)) end self:UpdateLayout() end local function buffssort_bytimeleft(a, b) if (not a or not b) then return true end if a[5] == 1 then if b[5] == 1 then return a[2] < b[2] else return true end end if b[5] == 1 then return false end if a[3] > b[3] then return true end if a[3] < b[3] then return false end return a[2] < b[2] end local function buffssort_bytimemax(a, b) if (not a or not b) then return true end if a[5] == 1 then if b[5] == 1 then return a[2] < b[2] else return true end end if b[5] == 1 then return false end if a[4] > b[4] then return true end if a[4] < b[4] then return false end return a[2] < b[2] end local function isEmpty(ttbl) for _,_ in ttbl do return false end return true end function ElkBuffBar:UpdateBuffs() local maxtimes = self.compost:Acquire() local buffssort = self.compost:Acquire() for i = 1, self.numBuffsShown do local button = getglobal("ElkBuffButton"..i) if not maxtimes[button.name] or maxtimes[button.name] < button.maxtime then maxtimes[button.name] = button.maxtime end end local numBuffs = 0 local buffIndex, untilCancelled local i = 0 while true do buffIndex, untilCancelled = GetPlayerBuff(i, "HELPFUL") if buffIndex < 0 then break end local timeleft = GetPlayerBuffTimeLeft(buffIndex) local timemax = timeleft local name = self:GetBuffName(buffIndex) if (name) then if maxtimes[name] and timemax < maxtimes[name] then timemax = maxtimes[name] end end table.insert(buffssort, self.compost:Acquire(buffIndex, name, timeleft, timemax, untilCancelled)) i = i + 1 end if ElkBuffBarOptions.sort == "TIMEMAX" then table.sort(buffssort, buffssort_bytimemax) elseif ElkBuffBarOptions.sort == "TIMELEFT" then table.sort(buffssort, buffssort_bytimeleft) end for it = 1, table.getn(buffssort) do numBuffs = numBuffs + 1 self:SetBuffButtonBuff(numBuffs, buffssort[it][1], buffssort[it][2], buffssort[it][3], buffssort[it][4], buffssort[it][5]) end buffssort = self.compost:Reclaim(buffssort, 1) buffssort = self.compost:Acquire() i = 0 while true do buffIndex, untilCancelled = GetPlayerBuff(i, "HARMFUL") if buffIndex < 0 then break end local timeleft = GetPlayerBuffTimeLeft(buffIndex) local timemax = timeleft local name = self:GetBuffName(buffIndex) if (name) then if maxtimes[name] and timemax < maxtimes[name] then timemax = maxtimes[name] end end table.insert(buffssort, self.compost:Acquire(buffIndex, name, timeleft, timemax, untilCancelled)) i = i + 1 end if ElkBuffBarOptions.sort == "TIMEMAX" then table.sort(buffssort, buffssort_bytimemax) elseif ElkBuffBarOptions.sort == "TIMELEFT" then table.sort(buffssort, buffssort_bytimeleft) end for it = 1, table.getn(buffssort) do numBuffs = numBuffs + 1 self:SetBuffButtonDebuff(numBuffs, buffssort[it][1], buffssort[it][2], buffssort[it][3], buffssort[it][4], buffssort[it][5]) end buffssort = self.compost:Reclaim(buffssort, 1) buffssort = self.compost:Acquire() local hasMainHandEnchant, mainHandExpiration, mainHandCharges, hasOffHandEnchant, offHandExpiration, offHandCharges = GetWeaponEnchantInfo() if ( hasMainHandEnchant ) then local timeleft = mainHandExpiration / 1000 local timemax = timeleft local id = GetInventorySlotInfo("MainHandSlot") local name = self:GetTempBuffName(id) if (name) then if maxtimes[name] and timemax < maxtimes[name] then timemax = maxtimes[name] end end table.insert(buffssort, self.compost:Acquire(id, name, timeleft, timemax, mainHandCharges)) end if ( hasOffHandEnchant ) then local timeleft = offHandExpiration / 1000 local timemax = timeleft local id = GetInventorySlotInfo("SecondaryHandSlot") local name = self:GetTempBuffName(id) if (name) then if maxtimes[name] and timemax < maxtimes[name] then timemax = maxtimes[name] end end oldn = table.getn(buffssort) table.insert(buffssort, self.compost:Acquire(id, name, timeleft, timemax, offHandCharges)) end if ElkBuffBarOptions.sort == "TIMEMAX" then table.sort(buffssort, buffssort_bytimemax) elseif ElkBuffBarOptions.sort == "TIMELEFT" then table.sort(buffssort, buffssort_bytimeleft) end for it = 1, table.getn(buffssort) do numBuffs = numBuffs + 1 self:SetBuffButtonWeapon(numBuffs, buffssort[it][1], buffssort[it][2], buffssort[it][3], buffssort[it][4], buffssort[it][5]) end self:Cleanup(numBuffs) self.numBuffsShown = numBuffs self:UpdateButtonPositions() maxtimes = self.compost:Reclaim(maxtimes) buffssort = self.compost:Reclaim(buffssort, 1) end function ElkBuffBar:SetBuffButtonBuff(buttonid, id, buffname, timeleft, timemax, cancel) self:CreateButtons(buttonid) local button = getglobal("ElkBuffButton"..buttonid) local bar = getglobal("ElkBuffButton"..buttonid.."TimeBar") local icon = getglobal("ElkBuffButton"..buttonid.."Icon") local name = getglobal("ElkBuffButton"..buttonid.."DescribeText") local buffCount = getglobal("ElkBuffButton"..buttonid.."Count") local duration = getglobal("ElkBuffButton"..buttonid.."DurationText") local debuff = getglobal("ElkBuffButton"..buttonid.."DebuffBorder") local tench = getglobal("ElkBuffButton"..buttonid.."TEnchBorder") button:SetAlpha(self.frame:GetAlpha()) button.type = "BUFF" button.id = id button.untilCancelled = cancel button:SetBackdropColor(0.3, 0.5, 1, 0.5) bar:SetStatusBarColor(0, 0.5, 1, 0.8) icon:SetTexture(GetPlayerBuffTexture(id)) button.timeleft = timeleft button.maxtime = timemax bar:SetMinMaxValues(0, button.maxtime) button.name = buffname or "Buff "..id local count = GetPlayerBuffApplications(id) if ( count > 1 ) then name:SetText((buffname or "Buff "..id).." x"..count) buffCount:SetText(count) buffCount:Show() else name:SetText(buffname or "Buff "..id) buffCount:Hide() end debuff:Hide() tench:Hide() button:Show() end function ElkBuffBar:SetBuffButtonDebuff(buttonid, id, buffname, timeleft, timemax, cancel) self:CreateButtons(buttonid) local button = getglobal("ElkBuffButton"..buttonid) local bar = getglobal("ElkBuffButton"..buttonid.."TimeBar") local icon = getglobal("ElkBuffButton"..buttonid.."Icon") local name = getglobal("ElkBuffButton"..buttonid.."DescribeText") local buffCount = getglobal("ElkBuffButton"..buttonid.."Count") local duration = getglobal("ElkBuffButton"..buttonid.."DurationText") local debuff = getglobal("ElkBuffButton"..buttonid.."DebuffBorder") local tench = getglobal("ElkBuffButton"..buttonid.."TEnchBorder") button:SetAlpha(self.frame:GetAlpha()) button.type = "DEBUFF" button.id = id button.untilCancelled = cancel button:SetBackdropColor(1, 0, 0, 0.5) icon:SetTexture(GetPlayerBuffTexture(id)) button.timeleft = timeleft button.maxtime = timemax bar:SetMinMaxValues(0, button.maxtime) button.name = buffname or "Debuff "..id local count = GetPlayerBuffApplications(id) if ( count > 1 ) then name:SetText((buffname or "Debuff "..id).." x"..count) buffCount:SetText(count) buffCount:Show() else name:SetText(buffname or "Debuff "..id) buffCount:Hide() end local color local debuffType = GetPlayerBuffDispelType(id) if ( debuffType ) then color = DebuffTypeColor[debuffType] else color = DebuffTypeColor["none"] end debuff:SetVertexColor(color.r, color.g, color.b) if ElkBuffBarOptions.dbcolor then bar:SetStatusBarColor(color.r, color.g, color.b, 0.8) else bar:SetStatusBarColor(1, 0, 0, 0.8) end debuff:Show() tench:Hide() button:Show() end function ElkBuffBar:SetBuffButtonWeapon(buttonid, id, buffname, timeleft, timemax, count) self:CreateButtons(buttonid) local button = getglobal("ElkBuffButton"..buttonid) local bar = getglobal("ElkBuffButton"..buttonid.."TimeBar") local icon = getglobal("ElkBuffButton"..buttonid.."Icon") local name = getglobal("ElkBuffButton"..buttonid.."DescribeText") local buffCount = getglobal("ElkBuffButton"..buttonid.."Count") local duration = getglobal("ElkBuffButton"..buttonid.."DurationText") local debuff = getglobal("ElkBuffButton"..buttonid.."DebuffBorder") local tench = getglobal("ElkBuffButton"..buttonid.."TEnchBorder") button:SetAlpha(self.frame:GetAlpha()) button.type = "WEAPON" button.id = id button.untilCancelled = 0 button:SetBackdropColor(0.5, 0, 0.5, 0.5) bar:SetStatusBarColor(0.5, 0, 0.5, 0.8) icon:SetTexture(GetInventoryItemTexture("player", id)) button.timeleft = timeleft button.maxtime = timemax bar:SetMinMaxValues(0, button.maxtime) button.name = buffname or "Weapon "..id if ( count > 1 ) then name:SetText((buffname or "Weapon "..id).." x"..count) buffCount:SetText(count) buffCount:Show() else name:SetText(buffname or "Weapon "..id) buffCount:Hide() end debuff:Hide() tench:Show() button:Show() end function ElkBuffBar:CreateButtons(numButtons) if numButtons > self.numBuffButtons then for i = self.numBuffButtons + 1, numButtons do local f = CreateFrame("Button", "ElkBuffButton"..i, self.frame, "ElkBuffBar_BuffButtonTemplate") self:UpdateButtonPosition(i) self:UpdateButtonHeight(i) self:UpdateButtonIcon(i) self:UpdateButtonTimer(i) f.owner = self f:SetScript("OnMouseDown", function() if arg1 == "LeftButton" then this.isMoving = true; this.owner:StartMoving() end end) f:SetScript("OnMouseUp", function() if arg1 == "LeftButton" then this.isMoving = false; this.owner:StopMoving() end end) f:SetScript("OnHide", function() if this.isMoving then this.owner:StopMoving() end end) f:RegisterForClicks("RightButtonUp") f:SetScript("OnClick", function() this.owner:ButtonOnClick() end) f:SetScript("OnEnter", function() this.owner:ButtonOnEnter() end) f:SetScript("OnLeave", function() this.owner:ButtonOnLeave() end) getglobal("ElkBuffButton"..i.."DescribeText"):SetTextColor(1, 1, 1) getglobal("ElkBuffButton"..i.."DurationText"):SetTextColor(1, 1, 1) end self.numBuffButtons = numButtons end end function ElkBuffBar:Cleanup(numBuffs) if numBuffs < self.numBuffButtons then for i = numBuffs + 1, self.numBuffButtons do local button = getglobal("ElkBuffButton"..i) button.id = nil button:Hide() end end end function ElkBuffBar:GetBuffName(id) self.tooltip:SetPlayerBuff(id) local toolTipText = getglobal("ElkBuffTooltipTextLeft1") if (toolTipText) then return toolTipText:GetText() or id end return id end function ElkBuffBar:GetTempBuffName(id) self.tooltip:SetInventoryItem("player", id) for i=1,self.tooltip:NumLines() do local toolTipText = getglobal("ElkBuffTooltipTextLeft" .. i) local _, _, buffname = string.find(toolTipText:GetText(), "^([^%(]+) %(%d+ [^%)]+%)") if buffname then return buffname end end local itemlink = GetInventoryItemLink("player", id); if (itemlink) then local _, _, name = string.find(itemlink, "|c%x+|Hitem:%d+:%d+:%d+:%d+|h%[(.-)%]|h|r"); return name or "Weapon "..id end return "Weapon "..id end function ElkBuffBar:OnUpdate(elapsed) local hasMainHandEnchant, mainHandExpiration, mainHandCharges, hasOffHandEnchant, offHandExpiration, offHandCharges = GetWeaponEnchantInfo() local mainHandName = "" if hasMainHandEnchant then mainHandName = self:GetTempBuffName(GetInventorySlotInfo("MainHandSlot")) end local offHandName = "" if hasOffHandEnchant then offHandName = self:GetTempBuffName(GetInventorySlotInfo("SecondaryHandSlot")) end hasMainHandEnchant = hasMainHandEnchant or false mainHandName = mainHandName or "" mainHandExpiration = mainHandExpiration or 0 mainHandCharges = mainHandCharges or 0 hasOffHandEnchant = hasOffHandEnchant or false offHandName = offHandName or "" offHandExpiration = offHandExpiration or 0 offHandCharges = offHandCharges or 0 if hasMainHandEnchant ~= self.old_hasMainHandEnchant or mainHandName ~= self.old_mainHandName or mainHandExpiration > self.old_mainHandExpiration or mainHandCharges ~= self.old_mainHandCharges or hasOffHandEnchant ~= self.old_hasOffHandEnchant or offHandName ~= self.old_offHandName or offHandExpiration > self.old_offHandExpiration or offHandCharges ~= self.old_offHandCharges then self:UpdateBuffs() end self.old_hasMainHandEnchant = hasMainHandEnchant self.old_mainHandName = mainHandName self.old_mainHandExpiration = mainHandExpiration self.old_mainHandCharges = mainHandCharges self.old_hasOffHandEnchant = hasOffHandEnchant self.old_offHandName = offHandName self.old_offHandExpiration = offHandExpiration self.old_offHandCharges = offHandCharges if ( self.UpdateTime > 0 ) then self.UpdateTime = self.UpdateTime - elapsed else self.UpdateTime = self.UpdateTime + TOOLTIP_UPDATE_TIME end self.FlashTime = self.FlashTime - elapsed if ( self.FlashTime < 0 ) then local overtime = -self.FlashTime if ( self.FlashState == 0 ) then self.FlashState = 1 self.FlashTime = BUFF_FLASH_TIME_ON else self.FlashState = 0 self.FlashTime = BUFF_FLASH_TIME_OFF end if ( overtime < self.FlashTime ) then self.FlashTime = self.FlashTime - overtime end end if ( self.FlashState == 1 ) then self.BuffAlphaValue = (BUFF_FLASH_TIME_ON - self.FlashTime) / BUFF_FLASH_TIME_ON else self.BuffAlphaValue = self.FlashTime / BUFF_FLASH_TIME_ON end self.BuffAlphaValue = ((self.BuffAlphaValue * (1 - BUFF_MIN_ALPHA)) + BUFF_MIN_ALPHA) * self.frame:GetAlpha() local mustupdate = nil for i = 1, self.numBuffsShown do local button = getglobal("ElkBuffButton"..i) local duration = getglobal("ElkBuffButton"..i.."DurationText") local bar = getglobal("ElkBuffButton"..i.."TimeBar") if button.untilCancelled ~= 1 then local timeleft = 0 if button.type == "BUFF" or button.type == "DEBUFF" then timeleft = GetPlayerBuffTimeLeft(button.id) elseif button.type == "WEAPON" then local hasMainHandEnchant, mainHandExpiration, mainHandCharges, hasOffHandEnchant, offHandExpiration, offHandCharges = GetWeaponEnchantInfo() if button.id == GetInventorySlotInfo("MainHandSlot") then timeleft = mainHandExpiration / 1000 end if button.id == GetInventorySlotInfo("SecondaryHandSlot") then timeleft = offHandExpiration / 1000 end end if ( timeleft < BUFF_WARNING_TIME ) then button:SetAlpha(self.BuffAlphaValue) else button:SetAlpha(self.frame:GetAlpha()) end if ElkBuffBarOptions.timer == "DEFAULT" then duration:SetText(SecondsToTimeAbbrev(timeleft)) duration:Show() elseif ElkBuffBarOptions.timer == "FULL" then local seconds = timeleft local temptime local time = "" if seconds >= 3600 then tempTime = floor(seconds / 3600) time = time..tempTime..":" seconds = mod(seconds, 3600) end if seconds >= 60 then tempTime = floor(seconds / 60) if time ~= "" and tempTime < 10 then time = time.."0"..tempTime..":" else time = time..tempTime..":" end seconds = mod(seconds, 60) end if seconds >= 0 then tempTime = format("%d", seconds) if time ~= "" and seconds < 10 then time = time.."0"..tempTime else time = time..tempTime end end duration:SetText(time) duration:Show() else duration:Hide() end bar:SetValue(timeleft) bar:Show() if button.timeleft < timeleft then mustupdate = true end button.timeleft = timeleft else duration:Hide() bar:Hide() end end if mustupdate then self:UpdateBuffs() end if ( self.UpdateTime > 0 ) then return end if ( GameTooltip:IsOwned(this) ) then self:ButtonOnEnter() end end function ElkBuffBar:ButtonOnEnter() if this.type == "BUFF" or this.type == "DEBUFF" then GameTooltip:SetOwner(this, "ANCHOR_BOTTOMLEFT") GameTooltip:SetPlayerBuff(this.id) elseif this.type == "WEAPON" then GameTooltip:SetOwner(this, "ANCHOR_BOTTOMLEFT") GameTooltip:SetInventoryItem("player", this.id) end end function ElkBuffBar:ButtonOnLeave() GameTooltip:Hide() end function ElkBuffBar:ButtonOnClick() if this.type == "BUFF" or this.type == "DEBUFF" then CancelPlayerBuff(this.id) end end function ElkBuffBar:StartMoving() if not self.Layout.locked then self.frame:StartMoving() end end function ElkBuffBar:StopMoving() self.frame:StopMovingOrSizing() if ElkBuffBarOptions.anchor == "TOPLEFT" then ElkBuffBarOptions.x = floor(self.frame:GetLeft() + .5) ElkBuffBarOptions.y = floor(self.frame:GetTop() + .5) elseif ElkBuffBarOptions.anchor == "TOPRIGHT" then ElkBuffBarOptions.x = floor(self.frame:GetRight() + .5) ElkBuffBarOptions.y = floor(self.frame:GetTop() + .5) elseif ElkBuffBarOptions.anchor == "BOTTOMLEFT" then ElkBuffBarOptions.x = floor(self.frame:GetLeft() + .5) ElkBuffBarOptions.y = floor(self.frame:GetBottom() + .5) elseif ElkBuffBarOptions.anchor == "BOTTOMRIGHT" then ElkBuffBarOptions.x = floor(self.frame:GetRight() + .5) ElkBuffBarOptions.y = floor(self.frame:GetBottom() + .5) end self:UpdateLayout() end function ElkBuffBar:UpdateLayout() if not self.Layout.width or self.Layout.width ~= ElkBuffBarOptions.width then self.frame:SetWidth(ElkBuffBarOptions.width) self.Layout.width = ElkBuffBarOptions.width end if not self.Layout.height or self.Layout.height ~= ElkBuffBarOptions.height then for i = 1, self.numBuffButtons do self:UpdateButtonHeight(i) end self.Layout.height = ElkBuffBarOptions.height end if not self.Layout.scale or self.Layout.scale ~= ElkBuffBarOptions.scale then self.frame:SetScale(ElkBuffBarOptions.scale) if self.Layout.scale and ElkBuffBarOptions.x and ElkBuffBarOptions.y then ElkBuffBarOptions.x = floor(ElkBuffBarOptions.x * self.Layout.scale / ElkBuffBarOptions.scale) ElkBuffBarOptions.y = floor(ElkBuffBarOptions.y * self.Layout.scale / ElkBuffBarOptions.scale) end self.Layout.scale = ElkBuffBarOptions.scale end if ElkBuffBarOptions.x and ElkBuffBarOptions.y and ((not self.Layout.x or self.Layout.x ~= ElkBuffBarOptions.x) or (not self.Layout.y or self.Layout.y ~= ElkBuffBarOptions.y) or (not self.Layout.anchor or self.Layout.anchor ~= ElkBuffBarOptions.anchor)) then if self.Layout.anchor and self.Layout.anchor ~= ElkBuffBarOptions.anchor then local x, y if self.Layout.anchor == "TOPLEFT" then x = ElkBuffBarOptions.x y = ElkBuffBarOptions.y - self.frame:GetHeight() elseif self.Layout.anchor == "TOPRIGHT" then x = ElkBuffBarOptions.x - self.frame:GetWidth() y = ElkBuffBarOptions.y - self.frame:GetHeight() elseif self.Layout.anchor == "BOTTOMLEFT" then x = ElkBuffBarOptions.x y = ElkBuffBarOptions.y elseif self.Layout.anchor == "BOTTOMRIGHT" then x = ElkBuffBarOptions.x - self.frame:GetWidth() y = ElkBuffBarOptions.y end if ElkBuffBarOptions.anchor == "TOPLEFT" then ElkBuffBarOptions.x = floor(x + .5) ElkBuffBarOptions.y = floor(y + self.frame:GetHeight() + .5) elseif ElkBuffBarOptions.anchor == "TOPRIGHT" then ElkBuffBarOptions.x = floor(x + self.frame:GetWidth() + .5) ElkBuffBarOptions.y = floor(y + self.frame:GetHeight() + .5) elseif ElkBuffBarOptions.anchor == "BOTTOMLEFT" then ElkBuffBarOptions.x = floor(x + .5) ElkBuffBarOptions.y = floor(y + .5) elseif ElkBuffBarOptions.anchor == "BOTTOMRIGHT" then ElkBuffBarOptions.x = floor(x + self.frame:GetWidth() + .5) ElkBuffBarOptions.y = floor(y + .5) end end self.frame:ClearAllPoints() self.frame:SetPoint(ElkBuffBarOptions.anchor, UIParent, "BOTTOMLEFT", ElkBuffBarOptions.x, ElkBuffBarOptions.y) self.Layout.x = ElkBuffBarOptions.x self.Layout.y = ElkBuffBarOptions.y self.Layout.anchor = ElkBuffBarOptions.anchor end if (not self.Layout.locked and ElkBuffBarOptions.locked) or (self.Layout.locked and not ElkBuffBarOptions.locked) then self.Layout.locked = ElkBuffBarOptions.locked end if not self.Layout.alpha or self.Layout.alpha ~= ElkBuffBarOptions.alpha then self.frame:SetAlpha(ElkBuffBarOptions.alpha) self.Layout.alpha = ElkBuffBarOptions.alpha end if not self.Layout.icon or self.Layout.icon ~= ElkBuffBarOptions.icon then for i = 1, self.numBuffButtons do self:UpdateButtonIcon(i) end self.Layout.icon = ElkBuffBarOptions.icon end if not self.Layout.sort or self.Layout.sort ~= ElkBuffBarOptions.sort then self:UpdateBuffs() self.Layout.sort = ElkBuffBarOptions.sort end if not self.Layout.timer or self.Layout.timer ~= ElkBuffBarOptions.timer then for i = 1, self.numBuffButtons do self:UpdateButtonTimer(i) end self.Layout.timer = ElkBuffBarOptions.timer end if (not self.Layout.invert and ElkBuffBarOptions.invert) or (self.Layout.invert and not ElkBuffBarOptions.invert) then self:UpdateButtonPositions() self.Layout.invert = ElkBuffBarOptions.invert end if not self.Layout.spacing or self.Layout.spacing ~= ElkBuffBarOptions.spacing then self:UpdateButtonPositions() self.Layout.spacing = ElkBuffBarOptions.spacing end if not self.Layout.group or self.Layout.group ~= ElkBuffBarOptions.group then self:UpdateButtonPositions() self.Layout.group = ElkBuffBarOptions.group end if not self.Layout.dbcolor or self.Layout.dbcolor ~= ElkBuffBarOptions.dbcolor then self:UpdateBuffs() self.Layout.dbcolor = ElkBuffBarOptions.dbcolor end end function ElkBuffBar:UpdateButtonHeight(buttonid) local button = getglobal("ElkBuffButton"..buttonid) local icon = getglobal("ElkBuffButton"..buttonid.."Icon") button:SetHeight(ElkBuffBarOptions.height) icon:SetWidth(ElkBuffBarOptions.height) icon:SetHeight(ElkBuffBarOptions.height) self:UpdateButtonIcon(buttonid) self:UpdateButtonPositions(true) end function ElkBuffBar:UpdateButtonIcon(buttonid) local button = getglobal("ElkBuffButton"..buttonid) local icon = getglobal("ElkBuffButton"..buttonid.."Icon") local bar = getglobal("ElkBuffButton"..buttonid.."TimeBar") if ElkBuffBarOptions.icon == "LEFT" then icon:ClearAllPoints() icon:SetPoint("TOPLEFT", button, "TOPLEFT") icon:Show() bar:ClearAllPoints() bar:SetPoint("TOPLEFT", button, "TOPLEFT", ElkBuffBarOptions.height, 0) bar:SetPoint("BOTTOMRIGHT", button, "BOTTOMRIGHT") elseif ElkBuffBarOptions.icon == "RIGHT" then icon:ClearAllPoints() icon:SetPoint("TOPRIGHT", button, "TOPRIGHT") icon:Show() bar:ClearAllPoints() bar:SetPoint("TOPLEFT", button, "TOPLEFT") bar:SetPoint("BOTTOMRIGHT", button, "BOTTOMRIGHT", -ElkBuffBarOptions.height, 0) else icon:Hide() bar:ClearAllPoints() bar:SetPoint("TOPLEFT", button, "TOPLEFT") bar:SetPoint("BOTTOMRIGHT", button, "BOTTOMRIGHT") end end function ElkBuffBar:UpdateButtonTimer(buttonid) local name = getglobal("ElkBuffButton"..buttonid.."DescribeText") local duration = getglobal("ElkBuffButton"..buttonid.."DurationText") if ElkBuffBarOptions.timer == "NONE" then name:SetPoint("RIGHT", -2, 0) duration:SetText("") duration:Hide() else name:SetPoint("RIGHT", -35, 0) duration:SetText("") duration:Show() end end function ElkBuffBar:UpdateButtonPosition(buttonid, space) local space = space or 0 local button = getglobal("ElkBuffButton"..buttonid) button:ClearAllPoints() button:SetPoint("LEFT", self.frame, "LEFT") button:SetPoint("RIGHT", self.frame, "RIGHT") if buttonid > 1 then if (ElkBuffBarOptions.invert) then button:SetPoint("BOTTOM", getglobal("ElkBuffButton"..(buttonid-1)), "TOP", 0, space) else button:SetPoint("TOP", getglobal("ElkBuffButton"..(buttonid-1)), "BOTTOM", 0, -space) end else if (ElkBuffBarOptions.invert) then button:SetPoint("BOTTOM", self.frame, "BOTTOM") else button:SetPoint("TOP", self.frame, "TOP") end end end function ElkBuffBar:UpdateButtonPositions(onlyheight) if self.numBuffsShown > 0 then local groupspacer = 0 local lasttype for i = 1, self.numBuffsShown do local button = getglobal("ElkBuffButton"..i) if lasttype and button.type ~= lasttype then if not onlyheight then self:UpdateButtonPosition(i, ElkBuffBarOptions.spacing + ElkBuffBarOptions.group) end groupspacer = groupspacer + 1 elseif not onlyheight then self:UpdateButtonPosition(i, ElkBuffBarOptions.spacing) end lasttype = button.type end self.frame:SetHeight(self.numBuffsShown * ElkBuffBarOptions.height + (self.numBuffsShown - 1) * ElkBuffBarOptions.spacing + groupspacer * ElkBuffBarOptions.group) else self.frame:SetHeight(ElkBuffBarOptions.height) end end function ElkBuffBar:SlashCommandHandler(msg) local _, _, carg1, carg2 = string.find(msg, "^([^ ]+)$") if not carg1 then _, _, carg1, carg2 = string.find(msg, "^([^ ]+)[ ]+([^ ]+)") end if carg1 then carg1 = string.lower(carg1) end -- print("|cffffff00[ElkBuffBar]|r msg is >|cffff0000"..(msg or "NIL").."|r<, carg1 is >|cffff0000"..(carg1 or "NIL").."|r<, carg2 is >|cffff0000"..(carg2 or "NIL").."|r<") if not carg1 then DEFAULT_CHAT_FRAME:AddMessage("|cffffff00[ElkBuffBar]|r command line options:") DEFAULT_CHAT_FRAME:AddMessage(" - reset : resets all values to default") DEFAULT_CHAT_FRAME:AddMessage(" - resetpos : resets position and scale to default") DEFAULT_CHAT_FRAME:AddMessage(" - width [100+] : sets the button's width (is |cffff0000"..ElkBuffBarOptions.width.."|r)") DEFAULT_CHAT_FRAME:AddMessage(" - height [10+] : sets the button's height (is |cffff0000"..ElkBuffBarOptions.height.."|r)") DEFAULT_CHAT_FRAME:AddMessage(" - scale [0.0+] : sets the button's scale (is |cffff0000"..ElkBuffBarOptions.scale.."|r)") DEFAULT_CHAT_FRAME:AddMessage(" - anchor [TOPLEFT/-RIGHT/BOTTOMLEFT/-RIGHT] : sets anchor (is |cffff0000"..ElkBuffBarOptions.anchor.."|r)") DEFAULT_CHAT_FRAME:AddMessage(" - locked [TRUE/FALSE] : toggles locked state (is |cffff0000"..(ElkBuffBarOptions.locked and "TRUE" or "FALSE").."|r)") DEFAULT_CHAT_FRAME:AddMessage(" - alpha [0.0-1.0] : sets the button's alpha value (is |cffff0000"..ElkBuffBarOptions.alpha.."|r)") DEFAULT_CHAT_FRAME:AddMessage(" - icon [LEFT/RIGHT/NONE] : sets the icon positions (is |cffff0000"..ElkBuffBarOptions.icon.."|r)") DEFAULT_CHAT_FRAME:AddMessage(" - sort [DEFAULT/TIMEMAX/TIMELEFT] : sets the sort style (is |cffff0000"..ElkBuffBarOptions.sort.."|r)") DEFAULT_CHAT_FRAME:AddMessage(" - timer [DEFAULT/NONE/FULL] : sets the timer style (is |cffff0000"..ElkBuffBarOptions.timer.."|r)") DEFAULT_CHAT_FRAME:AddMessage(" - invert [TRUE/FALSE] : toggles inverting of buffs (is |cffff0000"..(ElkBuffBarOptions.invert and "TRUE" or "FALSE").."|r)") DEFAULT_CHAT_FRAME:AddMessage(" - spacing [0+] : set space between bars (is |cffff0000"..ElkBuffBarOptions.spacing.."|r)") DEFAULT_CHAT_FRAME:AddMessage(" - group [0+] : set additionsl space between the buff groups (is |cffff0000"..ElkBuffBarOptions.group.."|r)") DEFAULT_CHAT_FRAME:AddMessage(" - dbcolor [TRUE/FALSE] : toggles type colored debuffs (is |cffff0000"..(ElkBuffBarOptions.dbcolor and "TRUE" or "FALSE").."|r)") elseif carg1 == "reset" then ElkBuffBarOptions = nil self:InitSettings() elseif carg1 == "resetpos" then ElkBuffBarOptions.scale = nil ElkBuffBarOptions.x = nil ElkBuffBarOptions.y = nil self:InitSettings() elseif carg1 == "width" then if carg2 then carg2 = floor(tonumber(carg2)) if carg2 < 100 then DEFAULT_CHAT_FRAME:AddMessage("|cffffff00[ElkBuffBar]|r WIDTH must be >= 100") else ElkBuffBarOptions.width = carg2 self:UpdateLayout() DEFAULT_CHAT_FRAME:AddMessage("|cffffff00[ElkBuffBar]|r WIDTH now set to |cffff0000"..ElkBuffBarOptions.width.."|r") end else DEFAULT_CHAT_FRAME:AddMessage("|cffffff00[ElkBuffBar]|r WIDTH is |cffff0000"..ElkBuffBarOptions.width.."|r") end elseif carg1 == "height" then if carg2 then carg2 = floor(tonumber(carg2)) if carg2 < 10 then DEFAULT_CHAT_FRAME:AddMessage("|cffffff00[ElkBuffBar]|r HEIGHT must be >= 10") else ElkBuffBarOptions.height = carg2 self:UpdateLayout() DEFAULT_CHAT_FRAME:AddMessage("|cffffff00[ElkBuffBar]|r HEIGHT now set to |cffff0000"..ElkBuffBarOptions.height.."|r") end else DEFAULT_CHAT_FRAME:AddMessage("|cffffff00[ElkBuffBar]|r HEIGHT is |cffff0000"..ElkBuffBarOptions.height.."|r") end elseif carg1 == "scale" then if carg2 then carg2 = tonumber(carg2) if carg2 <= 0 then DEFAULT_CHAT_FRAME:AddMessage("|cffffff00[ElkBuffBar]|r SCALE must be > 0.0") else ElkBuffBarOptions.scale = carg2 self:UpdateLayout() DEFAULT_CHAT_FRAME:AddMessage("|cffffff00[ElkBuffBar]|r SCALE now set to |cffff0000"..ElkBuffBarOptions.scale.."|r") end else DEFAULT_CHAT_FRAME:AddMessage("|cffffff00[ElkBuffBar]|r SCALE is |cffff0000"..ElkBuffBarOptions.scale.."|r") end elseif carg1 == "anchor" then if carg2 then carg2 = string.upper(carg2) if carg2 ~= "TOPLEFT" and carg2 ~= "TOPRIGHT" and carg2 ~= "BOTTOMLEFT" and carg2 ~= "BOTTOMRIGHT" then DEFAULT_CHAT_FRAME:AddMessage("|cffffff00[ElkBuffBar]|r ANCHOR must be TOPLEFT, TOPRIGHT, BOTTOMLEFT or BOTTOMRIGHT") else ElkBuffBarOptions.anchor = carg2 self:UpdateLayout() DEFAULT_CHAT_FRAME:AddMessage("|cffffff00[ElkBuffBar]|r ANCHOR now set to |cffff0000"..ElkBuffBarOptions.anchor.."|r") end else DEFAULT_CHAT_FRAME:AddMessage("|cffffff00[ElkBuffBar]|r ANCHOR is |cffff0000"..ElkBuffBarOptions.anchor.."|r") end elseif carg1 == "locked" then if carg2 then carg2 = string.lower(carg2) if carg2 ~= "true" and carg2 ~= "false" then DEFAULT_CHAT_FRAME:AddMessage("|cffffff00[ElkBuffBar]|r LOCKED must be TRUE or FALSE") else if carg2 == "true" then ElkBuffBarOptions.locked = true else ElkBuffBarOptions.locked = nil end self:UpdateLayout() DEFAULT_CHAT_FRAME:AddMessage("|cffffff00[ElkBuffBar]|r LOCKED now set to |cffff0000"..(ElkBuffBarOptions.locked and "TRUE" or "FALSE").."|r") end else DEFAULT_CHAT_FRAME:AddMessage("|cffffff00[ElkBuffBar]|r LOCKED is |cffff0000"..(ElkBuffBarOptions.locked and "TRUE" or "FALSE").."|r") end elseif carg1 == "alpha" then if carg2 then carg2 = tonumber(carg2) if carg2 < 0 or carg2 > 1 then DEFAULT_CHAT_FRAME:AddMessage("|cffffff00[ElkBuffBar]|r ALPHA must be >= 0.0 and <= 1.0") else ElkBuffBarOptions.alpha = carg2 self:UpdateLayout() DEFAULT_CHAT_FRAME:AddMessage("|cffffff00[ElkBuffBar]|r ALPHA now set to |cffff0000"..ElkBuffBarOptions.alpha.."|r") end else DEFAULT_CHAT_FRAME:AddMessage("|cffffff00[ElkBuffBar]|r ALPHA is |cffff0000"..ElkBuffBarOptions.alpha.."|r") end elseif carg1 == "icon" then if carg2 then carg2 = string.upper(carg2) if carg2 ~= "LEFT" and carg2 ~= "RIGHT" and carg2 ~= "NONE" then DEFAULT_CHAT_FRAME:AddMessage("|cffffff00[ElkBuffBar]|r ICON must be LEFT, RIGHT or NONE") else ElkBuffBarOptions.icon = carg2 self:UpdateLayout() DEFAULT_CHAT_FRAME:AddMessage("|cffffff00[ElkBuffBar]|r ICON now set to |cffff0000"..ElkBuffBarOptions.icon.."|r") end else DEFAULT_CHAT_FRAME:AddMessage("|cffffff00[ElkBuffBar]|r ICON is |cffff0000"..ElkBuffBarOptions.icon.."|r") end elseif carg1 == "sort" then if carg2 then carg2 = string.upper(carg2) if carg2 ~= "DEFAULT" and carg2 ~= "TIMEMAX" and carg2 ~= "TIMELEFT" then DEFAULT_CHAT_FRAME:AddMessage("|cffffff00[ElkBuffBar]|r SORT must be DEFAULT, TIMEMAX or TIMELEFT") else ElkBuffBarOptions.sort = carg2 self:UpdateLayout() DEFAULT_CHAT_FRAME:AddMessage("|cffffff00[ElkBuffBar]|r SORT now set to |cffff0000"..ElkBuffBarOptions.sort.."|r") end else DEFAULT_CHAT_FRAME:AddMessage("|cffffff00[ElkBuffBar]|r SORT is |cffff0000"..ElkBuffBarOptions.sort.."|r") end elseif carg1 == "timer" then if carg2 then carg2 = string.upper(carg2) if carg2 ~= "DEFAULT" and carg2 ~= "NONE" and carg2 ~= "FULL" then DEFAULT_CHAT_FRAME:AddMessage("|cffffff00[ElkBuffBar]|r TIMER must be DEFAULT, NONE or FULL") else ElkBuffBarOptions.timer = carg2 self:UpdateLayout() DEFAULT_CHAT_FRAME:AddMessage("|cffffff00[ElkBuffBar]|r TIMER now set to |cffff0000"..ElkBuffBarOptions.timer.."|r") end else DEFAULT_CHAT_FRAME:AddMessage("|cffffff00[ElkBuffBar]|r TIMER is |cffff0000"..ElkBuffBarOptions.timer.."|r") end elseif carg1 == "invert" then if carg2 then carg2 = string.lower(carg2) if carg2 ~= "true" and carg2 ~= "false" then DEFAULT_CHAT_FRAME:AddMessage("|cffffff00[ElkBuffBar]|r INVERT must be TRUE or FALSE") else if carg2 == "true" then ElkBuffBarOptions.invert = true else ElkBuffBarOptions.invert = nil end self:UpdateLayout() DEFAULT_CHAT_FRAME:AddMessage("|cffffff00[ElkBuffBar]|r INVERT now set to |cffff0000"..(ElkBuffBarOptions.invert and "TRUE" or "FALSE").."|r") end else DEFAULT_CHAT_FRAME:AddMessage("|cffffff00[ElkBuffBar]|r INVERT is |cffff0000"..(ElkBuffBarOptions.invert and "TRUE" or "FALSE").."|r") end elseif carg1 == "spacing" then if carg2 then carg2 = floor(tonumber(carg2)) if carg2 < 0 then DEFAULT_CHAT_FRAME:AddMessage("|cffffff00[ElkBuffBar]|r SPACING must be >= 0") else ElkBuffBarOptions.spacing = carg2 self:UpdateLayout() DEFAULT_CHAT_FRAME:AddMessage("|cffffff00[ElkBuffBar]|r SPACING now set to |cffff0000"..ElkBuffBarOptions.spacing.."|r") end else DEFAULT_CHAT_FRAME:AddMessage("|cffffff00[ElkBuffBar]|r SPACING is |cffff0000"..ElkBuffBarOptions.spacing.."|r") end elseif carg1 == "group" then if carg2 then carg2 = floor(tonumber(carg2)) if carg2 < 0 then DEFAULT_CHAT_FRAME:AddMessage("|cffffff00[ElkBuffBar]|r GROUP must be >= 0") else ElkBuffBarOptions.group = carg2 self:UpdateLayout() DEFAULT_CHAT_FRAME:AddMessage("|cffffff00[ElkBuffBar]|r GROUP now set to |cffff0000"..ElkBuffBarOptions.group.."|r") end else DEFAULT_CHAT_FRAME:AddMessage("|cffffff00[ElkBuffBar]|r GROUP is |cffff0000"..ElkBuffBarOptions.group.."|r") end elseif carg1 == "dbcolor" then if carg2 then carg2 = string.lower(carg2) if carg2 ~= "true" and carg2 ~= "false" then DEFAULT_CHAT_FRAME:AddMessage("|cffffff00[ElkBuffBar]|r DBCOLOR must be TRUE or FALSE") else if carg2 == "true" then ElkBuffBarOptions.dbcolor = true else ElkBuffBarOptions.dbcolor = nil end self:UpdateLayout() DEFAULT_CHAT_FRAME:AddMessage("|cffffff00[ElkBuffBar]|r DBCOLOR now set to |cffff0000"..(ElkBuffBarOptions.dbcolor and "TRUE" or "FALSE").."|r") end else DEFAULT_CHAT_FRAME:AddMessage("|cffffff00[ElkBuffBar]|r DBCOLOR is |cffff0000"..(ElkBuffBarOptions.dbcolor and "TRUE" or "FALSE").."|r") end else DEFAULT_CHAT_FRAME:AddMessage("|cffffff00[ElkBuffBar]|r "..carg1.." is no valid parameter.") end end ElkBuffBar:Init()