guSB = CreateFrame("Frame","guSB")
guSB:SetScript("OnEvent", function(self, event, ...)
self[event](self, event, ...)
end)
guSB:RegisterEvent("ADDON_LOADED")
local buffs = {}
local debuffs = {}
local wench = {}
local auras = {wench,buffs,debuffs}
local buffs_anchor, debuffs_anchor, cons_frame
local cons_num, cons_btn
local consolidatedbtn = {}
local consolidated = {}
local arset = {}
local defaults = {
buffs_point = "TOPRIGHT",
buffs_x = -150,
buffs_y = -10,
debuffs_point = "TOPRIGHT",
debuffs_x = -133,
debuffs_y = -138,
growthy = "BOTTOM",
growthx = "LEFT",
orientation = "HORIZONTAL",
maxlength = 16,
gap = 5,
width = 30,
height = 25,
hideblizzard = true,
consolidate = true,
}
local function Flip(p1,x,y)
local p2 = ""
local dir
if p1 == "CENTER" then return "CENTER" end
if string.find(p1,"TOP") then p2 = p2..(y and "BOTTOM" or "TOP")end
if string.find(p1,"BOTTOM") then p2 = p2..(y and "TOP" or "BOTTOM") end
if string.find(p1,"LEFT") then p2 = p2..(x and "RIGHT" or "LEFT") end
if string.find(p1,"RIGHT") then p2 = p2..(x and "LEFT" or "RIGHT") end
if p2 == "RIGHT" or p2 == "LEFT" then
dir = "HORIZONTAL"
elseif p2 == "TOP" or p2 == "BOTTOM" then
dir = "VERTICAL"
end
return p2, dir
end
function guSB.ADDON_LOADED(self,event,arg1)
if arg1 == "guSmallBuffs" then
gusbDB = gusbDB or {}
gusbDB.cons_ids = gusbDB.cons_ids or {}
gusbDB = setmetatable(gusbDB,{ __index = function(t,k) return defaults[k] end})
guSB:UpdateLayoutSettings()
buffs_anchor = self:CreateAnchor("buffs")
debuffs_anchor = self:CreateAnchor("debuffs")
guSB:RegisterEvent("UNIT_AURA")
if gusbDB.hideblizzard then
BuffFrame:UnregisterEvent("UNIT_AURA")
BuffFrame:Hide()
ConsolidatedBuffs.Show = ConsolidatedBuffs.Hide
ConsolidatedBuffs:Hide()
TemporaryEnchantFrame:Hide()
end
if gusbDB.consolidate then
cons_btn = guSB:MakeConsButton()
table.insert(auras, 1, consolidatedbtn)
table.insert(auras, consolidated)
consolidatedbtn[1] = cons_btn
cons_frame = guSB:MakeConsolidatedFrame(cons_btn)
end
guSB.CheckWeaponEnchants(self)
guSB:UNIT_AURA(nil, "player")
SLASH_GUSB1= "/gusb"
SLASH_GUSB2= "/gusmallbuffs"
SlashCmdList["GUSB"] = guSB.SlashCmd
end
end
function guSB.UNIT_AURA(self, event, unit)
if unit ~= "player" then return end
if gusbDB.consolidate then
cons_num = 0
for i,btn in pairs(consolidated) do
consolidated[i] = nil
end
end
local name, rank, icon, count, dispelType, duration, expires, caster, isStealable, shouldConsolidate, spellID
for i=1, BUFF_MAX_DISPLAY do
name, rank, icon, count, dispelType, duration, expires, caster, isStealable, shouldConsolidate, spellID = UnitAura("player",i,"HELPFUL")
if not name then
for j=i,BUFF_MAX_DISPLAY do
if buffs[j] then buffs[j]:Hide()
else break end
end
break
end
if not buffs[i] then
local btn = self:CreateBuffIcon("buff")
btn.id = i
buffs[i] = btn
end
local btn = buffs[i]
btn.icon:SetTexture(icon)
btn.bar:SetMinMaxValues(0, duration)
btn.count:SetText(count)
if count > 1 then btn.count:Show() else btn.count:Hide() end
btn.duration = duration
btn.expires = expires
btn.OnUpdateCounter = 1
btn:Show()
if btn.SetAttribute then
btn:SetAttribute("index", i)
end
if gusbDB.consolidate then
if shouldConsolidate then
consolidated[i] = btn
btn:SetParent(cons_frame)
cons_num = cons_num + 1
else
btn:SetParent(UIParent)
end
end
end
for i=1, DEBUFF_MAX_DISPLAY do
name, rank, icon, count, dispelType, duration, expires, caster, isStealable, shouldConsolidate, spellID = UnitAura("player",i,"HARMFUL")
if not name then
for j=i,DEBUFF_MAX_DISPLAY do
if debuffs[j] then debuffs[j]:Hide()
else break end
end
break
end
if not debuffs[i] then
local btn = self:CreateBuffIcon("debuff")
btn.id = i
debuffs[i] = btn
end
local btn = debuffs[i]
btn.icon:SetTexture(icon)
local color
if ( dispelType ) then
color = DebuffTypeColor[dispelType];
else
color = DebuffTypeColor["none"];
end
btn:SetBackdropColor(color.r,color.g,color.b)
btn.bar:SetMinMaxValues(0, duration)
btn.duration = duration
btn.count:SetText(count)
if count > 1 then btn.count:Show() else btn.count:Hide() end
btn.expires = expires
btn.OnUpdateCounter = 1
btn:Show()
end
if gusbDB.consolidate then
cons_btn.count:SetText(cons_num)
if cons_num > 0 then cons_btn:Show() else cons_btn:Hide() end
if cons_frame:IsShown() then cons_frame:ResizeFrame() end
end
guSB:ArrangeIcons()
end
function guSB.UpdateLayoutSettings(self)
arset.gxdir = (gusbDB.growthx == "LEFT" and -1 or 1)
arset.gydir = (gusbDB.growthy == "BOTTOM" and -1 or 1)
arset.stepx = (gusbDB.orientation == "HORIZONTAL" and 1 or 0) * arset.gxdir * gusbDB.gap
arset.stepy = (gusbDB.orientation == "VERTICAL" and 1 or 0) * arset.gydir * gusbDB.gap
arset.point = Flip(gusbDB.growthy..gusbDB.growthx, true, true)
arset.to = Flip(arset.point,(arset.stepx ~= 0),(arset.stepy ~= 0))
arset.newrowto = Flip(arset.point,(arset.stepy ~= 0),(arset.stepx ~= 0))
arset.max = gusbDB.maxlength
for _, icons in pairs(auras) do
for id,btn in pairs(icons) do
btn:SetWidth(gusbDB.width)
btn:SetHeight(gusbDB.height)
btn.icon:SetWidth(gusbDB.height)
btn.icon:SetHeight(gusbDB.height)
btn.bar:SetWidth(gusbDB.width - gusbDB.height - 2)
btn.bar:SetHeight(gusbDB.height)
btn:ClearAllPoints()
end
end
end
function guSB.ArrangeIcons(self)
local prev, prevcol
local placed = 1
local gxdir = arset.gxdir
local gydir = arset.gydir
local stepx = arset.stepx
local stepy = arset.stepy
local point = arset.point
local to = arset.to
local newrowto = arset.newrowto
local max = arset.max
for _, icons in ipairs(auras) do
if icons == debuffs then
prev = debuffs_anchor
placed = 1
elseif icons == consolidated then
prev = cons_frame
max = 3
placed = 1
elseif not prev then
prev = buffs_anchor
end
for id,btn in pairs(icons) do
local btn = icons[id]
if not btn:IsShown() then break end
if icons ~= buffs or not consolidated[id] then
if placed > 1 and select(2,math.modf((placed-1)/max)) == 0 then
btn:SetPoint(point,prevcol,newrowto, math.abs(stepy)*gxdir, math.abs(stepx)*gydir )
prevcol = btn
else
if placed == 1 then prevcol = btn end
btn:SetPoint(point,prev,to, stepx, stepy)
end
if placed == 1 and icons == consolidated then
btn:SetPoint(arset.point,cons_frame,arset.point,0,0)
end
placed = placed + 1
prev = btn
end
end
end
end
local function AuraOnUpdate(self,time)
self.OnUpdateCounter = (self.OnUpdateCounter or 0) + time
if self.OnUpdateCounter < 0.2 then return end
self.OnUpdateCounter = 0
local left = self.expires - GetTime()
self.bar:SetValue(left)
local r,g,b
local duration = self.duration
if duration == 0 and self.expires == 0 then
r,g,b = 1,0.5,0.9
self.bar:SetValue(1)
else
if left > duration / 2 then
r,g,b = (duration - left)*2/duration, 1, 0
else
r,g,b = 1, left*2/duration, 0
end
end
self.bar:SetStatusBarColor(r,g,b)
self.bar.bg:SetVertexColor(r/2,g/2,b/2)
end
function guSB.CreateBuffIcon(self, auratype)
local backdrop = {
bgFile = "Interface\\Tooltips\\UI-Tooltip-Background", tile = true, tileSize = 0,
insets = {left = -2, right = -2, top = -2, bottom = -2},
}
local f = CreateFrame("Button",nil,UIParent, "SecureActionButtonTemplate")
local width = gusbDB.width
local height = gusbDB.height
f:SetWidth(width)
f:SetHeight(height)
f:SetBackdrop(backdrop)
f:SetBackdropColor(0, 0, 0, 0.7)
f.icon = f:CreateTexture(nil,"ARTWORK")
f.icon:SetTexCoord(.07, .93, .07, .93)
f.icon:SetWidth(height)
f.icon:SetHeight(height)
f.icon:SetPoint("TOP", 0, 0)
f.icon:SetPoint("RIGHT", 0, 0)
f.count = f:CreateFontString(nil, "OVERLAY")
f.count:SetFont("Fonts\\FRIZQT__.TTF",13,"OUTLINE")
f.count:SetJustifyH("RIGHT")
f.count:SetVertexColor(1,1,1)
f.count:SetPoint("BOTTOMRIGHT",f.icon,"BOTTOMRIGHT",0,0)
f.count:Hide()
local bar = CreateFrame("StatusBar", nil, f)
bar:SetStatusBarTexture[[Interface\AddOns\guSmallBuffs\white.tga]]
bar:SetWidth(width - height - 2)
bar:SetHeight(height)
bar:SetOrientation("VERTICAL")
bar:SetMinMaxValues(0,100)
bar:SetValue(50)
bar:SetPoint("TOPLEFT",f,"TOPLEFT",0,0)
bar:SetStatusBarColor(1,0,0)
f.bar = bar
local bbg = bar:CreateTexture(nil,"BACKGROUND")
bbg:SetTexture[[Interface\AddOns\guSmallBuffs\white.tga]]
bbg:SetAllPoints(bar)
bbg:SetVertexColor(0.4,0,0)
f.bar.bg = bbg
--f:EnableMouse(true)
if auratype == "buff" then
f:RegisterForClicks("RightButtonUp")
--f:SetScript("OnClick",function(self,button)
--CancelUnitBuff("player", self.id, self.filter)
--end)
f:RegisterForClicks("RightButtonUp")
f.Secure = true
-- Setup stuff for clicking off buffs
f:SetAttribute("type", "cancelaura" )
f:SetAttribute("unit", "player")
end
f.filter = (auratype == "buff") and "HELPFUL" or "HARMFUL"
f:SetScript("OnEnter",function(self)
GameTooltip:SetOwner(self, "ANCHOR_BOTTOMLEFT")
GameTooltip:SetUnitAura("player", self.id, self.filter)
end)
f:SetScript("OnLeave",function(self)
GameTooltip:Hide()
end)
f:SetScript("OnUpdate",AuraOnUpdate)
f:Show()
return f
end
function guSB.CreateAnchor(self,tbl)
local f = CreateFrame("Button",nil,UIParent)
local width = gusbDB.width
local height = gusbDB.height
f:SetWidth(width)
f:SetHeight(height)
f:SetBackdrop({
bgFile = "Interface\\Tooltips\\UI-Tooltip-Background", tile = true, tileSize = 0,
insets = {left = -2, right = -2, top = -2, bottom = -2},
})
f:SetBackdropColor(0, 1, 0, 1)
f:RegisterForDrag("LeftButton")
f:EnableMouse(true)
f:SetMovable(true)
f:SetFrameStrata("HIGH")
f:SetFrameLevel(2)
f:SetScript("OnDragStart",function(self) self:StartMoving() end)
f:SetScript("OnDragStop",function(self)
self:StopMovingOrSizing();
_,_, gusbDB[tbl.."_point"], gusbDB[tbl.."_x"], gusbDB[tbl.."_y"] = self:GetPoint(1)
end)
f.SetPos = function(self,point, x, y )
gusbDB[tbl.."_point"] = point
gusbDB[tbl.."_x"] = x
gusbDB[tbl.."_y"] = y
self:ClearAllPoints()
self:SetPoint(point, UIParent, point, x, y)
end
f:SetPos(gusbDB[tbl.."_point"], gusbDB[tbl.."_x"], gusbDB[tbl.."_y"])
f:Hide()
return f
end
function guSB.MakeConsolidatedFrame(self, cbtn)
local f = CreateFrame("Frame",nil,UIParent)
f:SetBackdrop({
bgFile = "Interface\\Tooltips\\UI-Tooltip-Background", tile = true, tileSize = 0,
insets = {left = -5, right = -5, top = -5, bottom = -5},
})
f:SetBackdropColor(0, 0, 0, 0.85)
f:SetFrameLevel(5)
f:SetPoint(arset.point,cbtn,Flip(arset.point, (arset.stepx == 0), (arset.stepy == 0)),0,0)
f:SetWidth(1)
f:SetHeight(1)
f.ResizeFrame = function(self)
local num = 0
local button = select(2,next(consolidated))
if not button then return end
for id, btn in pairs(consolidated) do
num = num + 1
end
local i,f = math.modf(num/3)
local hr = i + (f > 0 and 1 or 0)
local wr = i > 0 and 3 or num
local hf = (arset.stepx == 0) and "SetWidth" or "SetHeight"
local wf = (arset.stepx == 0) and "SetHeight" or "SetWidth"
local ghf = hf == "SetWidth" and "GetWidth" or "GetHeight"
local gwf = wf == "SetWidth" and "GetWidth" or "GetHeight"
self[hf](self,hr*button[ghf](button) + (hr-1)*gusbDB.gap)
self[wf](self,wr*button[gwf](button) + (wr-1)*gusbDB.gap)
end
f:SetScript("OnShow", f.ResizeFrame)
f.fadeOnUpdate = function(self,time)
self.timeElapsed = (self.timeElapsed or 0) + time
if self.timeElapsed > 3 then
self:Hide()
self:SetScript("OnUpdate",nil)
self.timeElapsed = 0
end
end
f:Hide()
return f
end
function guSB.MakeConsButton(self)
local btn = self:CreateBuffIcon("debuff")
btn.icon:SetTexture("Interface\\Buttons\\BuffConsolidation")
btn.icon:SetTexCoord(0.15, 0.35, 0.3, 0.7)
btn:SetScript("OnUpdate",nil)
btn:SetScript("OnEnter",function () cons_frame:Show(); end)
btn:SetScript("OnLeave",function () cons_frame:SetScript("OnUpdate",cons_frame.fadeOnUpdate) end)
btn.bar:SetStatusBarColor(1,0.5,0.5)
btn.bar:SetValue(100)
btn.count:Show()
btn:Show()
return btn
end
function guSB.MutateToWeaponEnchant(f, id)
f.id = id
f:SetBackdropColor(0.5,0.2,0.85,1)
f:SetScript("OnEnter",function(self)
GameTooltip:SetOwner(self, "ANCHOR_BOTTOMRIGHT")
GameTooltip:SetInventoryItem("player", self.id)
end)
f:SetScript("OnClick",function(self)
CancelItemTempEnchantment(self.id - 15); -- should be 1 for mh
guSB:CheckWeaponEnchants()
end)
f.duration = 3600
f.bar:SetMinMaxValues(0,f.duration)
f:Hide()
return f
end
function guSB.CheckWeaponEnchants(self)
local hasMainHandEnchant, mainHandExpiration, mainHandCharges, hasOffHandEnchant, offHandExpiration, offHandCharges = GetWeaponEnchantInfo();
if ( hasOffHandEnchant ) then
if not wench[2] then
local btn = guSB:CreateBuffIcon("weapon")
guSB.MutateToWeaponEnchant(btn, 17)
wench[2] = btn
end
wench[2].icon:SetTexture(GetInventoryItemTexture("player", 17))
wench[2].expires = offHandExpiration/1000+GetTime()
if not wench[2]:IsShown()then
wench[2]:Show()
guSB:ArrangeIcons()
end
else
if wench[2] then if wench[2]:IsShown() then wench[2]:Hide() guSB:ArrangeIcons() end end
end
if ( hasMainHandEnchant ) then
if not wench[1] then
local btn = guSB:CreateBuffIcon("weapon")
guSB.MutateToWeaponEnchant(btn, 16)
wench[1] = btn
end
wench[1].icon:SetTexture(GetInventoryItemTexture("player", 16))
wench[1].expires = mainHandExpiration/1000+GetTime()
if not wench[1]:IsShown()then
wench[1]:Show()
guSB:ArrangeIcons()
end
else
if wench[1] then if wench[1]:IsShown() then wench[1]:Hide() guSB:ArrangeIcons() end end
end
end
CreateFrame("Frame",nil):SetScript("OnUpdate",function(self,time)
self.OnUpdateCounter = (self.OnUpdateCounter or 1) + time
if self.OnUpdateCounter < 1 then return end
self.OnUpdateCounter = 0
guSB:CheckWeaponEnchants()
end)
local ParseOpts = function(str)
local fields = {}
for opt,args in string.gmatch(str,"(%w*)%s*=%s*([%w%,%-%_%.%:%\\%']+)") do
fields[opt:lower()] = tonumber(args) or string.upper(args)
end
return fields
end
function guSB.SlashCmd(msg)
k,v = string.match(msg, "([%w%+%-%=]+) ?(.*)")
if not k or k == "help" then print([[Usage:
|cffff99bb/gusb set|r width=26 height=20 growthx=left/right growthy=top/bottom maxlength=16 gap=5 orientation=vertical/horizontal
|cffff99bb/gusb opts|r : display current settings
|cffff99bb/gusb hideblizz|r
|cffff99bb/gusb consolidate|r
|cffff99bb/gusb lock|r
|cffff99bb/gusb unlock|r ]]
)end
if k == "opts" then
print ("Width: "..gusbDB.width)
print ("Height: "..gusbDB.height)
print ("Growth-X: "..gusbDB.growthx)
print ("Growth-Y: "..gusbDB.growthy)
print ("Orientation: "..gusbDB.orientation)
print ("Max length: "..gusbDB.maxlength)
print ("Gap: "..gusbDB.gap)
print ("Hide Blizzard frames: "..(gusbDB.hideblizzard and "true" or "false"))
print ("Consolidate Buffs: "..(gusbDB.consolidate and "true" or "false"))
end
if k == "set" then
local p = ParseOpts(v)
gusbDB.width = p["width"] or gusbDB.width
gusbDB.height = p["height"] or gusbDB.height
gusbDB.growthx = p["growthx"] or gusbDB.growthx
gusbDB.growthy = p["growthy"] or gusbDB.growthy
gusbDB.orientation = p["orientation"] or gusbDB.orientation
gusbDB.maxlength = p["maxlength"] or gusbDB.maxlength
gusbDB.gap = p["gap"] or gusbDB.gap
guSB:UpdateLayoutSettings()
guSB:ArrangeIcons()
end
if k == "hideblizz" then
gusbDB.hideblizzard = not gusbDB.hideblizzard
print('Changes will take effect after reloadui')
end
if k == "consolidate" then
gusbDB.consolidate = not gusbDB.consolidate
print("Consolidated Buffs "..(gusbDB.consolidate and "enabled" or "disabled"))
print('Changes will take effect after reloadui')
end
if k == "unlock" then
buffs_anchor:Show()
debuffs_anchor:Show()
end
if k == "lock" then
buffs_anchor:Hide()
debuffs_anchor:Hide()
end
end