diff --git a/2/3/4/5/6/7/ElvUI/Modules/Auras/Auras.lua b/2/3/4/5/6/7/ElvUI/Modules/Auras/Auras.lua
new file mode 100644
index 0000000..28e1be2
--- /dev/null
+++ b/2/3/4/5/6/7/ElvUI/Modules/Auras/Auras.lua
@@ -0,0 +1,511 @@
+local E, L, V, P, G = unpack(ElvUI); --Inport: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
+local A = E:NewModule("Auras", "AceEvent-3.0");
+local LSM = LibStub("LibSharedMedia-3.0");
+
+--Cache global variables
+--Lua functions
+local GetTime = GetTime
+local _G = _G
+local unpack, select, pairs, ipairs = unpack, select, pairs, ipairs
+local floor, min, max, huge = math.floor, math.min, math.max, math.huge
+local format = string.format
+local wipe, tinsert, tsort, tremove = table.wipe, table.insert, table.sort, table.remove
+--WoW API / Variables
+local CreateFrame = CreateFrame
+local UnitAura = UnitAura
+local CancelItemTempEnchantment = CancelItemTempEnchantment
+local CancelUnitBuff = CancelUnitBuff
+local GetInventoryItemQuality = GetInventoryItemQuality
+local GetItemQualityColor = GetItemQualityColor
+local GetWeaponEnchantInfo = GetWeaponEnchantInfo
+local GetInventoryItemTexture = GetInventoryItemTexture
+
+local DIRECTION_TO_POINT = {
+ DOWN_RIGHT = "TOPLEFT",
+ DOWN_LEFT = "TOPRIGHT",
+ UP_RIGHT = "BOTTOMLEFT",
+ UP_LEFT = "BOTTOMRIGHT",
+ RIGHT_DOWN = "TOPLEFT",
+ RIGHT_UP = "BOTTOMLEFT",
+ LEFT_DOWN = "TOPRIGHT",
+ LEFT_UP = "BOTTOMRIGHT"
+}
+
+local DIRECTION_TO_HORIZONTAL_SPACING_MULTIPLIER = {
+ DOWN_RIGHT = 1,
+ DOWN_LEFT = -1,
+ UP_RIGHT = 1,
+ UP_LEFT = -1,
+ RIGHT_DOWN = 1,
+ RIGHT_UP = 1,
+ LEFT_DOWN = -1,
+ LEFT_UP = -1
+}
+
+local DIRECTION_TO_VERTICAL_SPACING_MULTIPLIER = {
+ DOWN_RIGHT = -1,
+ DOWN_LEFT = -1,
+ UP_RIGHT = 1,
+ UP_LEFT = 1,
+ RIGHT_DOWN = -1,
+ RIGHT_UP = 1,
+ LEFT_DOWN = -1,
+ LEFT_UP = 1
+}
+
+local IS_HORIZONTAL_GROWTH = {
+ RIGHT_DOWN = true,
+ RIGHT_UP = true,
+ LEFT_DOWN = true,
+ LEFT_UP = true
+}
+
+function A:UpdateTime(elapsed)
+ if self.offset then
+ local expiration = select(self.offset, GetWeaponEnchantInfo())
+ if expiration then
+ self.timeLeft = expiration / 1e3
+ else
+ self.timeLeft = 0
+ end
+ else
+ self.timeLeft = self.timeLeft - elapsed
+ end
+
+ if self.nextUpdate > 0 then
+ self.nextUpdate = not self.offset and self.nextUpdate - elapsed or 1
+ return
+ end
+
+ local timerValue, formatID
+ timerValue, formatID, self.nextUpdate = E:GetTimeInfo(self.timeLeft, A.db.fadeThreshold)
+ --print(timervalue)
+ --self.time:SetText(format("%s%s|r", E.TimeColors[formatID], format(E.TimeFormats[formatID][2], timervalue)))
+
+ if self.timeLeft > E.db.auras.fadeThreshold then
+ -- E:StopFlash(self)
+ else
+ -- E:Flash(self, 1)
+ end
+end
+
+local UpdateTooltip = function(self)
+ if self.offset then
+ GameTooltip:SetInventoryItem("player", self.offset == 2 and 16 or 17)
+ else
+ GameTooltip:SetUnitAura("player", self:GetID(), self:GetParent().filter)
+ end
+end
+
+local OnEnter = function(self)
+ if not self:IsVisible() then return end
+
+ GameTooltip:SetOwner(self, "ANCHOR_BOTTOMLEFT", -5, -5)
+ self:UpdateTooltip()
+end
+
+local OnLeave = function()
+ GameTooltip:Hide()
+end
+
+local OnClick = function(self)
+ if self.offset then
+ if self.offset == 2 then
+ CancelPlayerBuff(17)
+ elseif self.offset == 5 then
+ CancelPlayerBuff(16)
+ end
+ else
+ CancelUnitBuff("player", self:GetID(), self:GetParent().filter)
+ end
+end
+
+function A:CreateIcon(button)
+ local font = LSM:Fetch("font", self.db.font)
+ button:RegisterForClicks("RightButtonUp")
+
+ button.texture = button:CreateTexture(nil, "BORDER")
+ E:SetInside(button.texture)
+ button.texture:SetTexCoord(unpack(E.TexCoords))
+
+ button.count = button:CreateFontString(nil, "ARTWORK")
+ button.count:SetPoint("BOTTOMRIGHT", -1 + self.db.countXOffset, 1 + self.db.countYOffset)
+ E:FontTemplate(button.count, font, self.db.fontSize, self.db.fontOutline)
+
+ button.time = button:CreateFontString(nil, "ARTWORK")
+ button.time:SetPoint("TOP", button, "BOTTOM", 1 + self.db.timeXOffset, 0 + self.db.timeYOffset)
+ E:FontTemplate(button.time, font, self.db.fontSize, self.db.fontOutline)
+
+ button.highlight = button:CreateTexture(nil, "HIGHLIGHT")
+ button.highlight:SetTexture(1, 1, 1, 0.45)
+ E:SetInside(button.highlight)
+
+ button.UpdateTooltip = UpdateTooltip
+ button:SetScript("OnEnter",function() OnEnter(this) end)
+ button:SetScript("OnLeave", function() OnLeave(this) end)
+ button:SetScript("OnClick", function() OnClick(this) end)
+
+ E:SetTemplate(button, "Default")
+end
+
+local enchantableSlots = {
+ [1] = 16,
+ [2] = 17
+}
+
+local buttons = {}
+function A:ConfigureAuras(header, auraTable, weaponPosition)
+ local headerName = header:GetName()
+
+ local db = self.db.debuffs
+ if header.filter == "HELPFUL" then
+ db = self.db.buffs
+ end
+
+ local size = db.size
+ local point = DIRECTION_TO_POINT[db.growthDirection]
+ local xOffset = 0
+ local yOffset = 0
+ local wrapXOffset = 0
+ local wrapYOffset = 0
+ local wrapAfter = db.wrapAfter
+ local maxWraps = db.maxWraps
+ local minWidth = 0
+ local minHeight = 0
+
+ if IS_HORIZONTAL_GROWTH[db.growthDirection] then
+ minWidth = ((wrapAfter == 1 and 0 or db.horizontalSpacing) + size) * wrapAfter
+ minHeight = (db.verticalSpacing + size) * maxWraps
+ xOffset = DIRECTION_TO_HORIZONTAL_SPACING_MULTIPLIER[db.growthDirection] * (db.horizontalSpacing + size)
+ yOffset = 0
+ wrapXOffset = 0
+ wrapYOffset = DIRECTION_TO_VERTICAL_SPACING_MULTIPLIER[db.growthDirection] * (db.verticalSpacing + size)
+ else
+ minWidth = (db.horizontalSpacing + size) * maxWraps
+ minHeight = ((wrapAfter == 1 and 0 or db.verticalSpacing) + size) * wrapAfter
+ xOffset = 0
+ yOffset = DIRECTION_TO_VERTICAL_SPACING_MULTIPLIER[db.growthDirection] * (db.verticalSpacing + size)
+ wrapXOffset = DIRECTION_TO_HORIZONTAL_SPACING_MULTIPLIER[db.growthDirection] * (db.horizontalSpacing + size)
+ wrapYOffset = 0
+ end
+
+ wipe(buttons)
+ local button
+ for i = 1, getn(auraTable) do
+ button = _G[headerName.."AuraButton"..i]
+ if button then
+ if button:IsShown() then button:Hide() end
+ else
+ button = CreateFrame("Button", "$parentAuraButton"..i, header)
+ self:CreateIcon(button)
+ end
+ local buffInfo = auraTable[i]
+ button:SetID(buffInfo.index)
+
+ if buffInfo.duration > 0 and buffInfo.expires then
+ local timeLeft = buffInfo.expires - GetTime()
+ if not button.timeLeft then
+ button.timeLeft = timeLeft
+ button:SetScript("OnUpdate", function() self.UpdateTime(this, arg1) end)
+ else
+ button.timeLeft = timeLeft
+ end
+
+ button.nextUpdate = -1
+ self.UpdateTime(button, 0)
+ else
+ button.timeLeft = nil
+ button.time:SetText("")
+ button:SetScript("OnUpdate", nil)
+ end
+
+ if buffInfo.count > 1 then
+ button.count:SetText(buffInfo.count)
+ else
+ button.count:SetText("")
+ end
+
+ if buffInfo.filter == "HARMFUL" then
+ local color = DebuffTypeColor[buffInfo.dispelType or ""]
+ button:SetBackdropBorderColor(color.r, color.g, color.b)
+ else
+ button:SetBackdropBorderColor(unpack(E.media.bordercolor))
+ end
+
+ button.texture:SetTexture(buffInfo.icon)
+
+ buttons[i] = button
+ end
+
+ if weaponPosition then
+ local hasMainHandEnchant, mainHandExpiration, _, hasOffHandEnchant, offHandExpiration = GetWeaponEnchantInfo()
+ for weapon = 2, 1, -1 do
+ button = _G["ElvUIPlayerBuffsTempEnchant"..weapon]
+ if select(weapon, hasMainHandEnchant, hasOffHandEnchant) then
+ if not button then
+ button = CreateFrame("Button", "$parentTempEnchant"..weapon, header)
+ self:CreateIcon(button)
+ end
+ if button then
+ if button:IsShown() then button:Hide() end
+
+ local index = enchantableSlots[weapon]
+ local quality = GetInventoryItemQuality("player", index)
+ button.texture:SetTexture(GetInventoryItemTexture("player", index))
+
+ if quality then
+ button:SetBackdropBorderColor(GetItemQualityColor(quality))
+ end
+
+ local expirationTime = select(weapon, mainHandExpiration, offHandExpiration)
+ if expirationTime then
+ button.offset = select(weapon, 2, 5)
+ button:SetScript("OnUpdate", function() self.UpdateTime(this, arg1) end)
+ button.nextUpdate = -1
+ A.UpdateTime(button, 0)
+ else
+ button.timeLeft = nil
+ button.offset = nil
+ button:SetScript("OnUpdate", nil)
+ button.time:SetText("")
+ end
+
+ buttons[getn(buttons)+1] = button
+ end
+ else
+ if button and type(button.Hide) == "function" then
+ button.offset = nil
+ button:Hide()
+ end
+ end
+ end
+ end
+
+ local display = getn(buttons)
+ if wrapAfter and maxWraps then
+ display = min(display, wrapAfter * maxWraps)
+ end
+
+ local left, right, top, bottom = huge, -huge, -huge, huge
+ for index = 1, display do
+ button = buttons[index]
+ local tick, cycle = floor(mod((index - 1), wrapAfter)), floor((index - 1) / wrapAfter)
+ button:ClearAllPoints()
+ button:SetPoint(point, header, cycle * wrapXOffset + tick * xOffset, cycle * wrapYOffset + tick * yOffset)
+
+ button:SetWidth(size)
+ button:SetHeight(size)
+
+ if button.time then
+ local font = LSM:Fetch("font", self.db.font)
+ button.time:ClearAllPoints()
+ button.time:SetPoint("TOP", button, "BOTTOM", 1 + self.db.timeXOffset, 0 + self.db.timeYOffset)
+ E:FontTemplate(button.time, font, self.db.fontSize, self.db.fontOutline)
+
+ button.count:ClearAllPoints()
+ button.count:SetPoint("BOTTOMRIGHT", -1 + self.db.countXOffset, 0 + self.db.countYOffset)
+ E:FontTemplate(button.count, font, self.db.fontSize, self.db.fontOutline)
+ end
+
+ button:Show()
+ left = min(left, button:GetLeft() or huge)
+ right = max(right, button:GetRight() or -huge)
+ top = max(top, button:GetTop() or -huge)
+ bottom = min(bottom, button:GetBottom() or huge)
+ end
+ local deadIndex = getn(auraTable) + 1
+ button = _G[headerName.."AuraButton"..deadIndex]
+ while button do
+ if button:IsShown() then button:Hide() end
+ deadIndex = deadIndex + 1
+ button = _G[headerName.."AuraButton"..deadIndex]
+ end
+
+ if display >= 1 then
+ header:SetWidth(max(right - left, minWidth))
+ header:SetHeight(max(top - bottom, minHeight))
+ else
+ header:SetWidth(minWidth)
+ header:SetHeight(minHeight)
+ end
+end
+
+local freshTable
+local releaseTable
+do
+ local tableReserve = {}
+ freshTable = function ()
+ local t = next(tableReserve) or {}
+ tableReserve[t] = nil
+ return t
+ end
+ releaseTable = function (t)
+ tableReserve[t] = wipe(t)
+ end
+end
+
+local function sortFactory(key, separateOwn, reverse)
+ if separateOwn ~= 0 then
+ if reverse then
+ return function(a, b)
+ if a.filter == b.filter then
+ local ownA, ownB = a.caster == "player", b.caster == "player"
+ if ownA ~= ownB then
+ return ownA == (separateOwn > 0)
+ end
+ return a[key] > b[key]
+ else
+ return a.filter < b.filter
+ end
+ end;
+ else
+ return function(a, b)
+ if a.filter == b.filter then
+ local ownA, ownB = a.caster == "player", b.caster == "player"
+ if ownA ~= ownB then
+ return ownA == (separateOwn > 0)
+ end
+ return a[key] < b[key]
+ else
+ return a.filter < b.filter
+ end
+ end;
+ end
+ else
+ if reverse then
+ return function(a, b)
+ if a.filter == b.filter then
+ return a[key] > b[key]
+ else
+ return a.filter < b.filter
+ end
+ end;
+ else
+ return function(a, b)
+ if a.filter == b.filter then
+ return a[key] < b[key]
+ else
+ return a.filter < b.filter
+ end
+ end;
+ end
+ end
+end
+
+local sorters = {}
+for _, key in ipairs{"index", "name", "expires"} do
+ local label = string.upper(key)
+ sorters[label] = {}
+ for bool in pairs{[true] = true, [false] = false} do
+ sorters[label][bool] = {}
+ for sep = -1, 1 do
+ sorters[label][bool][sep] = sortFactory(key, sep, bool)
+ end
+ end
+end
+sorters.TIME = sorters.EXPIRES
+
+local sortingTable = {}
+function A:UpdateHeader(header)
+ local filter = header.filter
+ local db = self.db.debuffs
+
+ wipe(sortingTable)
+
+ local weaponPosition
+ if filter == "HELPFUL" then
+ db = self.db.buffs
+ weaponPosition = 0
+ end
+
+ local aura, _
+ for i = 1, 16 do
+ aura, _ = freshTable()
+ aura.buffIndex, aura.untilCancelled = GetPlayerBuff(i, filter)
+ if aura.buffIndex > 0 then
+ aura.icon, aura.count, aura.dispelType, aura.duration = GetPlayerBuffTexture(aura.buffIndex), GetPlayerBuffApplications(aura.buffIndex), GetPlayerBuffDispelType(aura.buffIndex), GetPlayerBuffTimeLeft(aura.buffIndex)
+ aura.filter = filter
+ aura.index = i
+
+ tinsert(sortingTable, aura)
+ else
+ releaseTable(aura)
+ end
+ end
+
+ local sortMethod = (sorters[db.sortMethod] or sorters["INDEX"])[db.sortDir == "-"][db.seperateOwn]
+ --tsort(sortingTable, sortMethod)
+
+ self:ConfigureAuras(header, sortingTable, weaponPosition)
+ while sortingTable[1] do
+ releaseTable(tremove(sortingTable))
+ end
+end
+
+function A:CreateAuraHeader(filter)
+ local name = "ElvUIPlayerDebuffs"
+ if filter == "HELPFUL" then
+ name = "ElvUIPlayerBuffs"
+ end
+
+ local header = CreateFrame("Frame", name, UIParent)
+ header:SetClampedToScreen(true)
+ header.filter = filter
+
+ header:RegisterEvent("PLAYER_AURAS_CHANGED")
+ header:SetScript("OnEvent", function()
+ A:UpdateHeader(this)
+ end)
+
+ self:UpdateHeader(header)
+
+ return header
+end
+
+function A:Initialize()
+ if self.db then return end
+
+ if E.private.auras.disableBlizzard then
+ E:Kill(BuffFrame)
+ E:Kill(TemporaryEnchantFrame)
+ end
+
+ if not E.private.auras.enable then return end
+
+ self.db = E.db.auras
+
+ self.BuffFrame = self:CreateAuraHeader("HELPFUL")
+ self.BuffFrame:SetPoint("TOPRIGHT", MMHolder, "TOPLEFT", -(6 + E.Border), -E.Border - E.Spacing)
+ E:CreateMover(self.BuffFrame, "BuffsMover", L["Player Buffs"])
+
+ self.BuffFrame.GetUpdateWeaponEnchant = function(self)
+ local hasMainHandEnchant, _, _, hasOffHandEnchant = GetWeaponEnchantInfo()
+ if hasMainHandEnchant and not self.hasMainHandEnchant then
+ self.hasMainHandEnchant = true
+ return true
+ elseif hasOffHandEnchant and not self.hasOffHandEnchant then
+ self.hasOffHandEnchant = true
+ return true
+ elseif self.hasMainHandEnchant and not hasMainHandEnchant then
+ self.hasMainHandEnchant = false
+ return true
+ elseif self.hasOffHandEnchant and not hasOffHandEnchant then
+ self.hasOffHandEnchant = false
+ return true
+ end
+ end
+
+ self.BuffFrame:SetScript("OnUpdate", function()
+ if this:GetUpdateWeaponEnchant() then A:UpdateHeader(this) end
+ end)
+
+ self.DebuffFrame = self:CreateAuraHeader("HARMFUL")
+ self.DebuffFrame:SetPoint("BOTTOMRIGHT", MMHolder, "BOTTOMLEFT", -(6 + E.Border), E.Border + E.Spacing)
+ E:CreateMover(self.DebuffFrame, "DebuffsMover", L["Player Debuffs"])
+end
+
+local function InitializeCallback()
+ A:Initialize()
+end
+
+E:RegisterModule(A:GetName(), InitializeCallback)
\ No newline at end of file
diff --git a/2/3/4/5/6/7/ElvUI/Modules/Auras/Load_Auras.xml b/2/3/4/5/6/7/ElvUI/Modules/Auras/Load_Auras.xml
new file mode 100644
index 0000000..2be9b8a
--- /dev/null
+++ b/2/3/4/5/6/7/ElvUI/Modules/Auras/Load_Auras.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/2/3/4/5/6/7/ElvUI/Modules/Load_Modules.xml b/2/3/4/5/6/7/ElvUI/Modules/Load_Modules.xml
index 1a6f090..b30226d 100644
--- a/2/3/4/5/6/7/ElvUI/Modules/Load_Modules.xml
+++ b/2/3/4/5/6/7/ElvUI/Modules/Load_Modules.xml
@@ -1,4 +1,5 @@
+
diff --git a/2/3/4/5/6/7/ElvUI/Settings/Private.lua b/2/3/4/5/6/7/ElvUI/Settings/Private.lua
index 1b615a7..655e1de 100644
--- a/2/3/4/5/6/7/ElvUI/Settings/Private.lua
+++ b/2/3/4/5/6/7/ElvUI/Settings/Private.lua
@@ -14,6 +14,11 @@ V["general"] = {
},
}
+V["auras"] = {
+ ["enable"] = true,
+ ["disableBlizzard"] = true,
+}
+
V["chat"] = {
["enable"] = true,
}
diff --git a/2/3/4/5/6/7/ElvUI/Settings/Profile.lua b/2/3/4/5/6/7/ElvUI/Settings/Profile.lua
index 76b2a69..298e0c4 100644
--- a/2/3/4/5/6/7/ElvUI/Settings/Profile.lua
+++ b/2/3/4/5/6/7/ElvUI/Settings/Profile.lua
@@ -104,6 +104,40 @@ P["databars"] = {
},
}
+--Auras
+P["auras"] = {
+ ["font"] = "Homespun",
+ ["fontSize"] = 10,
+ ["fontOutline"] = "MONOCHROMEOUTLINE",
+ ["countYOffset"] = 0,
+ ["countXOffset"] = 0,
+ ["timeYOffset"] = 0,
+ ["timeXOffset"] = 0,
+ ["fadeThreshold"] = 5,
+ ["buffs"] = {
+ ["growthDirection"] = "LEFT_DOWN",
+ ["wrapAfter"] = 12,
+ ["maxWraps"] = 3,
+ ["horizontalSpacing"] = 6,
+ ["verticalSpacing"] = 16,
+ ["sortMethod"] = "TIME",
+ ["sortDir"] = "-",
+ ["seperateOwn"] = 1,
+ ["size"] = 32,
+ },
+ ["debuffs"] = {
+ ["growthDirection"] = "LEFT_DOWN",
+ ["wrapAfter"] = 12,
+ ["maxWraps"] = 1,
+ ["horizontalSpacing"] = 6,
+ ["verticalSpacing"] = 16,
+ ["sortMethod"] = "TIME",
+ ["sortDir"] = "-",
+ ["seperateOwn"] = 1,
+ ["size"] = 32,
+ },
+}
+
--Chat
P["chat"] = {
["lockPositions"] = true,