initial commit

This commit is contained in:
Gitea
2020-11-13 14:27:50 -05:00
commit e2015fd9bb
581 changed files with 101308 additions and 0 deletions

View File

@@ -0,0 +1,311 @@
local _, ns = ...
local oUF = ns.oUF
local VISIBLE = 1
local HIDDEN = 0
local pcall = pcall
local floor = floor
local format = format
local unpack = unpack
local tinsert = tinsert
local infinity = math.huge
local _G = _G
local GetTime = GetTime
local UnitAura = UnitAura
local CreateFrame = CreateFrame
local UnitIsEnemy = UnitIsEnemy
local UnitReaction = UnitReaction
local GameTooltip = GameTooltip
local DAY, HOUR, MINUTE = 86400, 3600, 60
local function FormatTime(s)
if s == infinity then return end
if s < MINUTE then
return format("%.1fs", s)
elseif s < HOUR then
return format("%dm %ds", s/60%60, s%60)
elseif s < DAY then
return format("%dh %dm", s/(60*60), s/60%60)
else
return format("%dd %dh", s/DAY, (s / HOUR) - (floor(s/DAY) * 24))
end
end
local function onEnter(self)
if GameTooltip:IsForbidden() or not self:IsVisible() then return end
GameTooltip:SetOwner(self, self.tooltipAnchor)
GameTooltip:SetUnitAura(self.unit, self.index, self.filter)
end
local function onLeave()
if GameTooltip:IsForbidden() then return end
GameTooltip:Hide()
end
local function onUpdate(self, elapsed)
self.elapsed = (self.elapsed or 0) + elapsed
if self.elapsed >= 0.01 then
if self.noTime then
self:SetValue(1)
self.timeText:SetText()
self:SetScript("OnUpdate", nil)
else
local timeNow = GetTime()
self:SetValue((self.expiration - timeNow) / self.duration)
self.timeText:SetText(FormatTime(self.expiration - timeNow))
end
self.elapsed = 0
end
end
local function createAuraBar(element, index)
local statusBar = CreateFrame('StatusBar', element:GetName() .. 'StatusBar' .. index, element)
statusBar:SetStatusBarTexture([[Interface\TargetingFrame\UI-StatusBar]])
statusBar:SetMinMaxValues(0, 1)
statusBar.tooltipAnchor = element.tooltipAnchor
statusBar:SetScript('OnEnter', onEnter)
statusBar:SetScript('OnLeave', onLeave)
statusBar:EnableMouse(false)
local spark = statusBar:CreateTexture(nil, "OVERLAY", nil);
spark:SetTexture([[Interface\CastingBar\UI-CastingBar-Spark]])
spark:SetWidth(12)
spark:SetBlendMode("ADD")
spark:SetPoint('CENTER', statusBar:GetStatusBarTexture(), 'RIGHT')
local icon = statusBar:CreateTexture(nil, 'ARTWORK')
icon:SetPoint('RIGHT', statusBar, 'LEFT', -(element.gap or 2), 0)
icon:SetSize(element.height, element.height)
local nameText = statusBar:CreateFontString(nil, 'OVERLAY', 'NumberFontNormal')
nameText:SetPoint('LEFT', statusBar, 'LEFT', 2, 0)
local timeText = statusBar:CreateFontString(nil, 'OVERLAY', 'NumberFontNormal')
timeText:SetPoint('RIGHT', statusBar, 'RIGHT', -2, 0)
statusBar.icon = icon
statusBar.nameText = nameText
statusBar.timeText = timeText
statusBar.spark = spark
if(element.PostCreateBar) then element:PostCreateBar(statusBar) end
return statusBar
end
local function customFilter(element, unit, button, name)
if((element.onlyShowPlayer and button.isPlayer) or (not element.onlyShowPlayer and name)) then
return true
end
end
local function updateBar(element, unit, index, offset, filter, isDebuff, visible)
local name, texture, count, debuffType, duration, expiration, caster, isStealable, nameplateShowSelf, spellID, canApply, isBossDebuff, casterIsPlayer, nameplateShowAll, timeMod, effect1, effect2, effect3 = UnitAura(unit, index, filter)
if(name) then
local position = visible + offset + 1
local statusBar = element[position]
if(not statusBar) then
statusBar = (element.CreateBar or createAuraBar) (element, position)
tinsert(element, statusBar)
element.createdBars = element.createdBars + 1
end
statusBar.unit = unit
statusBar.index = index
statusBar.caster = caster
statusBar.filter = filter
statusBar.isDebuff = isDebuff
statusBar.isPlayer = caster == 'player' or caster == 'vehicle'
local show = (element.CustomFilter or customFilter) (element, unit, statusBar, name, texture,
count, debuffType, duration, expiration, caster, isStealable, nameplateShowSelf, spellID,
canApply, isBossDebuff, casterIsPlayer, nameplateShowAll, timeMod, effect1, effect2, effect3)
if(show) then
statusBar.icon:SetTexture(texture)
if count > 1 then
statusBar.nameText:SetFormattedText('[%d] %s', count, name)
else
statusBar.nameText:SetText(name)
end
statusBar.duration = duration
statusBar.expiration = expiration
statusBar.spellID = spellID
statusBar.spell = name
statusBar.noTime = (duration == 0 and expiration == 0)
if not statusBar.noTime and element.sparkEnabled then
statusBar.spark:Show()
else
statusBar.spark:Hide()
end
local r, g, b = .2, .6, 1
if element.buffColor then r, g, b = unpack(element.buffColor) end
if filter == 'HARMFUL' then
if not debuffType or debuffType == '' then
debuffType = 'none'
end
local color = _G.DebuffTypeColor[debuffType]
r, g, b = color.r, color.g, color.b
end
statusBar:SetStatusBarColor(r, g, b)
statusBar:SetSize(element.width, element.height)
statusBar.icon:SetSize(element.height, element.height)
statusBar:SetScript('OnUpdate', onUpdate)
statusBar:SetID(index)
statusBar:Show()
if(element.PostUpdateBar) then
element:PostUpdateBar(unit, statusBar, index, position, duration, expiration, debuffType, isStealable)
end
return VISIBLE
else
return HIDDEN
end
end
end
local function SetPosition(element, from, to)
local height = element.height
local spacing = element.spacing or 1
local anchor = element.initialAnchor
local growth = element.growth == 'DOWN' and -1 or 1
for i = from, to do
local button = element[i]
if(not button) then break end
button:ClearAllPoints()
button:SetPoint(anchor, element, anchor, (height + element.gap), growth * (i > 1 and ((i - 1) * (height + spacing)) or 0))
end
end
local function filterBars(element, unit, filter, limit, isDebuff, offset, dontHide)
if(not offset) then offset = 0 end
local index = 1
local visible = 0
local hidden = 0
while(visible < limit) do
local result = updateBar(element, unit, index, offset, filter, isDebuff, visible)
if(not result) then
break
elseif(result == VISIBLE) then
visible = visible + 1
elseif(result == HIDDEN) then
hidden = hidden + 1
end
index = index + 1
end
if(not dontHide) then
for i = visible + offset + 1, #element do
element[i]:Hide()
end
end
return visible, hidden
end
local function UpdateAuras(self, event, unit)
if(self.unit ~= unit) then return end
local element = self.AuraBars
if(element) then
if(element.PreUpdate) then element:PreUpdate(unit) end
local isEnemy = UnitIsEnemy('player', unit)
local reaction = UnitReaction('player', unit)
local filter = (not isEnemy and (not reaction or reaction > 4) and (element.friendlyAuraType or 'HELPFUL')) or element.enemyAuraType or 'HARMFUL'
local visible, hidden = filterBars(element, unit, filter, element.maxBars, filter == 'HARMFUL', 0)
local fromRange, toRange
if(element.PreSetPosition) then
fromRange, toRange = element:PreSetPosition(element.maxBars)
end
if(fromRange or element.createdBars > element.anchoredBars) then
(element.SetPosition or SetPosition) (element, fromRange or element.anchoredBars + 1, toRange or element.createdBars)
element.anchoredBars = element.createdBars
end
if(element.PostUpdate) then element:PostUpdate(unit) end
end
end
local function Update(self, event, unit)
if(self.unit ~= unit) then return end
UpdateAuras(self, event, unit)
-- Assume no event means someone wants to re-anchor things. This is usually
-- done by UpdateAllElements and :ForceUpdate.
if(event == 'ForceUpdate' or not event) then
local element = self.AuraBars
if(element) then
(element.SetPosition or SetPosition) (element, 1, element.createdBars)
end
end
end
local function ForceUpdate(element)
return Update(element.__owner, 'ForceUpdate', element.__owner.unit)
end
local function Enable(self)
local element = self.AuraBars
if(element) then
self:RegisterEvent('UNIT_AURA', UpdateAuras)
element.__owner = self
element.ForceUpdate = ForceUpdate
element.createdBars = element.createdBars or 0
element.anchoredBars = 0
element.width = element.width or 240
element.height = element.height or 12
element.sparkEnabled = element.sparkEnabled or true
element.spacing = element.spacing or 2
element.initialAnchor = element.initialAnchor or 'BOTTOMLEFT'
element.growth = element.growth or 'UP'
element.gap = element.gap or 2
element.maxBars = element.maxBars or 32
-- Avoid parenting GameTooltip to frames with anchoring restrictions,
-- otherwise it'll inherit said restrictions which will cause issues
-- with its further positioning, clamping, etc
if(not pcall(self.GetCenter, self)) then
element.tooltipAnchor = 'ANCHOR_CURSOR'
else
element.tooltipAnchor = element.tooltipAnchor or 'ANCHOR_BOTTOMRIGHT'
end
element:Show()
return true
end
end
local function Disable(self)
local element = self.AuraBars
if(element) then
self:UnregisterEvent('UNIT_AURA', UpdateAuras)
element:Hide()
end
end
oUF:AddElement('AuraBars', Update, Enable, Disable)

View File

@@ -0,0 +1,185 @@
local _, ns = ...
local oUF = ns.oUF
if not oUF then return end
local UnitAura = UnitAura
local UnitCanAssist = UnitCanAssist
local GetSpecialization = GetSpecialization
local GetActiveSpecGroup = GetActiveSpecGroup
local Classic = WOW_PROJECT_ID == WOW_PROJECT_CLASSIC
local DispelList, BlackList = {}, {}
-- GLOBALS: DebuffTypeColor
--local DispellPriority = { Magic = 4, Curse = 3, Disease = 2, Poison = 1 }
--local FilterList = {}
if Classic then
DispelList.PRIEST = { Magic = true, Disease = true }
DispelList.SHAMAN = { Poison = true, Disease = true }
DispelList.PALADIN = { Magic = true, Poison = true, Disease = true }
DispelList.MAGE = { Curse = true }
DispelList.DRUID = { Curse = true, Poison = true }
DispelList.WARLOCK = { Magic = true }
else
DispelList.PRIEST = { Magic = true, Disease = true }
DispelList.SHAMAN = { Magic = false, Curse = true }
DispelList.PALADIN = { Magic = false, Poison = true, Disease = true }
DispelList.DRUID = { Magic = false, Curse = true, Poison = true, Disease = false }
DispelList.MONK = { Magic = false, Poison = true, Disease = true }
DispelList.MAGE = { Curse = true }
end
local playerClass = select(2, UnitClass('player'))
local CanDispel = DispelList[playerClass] or {}
if not Classic then
BlackList[140546] = true -- Fully Mutated
BlackList[136184] = true -- Thick Bones
BlackList[136186] = true -- Clear mind
BlackList[136182] = true -- Improved Synapses
BlackList[136180] = true -- Keen Eyesight
BlackList[105171] = true -- Deep Corruption
BlackList[108220] = true -- Deep Corruption
BlackList[116095] = true -- Disable, Slow
BlackList[137637] = true -- Warbringer, Slow
end
local function GetAuraType(unit, filter, filterTable)
if not unit or not UnitCanAssist('player', unit) then return end
local i = 1
while true do
local name, texture, _, debufftype, _, _, _, _, _, spellID = UnitAura(unit, i, 'HARMFUL')
if not texture then break end
local filterSpell = filterTable[spellID] or filterTable[name]
if filterTable and filterSpell then
if filterSpell.enable then
return debufftype, texture, true, filterSpell.style, filterSpell.color
end
elseif debufftype and (not filter or (filter and CanDispel[debufftype])) and not (BlackList[name] or BlackList[spellID]) then
return debufftype, texture
end
i = i + 1
end
i = 1
while true do
local _, texture, _, debufftype, _, _, _, _, _, spellID = UnitAura(unit, i)
if not texture then break end
local filterSpell = filterTable[spellID]
if filterTable and filterSpell and filterSpell.enable then
return debufftype, texture, true, filterSpell.style, filterSpell.color
end
i = i + 1
end
end
--[[
local function FilterTable()
local debufftype, texture, filterSpell
return debufftype, texture, true, filterSpell.style, filterSpell.color
end
]]
local function CheckTalentTree(tree)
local activeGroup = GetActiveSpecGroup()
local spec = activeGroup and GetSpecialization(false, false, activeGroup)
if spec then
return tree == spec
end
end
local function CheckSpec()
if Classic then return end
-- Check for certain talents to see if we can dispel magic or not
if playerClass == 'PALADIN' then
CanDispel.Magic = CheckTalentTree(1)
elseif playerClass == 'SHAMAN' then
CanDispel.Magic = CheckTalentTree(3)
elseif playerClass == 'DRUID' then
CanDispel.Magic = CheckTalentTree(4)
elseif playerClass == 'MONK' then
CanDispel.Magic = CheckTalentTree(2)
end
end
local function Update(self, _, unit)
if unit ~= self.unit then return end
local debuffType, texture, wasFiltered, style, color = GetAuraType(unit, self.AuraHighlightFilter, self.AuraHighlightFilterTable)
if wasFiltered then
if style == 'GLOW' and self.AuraHightlightGlow then
self.AuraHightlightGlow:Show()
self.AuraHightlightGlow:SetBackdropBorderColor(color.r, color.g, color.b)
elseif self.AuraHightlightGlow then
self.AuraHightlightGlow:Hide()
self.AuraHighlight:SetVertexColor(color.r, color.g, color.b, color.a)
end
elseif debuffType then
color = DebuffTypeColor[debuffType or 'none']
if self.AuraHighlightBackdrop and self.AuraHightlightGlow then
self.AuraHightlightGlow:Show()
self.AuraHightlightGlow:SetBackdropBorderColor(color.r, color.g, color.b)
elseif self.AuraHighlightUseTexture then
self.AuraHighlight:SetTexture(texture)
else
self.AuraHighlight:SetVertexColor(color.r, color.g, color.b, color.a)
end
else
if self.AuraHightlightGlow then
self.AuraHightlightGlow:Hide()
end
if self.AuraHighlightUseTexture then
self.AuraHighlight:SetTexture(nil)
else
self.AuraHighlight:SetVertexColor(0, 0, 0, 0)
end
end
if self.AuraHighlight.PostUpdate then
self.AuraHighlight:PostUpdate(self, debuffType, texture, wasFiltered, style, color)
end
end
local function Enable(self)
if self.AuraHighlight then
self:RegisterEvent('UNIT_AURA', Update)
return true
end
end
local function Disable(self)
local element = self.AuraHighlight
if element then
self:UnregisterEvent('UNIT_AURA', Update)
if self.AuraHightlightGlow then
self.AuraHightlightGlow:Hide()
end
if element then
element:SetVertexColor(0, 0, 0, 0)
end
end
end
local f = CreateFrame('Frame')
f:RegisterEvent('CHARACTER_POINTS_CHANGED')
if not Classic then
f:RegisterEvent('PLAYER_TALENT_UPDATE')
f:RegisterEvent('PLAYER_SPECIALIZATION_CHANGED')
end
f:SetScript('OnEvent', CheckSpec)
oUF:AddElement('AuraHighlight', Update, Enable, Disable)

View File

@@ -0,0 +1,304 @@
-- Original work by Astromech
-- Rewritten based on Auras by Azilroka
local _, ns = ...
local oUF = ns.oUF
local VISIBLE = 1
local HIDDEN = 0
local min, wipe, pairs, tinsert = min, wipe, pairs, tinsert
local CreateFrame = CreateFrame
local UnitAura = UnitAura
local UnitIsUnit = UnitIsUnit
local GetSpellTexture = GetSpellTexture
local function createAuraIcon(element, index)
local button = CreateFrame('Button', element:GetName() .. 'Button' .. index, element)
button:EnableMouse(false)
button:Hide()
local cd = CreateFrame('Cooldown', '$parentCooldown', button, 'CooldownFrameTemplate')
cd:SetAllPoints()
cd:SetReverse(true)
cd:SetDrawBling(false)
cd:SetDrawEdge(false)
local icon = button:CreateTexture(nil, 'ARTWORK')
icon:SetAllPoints()
local countFrame = CreateFrame('Frame', nil, button)
countFrame:SetAllPoints(button)
countFrame:SetFrameLevel(cd:GetFrameLevel() + 1)
local count = countFrame:CreateFontString(nil, 'OVERLAY', 'NumberFontNormal')
count:SetPoint('BOTTOMRIGHT', countFrame, 'BOTTOMRIGHT', -1, 0)
local overlay = button:CreateTexture(nil, 'OVERLAY')
overlay:SetTexture([[Interface\Buttons\UI-Debuff-Overlays]])
overlay:SetAllPoints()
overlay:SetTexCoord(.296875, .5703125, 0, .515625)
button.overlay = overlay
button.icon = icon
button.count = count
button.cd = cd
if(element.PostCreateIcon) then element:PostCreateIcon(button) end
return button
end
local function customFilter(element, _, button, name, _, _, debuffType, _, _, caster, isStealable, _, spellID, canApply, isBossDebuff, casterIsPlayer)
local setting = element.watched[spellID]
if not setting then return false end
button.onlyShowMissing = setting.onlyShowMissing
button.anyUnit = setting.anyUnit
if setting.enabled then
if setting.onlyShowMissing and not setting.anyUnit and caster == 'player' then
return false
elseif setting.onlyShowMissing and setting.anyUnit and casterIsPlayer then
return true
elseif not setting.onlyShowMissing and setting.anyUnit and casterIsPlayer then
return true
elseif not setting.onlyShowMissing and not setting.anyUnit and caster == 'player' then
return true
end
end
return false
end
local function updateIcon(element, unit, index, offset, filter, isDebuff, visible)
local name, texture, count, debuffType, duration, expiration, caster, isStealable,
nameplateShowSelf, spellID, canApply, isBossDebuff, casterIsPlayer, nameplateShowAll,
timeMod, effect1, effect2, effect3 = UnitAura(unit, index, filter)
if(name) then
local position = visible + offset + 1
local button = element[position]
if(not button) then
button = (element.CreateIcon or createAuraIcon) (element, position)
tinsert(element, button)
element.createdIcons = element.createdIcons + 1
end
button.caster = caster
button.filter = filter
button.isDebuff = isDebuff
button.debuffType = debuffType
button.spellID = spellID
button.isPlayer = caster == 'player'
local show = (element.CustomFilter or customFilter) (element, unit, button, name, texture,
count, debuffType, duration, expiration, caster, isStealable, nameplateShowSelf, spellID,
canApply, isBossDebuff, casterIsPlayer, nameplateShowAll, timeMod, effect1, effect2, effect3)
if(show) then
local setting = element.watched[spellID]
if(button.cd) then
if(duration and duration > 0) then
button.cd:SetCooldown(expiration - duration, duration)
button.cd:Show()
else
button.cd:Hide()
end
end
if(button.overlay) then
if((isDebuff and element.showDebuffType) or (not isDebuff and element.showBuffType) or element.showType) then
local color = element.__owner.colors.debuff[debuffType] or element.__owner.colors.debuff.none
button.overlay:SetVertexColor(color[1], color[2], color[3])
button.overlay:Show()
else
button.overlay:Hide()
end
end
if(button.stealable) then
if(not isDebuff and isStealable and element.showStealableBuffs and not UnitIsUnit('player', unit)) then
button.stealable:Show()
else
button.stealable:Hide()
end
end
if(button.icon) then button.icon:SetTexture(texture) end
if(button.count) then button.count:SetText(count > 1 and count) end
if setting.sizeOffset == 0 then
button:SetSize(element.size, element.size)
else
button:SetSize(setting.sizeOffset + element.size, setting.sizeOffset + element.size)
end
button:SetID(index)
button:Show()
button:ClearAllPoints()
button:SetPoint(setting.point, setting.xOffset, setting.yOffset)
if(element.PostUpdateIcon) then
element:PostUpdateIcon(unit, button, index, position, duration, expiration, debuffType, isStealable)
end
return VISIBLE
else
button.isFiltered = true
return HIDDEN
end
end
end
local missing = {}
local function onlyShowMissingIcon(element, unit, offset)
wipe(missing)
for SpellID, setting in pairs(element.watched) do
if setting.onlyShowMissing then
missing[SpellID] = setting
end
end
for i = 1, #element do
local button = element[i]
if button.isFiltered and missing[button.spellID] then
missing[button.spellID] = nil
end
end
local visible = 0
for SpellID, setting in pairs(missing) do
local position = visible + offset + 1
local button = element[position]
if(not button) then
button = (element.CreateIcon or createAuraIcon) (element, position)
tinsert(element, button)
element.createdIcons = element.createdIcons + 1
end
if(button.cd) then button.cd:Hide() end
if(button.icon) then button.icon:SetTexture(GetSpellTexture(SpellID)) end
if(button.overlay) then button.overlay:Hide() end
if setting.sizeOffset == 0 then
button:SetSize(element.size, element.size)
else
button:SetSize(setting.sizeOffset + element.size, setting.sizeOffset + element.size)
end
button:SetID(position)
button.spellID = SpellID
button:Show()
button:ClearAllPoints()
button:SetPoint(setting.point, setting.xOffset, setting.yOffset)
if(element.PostUpdateIcon) then
element:PostUpdateIcon(unit, button, nil, position)
end
visible = visible + 1
end
return visible
end
local function filterIcons(element, unit, filter, limit, isDebuff, offset, dontHide)
if (not offset) then offset = 0 end
local index, visible, hidden = 1, 0, 0
while (visible < limit) do
local result = updateIcon(element, unit, index, offset, filter, isDebuff, visible)
if (not result) then
break
elseif (result == VISIBLE) then
visible = visible + 1
elseif (result == HIDDEN) then
hidden = hidden + 1
end
index = index + 1
end
if (not dontHide) then
for i = visible + offset + 1, #element do
element[i]:Hide()
end
end
return visible, hidden
end
local function UpdateAuras(self, event, unit)
if(self.unit ~= unit) then return end
local element = self.AuraWatch
if(element) then
if(element.PreUpdate) then element:PreUpdate(unit) end
local numBuffs = element.numBuffs or 32
local numDebuffs = element.numDebuffs or 16
local numAuras = element.numTotal or (numBuffs + numDebuffs)
for i = 1, #element do element[i].isFiltered = false end
local visibleBuffs, hiddenBuffs = filterIcons(element, unit, element.buffFilter or element.filter or 'HELPFUL', min(numBuffs, numAuras), nil, 0, true)
local visibleDebuffs, hiddenDebuffs = filterIcons(element, unit, element.buffFilter or element.filter or 'HARMFUL', min(numDebuffs, numAuras - visibleBuffs), true, visibleBuffs)
element.visibleDebuffs = visibleDebuffs
element.visibleBuffs = visibleBuffs
element.visibleAuras = visibleBuffs + visibleDebuffs
element.allAuras = visibleBuffs + visibleDebuffs + hiddenBuffs + hiddenDebuffs
onlyShowMissingIcon(element, unit, element.visibleAuras)
if(element.PostUpdate) then element:PostUpdate(unit) end
end
end
local function Update(self, event, unit)
if(self.unit ~= unit) then return end
UpdateAuras(self, event, unit)
end
local function ForceUpdate(element)
return Update(element.__owner, 'ForceUpdate', element.__owner.unit)
end
local function SetNewTable(element, table)
element.watched = table or {}
end
local function Enable(self)
local element = self.AuraWatch
if(element) then
element.__owner = self
element.SetNewTable = SetNewTable
element.ForceUpdate = ForceUpdate
element.watched = element.watched or {}
element.createdIcons = element.createdIcons or 0
element.anchoredIcons = 0
element.size = 8
self:RegisterEvent('UNIT_AURA', UpdateAuras)
element:Show()
return true
end
end
local function Disable(self)
if(self.AuraWatch) then
self:UnregisterEvent('UNIT_AURA', UpdateAuras)
if(self.AuraWatch) then self.AuraWatch:Hide() end
end
end
oUF:AddElement('AuraWatch', Update, Enable, Disable)

View File

@@ -0,0 +1,303 @@
local _, ns = ...
local oUF = _G.oUF or ns.oUF
assert(oUF, "oUF_Cutaway was unable to locate oUF install.")
--[[
Configuration values for both health and power:
.enabled: enable cutaway for this element, defaults to disabled
.fadeOutTime: How long it takes the cutaway health to fade, defaults to 0.6 seconds
.lengthBeforeFade: How long it takes before the cutaway begins to fade, defaults to 0.3 seconds
]]
-- GLOBALS: ElvUI
local max = math.max
local assert = assert
local hooksecurefunc = hooksecurefunc
local UnitHealthMax = UnitHealthMax
local UnitPowerMax = UnitPowerMax
local UnitIsTapDenied = UnitIsTapDenied
local UnitGUID = UnitGUID
local E -- placeholder
local function checkElvUI()
if not E then
E = ElvUI and ElvUI[1]
assert(E, "oUF_Cutaway was not able to locate ElvUI and it is required.")
end
end
local function closureFunc(self)
self.ready = nil
self.playing = nil
self.cur = nil
end
local function fadeClosure(element)
if not element.FadeObject then
element.FadeObject = {
finishedFuncKeep = true,
finishedArg1 = element,
finishedFunc = closureFunc
}
end
E:UIFrameFadeOut(element, element.fadeOutTime, element.__parentElement:GetAlpha(), 0)
end
local function Shared_PreUpdate(self, element, unit)
element.unit = unit
local oldGUID, newGUID = element.guid, UnitGUID(unit)
element.guid = newGUID
if not oldGUID or oldGUID ~= newGUID then
return
end
element.cur = self.cur
element.ready = true
end
local function UpdateSize(self, element, curV, maxV)
local isVertical = self:GetOrientation() == 'VERTICAL'
local pm = (isVertical and self:GetHeight()) or self:GetWidth()
local oum = (1 / maxV) * pm
local c = max(element.cur - curV, 0)
local mm = c * oum
if isVertical then
element:Height(mm)
else
element:Width(mm)
end
end
local PRE, POST = 0, 1
local function Shared_UpdateCheckReturn(self, element, updateType, ...)
if not element:IsVisible() then
return true
end
if updateType == PRE then
local maxV = ...
return (not element.enabled or not self.cur) or element.ready or not maxV or maxV == 0
elseif updateType == POST then
local curV, maxV, unit = ...
return (not element.enabled or not element.cur) or (not element.ready or not curV or not maxV or maxV == 0) or element.unit ~= unit
end
end
local function Health_PreUpdate(self, unit)
local element = self.__owner.Cutaway.Health
local maxV = (element.GetHealthMax or UnitHealthMax)(unit)
if Shared_UpdateCheckReturn(self, element, PRE, maxV) or UnitIsTapDenied(unit) then
return
end
Shared_PreUpdate(self, element, unit)
end
local function Health_PostUpdate(self, unit, curHealth, maxHealth)
local element = self.__owner.Cutaway.Health
if Shared_UpdateCheckReturn(self, element, POST, curHealth, maxHealth, unit) then
return
end
UpdateSize(self, element, curHealth, maxHealth)
if element.playing then
return
end
if (element.cur - curHealth) > (maxHealth * 0.01) then
element:SetAlpha(self:GetAlpha())
E:Delay(element.lengthBeforeFade, fadeClosure, element)
element.playing = true
else
element:SetAlpha(0)
closureFunc(element)
end
end
local function Health_PostUpdateColor(self, r, g, b)
self.__owner.Cutaway.Health:SetVertexColor(r * 1.5, g * 1.5, b * 1.5)
end
local function Power_PreUpdate(self, unit)
local element = self.__owner.Cutaway.Power
local maxV = (element.GetPowerMax or UnitPowerMax)(unit)
if Shared_UpdateCheckReturn(self, element, PRE, maxV) then
return
end
Shared_PreUpdate(self, element, unit)
end
local function Power_PostUpdate(self, unit, curPower, _, maxPower)
local element = self.__owner.Cutaway.Power
if Shared_UpdateCheckReturn(self, element, POST, curPower, maxPower, unit) then
return
end
UpdateSize(self, element, curPower, maxPower)
if element.playing then
return
end
if (element.cur - curPower) > (maxPower * 0.01) then
element:SetAlpha(self:GetAlpha())
E:Delay(element.lengthBeforeFade, fadeClosure, element)
element.playing = true
else
element:SetAlpha(0)
closureFunc(element)
end
end
local function Power_PostUpdateColor(self, r, g, b)
self.__owner.Cutaway.Power:SetVertexColor(r * 1.5, g * 1.5, b * 1.5)
end
local defaults = {
health = {
enabled = false,
lengthBeforeFade = 0.3,
fadeOutTime = 0.6
},
power = {
enabled = false,
lengthBeforeFade = 0.3,
fadeOutTime = 0.6
}
}
local function UpdateConfigurationValues(self, db)
local hs, ps = false, false
if self.Health then
local health = self.Health
local hdb = db.health
hs = hdb.enabled
health.enabled = hs
if hs then
health.lengthBeforeFade = hdb.lengthBeforeFade
health.fadeOutTime = hdb.fadeOutTime
health:Show()
else
health:Hide()
end
end
if self.Power then
local power = self.Power
local pdb = db.power
ps = pdb.enabled
power.enabled = ps
if ps then
power.lengthBeforeFade = pdb.lengthBeforeFade
power.fadeOutTime = pdb.fadeOutTime
power:Show()
else
power:Hide()
end
end
return hs, ps
end
local function Enable(self)
local element = self and self.Cutaway
if element then
checkElvUI()
if element.Health and element.Health:IsObjectType("Texture") and not element.Health:GetTexture() then
element.Health:SetTexture([[Interface\TargetingFrame\UI-StatusBar]])
end
if element.Power and element.Power:IsObjectType("Texture") and not element.Power:GetTexture() then
element.Power:SetTexture([[Interface\TargetingFrame\UI-StatusBar]])
end
if not element.defaultsSet then
UpdateConfigurationValues(element, defaults)
element.defaultsSet = true
end
if element.Health and self.Health then
self.Health.__owner = self
element.Health.__parentElement = self.Health
element.Health:SetAlpha(0)
if not element.Health.hasCutawayHook then
if self.Health.PreUpdate then
hooksecurefunc(self.Health, "PreUpdate", Health_PreUpdate)
else
self.Health.PreUpdate = Health_PreUpdate
end
if self.Health.PostUpdate then
hooksecurefunc(self.Health, "PostUpdate", Health_PostUpdate)
else
self.Health.PostUpdate = Health_PostUpdate
end
hooksecurefunc(self.Health, "SetStatusBarColor", Health_PostUpdateColor)
element.Health.hasCutawayHook = true
end
end
if element.Power and self.Power then
self.Power.__owner = self
element.Power.__parentElement = self.Power
element.Power:SetAlpha(0)
if not element.Power.hasCutawayHook then
if self.Power.PreUpdate then
hooksecurefunc(self.Power, "PreUpdate", Power_PreUpdate)
else
self.Power.PreUpdate = Power_PreUpdate
end
if self.Power.PostUpdate then
hooksecurefunc(self.Power, "PostUpdate", Power_PostUpdate)
else
self.Power.PostUpdate = Power_PostUpdate
end
hooksecurefunc(self.Power, "SetStatusBarColor", Power_PostUpdateColor)
element.Power.hasCutawayHook = true
end
end
if not element.UpdateConfigurationValues then
element.UpdateConfigurationValues = UpdateConfigurationValues
end
return true
end
end
local function disableElement(element)
if element then
element.enabled = false
element:Hide()
end
end
local function Disable(self)
if self and self.Cutaway then
disableElement(self.Cutaway.Health)
disableElement(self.Cutaway.Power)
end
end
oUF:AddElement("Cutaway", nil, Enable, Disable)

View File

@@ -0,0 +1,346 @@
local _, ns = ...
local oUF = _G.oUF or ns.oUF
assert(oUF, "oUF_Fader cannot find an instance of oUF. If your oUF is embedded into a layout, it may not be embedded properly.")
-------------
-- Credits -- p3lim, Azilroka, Simpy
-------------
local _G = _G
local pairs, ipairs, type = pairs, ipairs, type
local next, tinsert, tremove = next, tinsert, tremove
local CreateFrame = CreateFrame
local GetMouseFocus = GetMouseFocus
local UnitAffectingCombat = UnitAffectingCombat
local UnitCastingInfo = UnitCastingInfo
local UnitChannelInfo = UnitChannelInfo
local UnitExists = UnitExists
local UnitHasVehicleUI = UnitHasVehicleUI
local UnitHealth = UnitHealth
local UnitHealthMax = UnitHealthMax
local UnitPower = UnitPower
local UnitPowerMax = UnitPowerMax
local UnitPowerType = UnitPowerType
-- These variables will be left-over when disabled if they were used (for reuse later if they become re-enabled):
---- Fader.HoverHooked, Fader.TargetHooked
local E -- ElvUI engine defined in ClearTimers
local MIN_ALPHA, MAX_ALPHA = .35, 1
local onRangeObjects, onRangeFrame = {}
local PowerTypesFull = {MANA = true, FOCUS = true, ENERGY = true}
local function ClearTimers(element)
if not E then E = _G.ElvUI[1] end
if element.configTimer then
E:CancelTimer(element.configTimer)
element.configTimer = nil
end
if element.delayTimer then
E:CancelTimer(element.delayTimer)
element.delayTimer = nil
end
end
local function ToggleAlpha(self, element, endAlpha)
element:ClearTimers()
if element.Smooth then
E:UIFrameFadeOut(self, element.Smooth, self:GetAlpha(), endAlpha)
else
self:SetAlpha(endAlpha)
end
end
local function Update(self, _, unit)
local element = self.Fader
if self.isForced or (not element or not element.count or element.count <= 0) then
self:SetAlpha(1)
return
end
unit = unit or self.unit
-- range fader
if element.Range then
if element.UpdateRange then
element.UpdateRange(self, unit)
end
if element.RangeAlpha then
ToggleAlpha(self, element, element.RangeAlpha)
end
return
end
-- normal fader
local _, powerType
if element.Power then
_, powerType = UnitPowerType(unit)
end
if
(element.Casting and (UnitCastingInfo(unit) or UnitChannelInfo(unit))) or
(element.Combat and UnitAffectingCombat(unit)) or
(element.PlayerTarget and UnitExists('target')) or
(element.UnitTarget and UnitExists(unit..'target')) or
(element.Focus and UnitExists('focus')) or
(element.Health and UnitHealth(unit) < UnitHealthMax(unit)) or
(element.Power and (PowerTypesFull[powerType] and UnitPower(unit) < UnitPowerMax(unit))) or
(element.Vehicle and UnitHasVehicleUI(unit)) or
(element.Hover and GetMouseFocus() == (self.__faderobject or self))
then
ToggleAlpha(self, element, element.MaxAlpha)
else
if element.Delay then
if element.DelayAlpha then
ToggleAlpha(self, element, element.DelayAlpha)
end
element:ClearTimers()
element.delayTimer = E:ScheduleTimer(ToggleAlpha, element.Delay, self, element, element.MinAlpha)
else
ToggleAlpha(self, element, element.MinAlpha)
end
end
end
local function ForceUpdate(element)
return Update(element.__owner, "ForceUpdate", element.__owner.unit)
end
local function onRangeUpdate(frame, elapsed)
frame.timer = (frame.timer or 0) + elapsed
if (frame.timer >= .20) then
for _, object in next, onRangeObjects do
if object:IsVisible() then
object.Fader:ForceUpdate()
end
end
frame.timer = 0
end
end
local function HoverScript(self)
local Fader = self.__faderelement or self.Fader
if Fader and Fader.HoverHooked == 1 then
Fader:ForceUpdate()
end
end
local function TargetScript(self)
if self.Fader and self.Fader.TargetHooked == 1 then
if self:IsShown() then
self.Fader:ForceUpdate()
else
self:SetAlpha(0)
end
end
end
local options = {
Range = {
enable = function(self)
if not onRangeFrame then
onRangeFrame = CreateFrame('Frame')
onRangeFrame:SetScript('OnUpdate', onRangeUpdate)
end
onRangeFrame:Show()
tinsert(onRangeObjects, self)
end,
disable = function(self)
if onRangeFrame then
for idx, obj in next, onRangeObjects do
if obj == self then
self.Fader.RangeAlpha = nil
tremove(onRangeObjects, idx)
break
end
end
if #onRangeObjects == 0 then
onRangeFrame:Hide()
end
end
end
},
Hover = {
enable = function(self)
if not self.Fader.HoverHooked then
local Frame = self.__faderobject or self
Frame:HookScript('OnEnter', HoverScript)
Frame:HookScript('OnLeave', HoverScript)
end
self.Fader.HoverHooked = 1 -- on state
end,
disable = function(self)
if self.Fader.HoverHooked == 1 then
self.Fader.HoverHooked = 0 -- off state
end
end
},
Combat = {
enable = function(self)
self:RegisterEvent('PLAYER_REGEN_ENABLED', Update, true)
self:RegisterEvent('PLAYER_REGEN_DISABLED', Update, true)
self:RegisterEvent('UNIT_FLAGS', Update)
end,
events = {'PLAYER_REGEN_ENABLED','PLAYER_REGEN_DISABLED','UNIT_FLAGS'}
},
Target = { --[[ UnitTarget, PlayerTarget ]]
enable = function(self)
if not self.Fader.TargetHooked then
self:HookScript('OnShow', TargetScript)
self:HookScript('OnHide', TargetScript)
end
self.Fader.TargetHooked = 1 -- on state
if not self:IsShown() then
self:SetAlpha(0)
end
self:RegisterEvent('UNIT_TARGET', Update)
self:RegisterEvent('PLAYER_TARGET_CHANGED', Update, true)
self:RegisterEvent('PLAYER_FOCUS_CHANGED', Update, true)
end,
events = {'UNIT_TARGET','PLAYER_TARGET_CHANGED','PLAYER_FOCUS_CHANGED'},
disable = function(self)
if self.Fader.TargetHooked == 1 then
self.Fader.TargetHooked = 0 -- off state
end
end
},
Focus = {
enable = function(self)
self:RegisterEvent('PLAYER_FOCUS_CHANGED', Update, true)
end,
events = {'PLAYER_FOCUS_CHANGED'}
},
Health = {
enable = function(self)
self:RegisterEvent('UNIT_HEALTH', Update)
self:RegisterEvent('UNIT_MAXHEALTH', Update)
end,
events = {'UNIT_HEALTH','UNIT_MAXHEALTH'}
},
Power = {
enable = function(self)
self:RegisterEvent('UNIT_POWER_UPDATE', Update)
self:RegisterEvent('UNIT_MAXPOWER', Update)
end,
events = {'UNIT_POWER_UPDATE','UNIT_MAXPOWER'}
},
Vehicle = {
enable = function(self)
self:RegisterEvent('UNIT_ENTERED_VEHICLE', Update, true)
self:RegisterEvent('UNIT_EXITED_VEHICLE', Update, true)
end,
events = {'UNIT_ENTERED_VEHICLE','UNIT_EXITED_VEHICLE'}
},
Casting = {
enable = function(self)
self:RegisterEvent('UNIT_SPELLCAST_START', Update)
self:RegisterEvent('UNIT_SPELLCAST_FAILED', Update)
self:RegisterEvent('UNIT_SPELLCAST_STOP', Update)
self:RegisterEvent('UNIT_SPELLCAST_INTERRUPTED', Update)
self:RegisterEvent('UNIT_SPELLCAST_CHANNEL_START', Update)
self:RegisterEvent('UNIT_SPELLCAST_CHANNEL_STOP', Update)
end,
events = {'UNIT_SPELLCAST_START','UNIT_SPELLCAST_FAILED','UNIT_SPELLCAST_STOP','UNIT_SPELLCAST_INTERRUPTED','UNIT_SPELLCAST_CHANNEL_START','UNIT_SPELLCAST_CHANNEL_STOP'}
},
MinAlpha = {
countIgnored = true,
enable = function(self, state)
self.Fader.MinAlpha = state or MIN_ALPHA
end
},
MaxAlpha = {
countIgnored = true,
enable = function(self, state)
self.Fader.MaxAlpha = state or MAX_ALPHA
end
},
Smooth = {countIgnored = true},
DelayAlpha = {countIgnored = true},
Delay = {countIgnored = true},
}
local function CountOption(element, state, oldState)
if state and not oldState then
element.count = (element.count or 0) + 1
elseif oldState and element.count and not state then
element.count = element.count - 1
end
end
local function SetOption(element, opt, state)
local option = ((opt == 'UnitTarget' or opt == 'PlayerTarget') and 'Target') or opt
local oldState = element[opt]
if option and options[option] and (oldState ~= state) then
element[opt] = state
if state then
if type(state) == 'table' then
state.__faderelement = element
element.__owner.__faderobject = state
end
if options[option].enable then
options[option].enable(element.__owner, state)
end
else
if options[option].events and next(options[option].events) then
for _, event in ipairs(options[option].events) do
element.__owner:UnregisterEvent(event, Update)
end
end
if options[option].disable then
options[option].disable(element.__owner)
end
end
if not options[option].countIgnored then
CountOption(element, state, oldState)
end
end
end
local function Enable(self)
if self.Fader then
self.Fader.__owner = self
self.Fader.ForceUpdate = ForceUpdate
self.Fader.SetOption = SetOption
self.Fader.ClearTimers = ClearTimers
self.Fader.MinAlpha = MIN_ALPHA
self.Fader.MaxAlpha = MAX_ALPHA
return true
end
end
local function Disable(self)
if self.Fader then
for opt in pairs(options) do
if opt == 'Target' then
self.Fader:SetOption('UnitTarget')
self.Fader:SetOption('PlayerTarget')
else
self.Fader:SetOption(opt)
end
end
self.Fader.count = nil
self.Fader:ClearTimers()
end
end
oUF:AddElement('Fader', nil, Enable, Disable)

View File

@@ -0,0 +1,63 @@
local _, ns = ...
local oUF = ns.oUF or oUF
assert(oUF, 'oUF not loaded')
local Update = function(self, event, unit)
if event == 'ARENA_OPPONENT_UPDATE' and unit ~= self.unit then return; end
local specIcon = self.PVPSpecIcon
local _, instanceType = IsInInstance();
specIcon.instanceType = instanceType
if(specIcon.PreUpdate) then specIcon:PreUpdate(event) end
if instanceType == 'arena' then
local ID = self.unit:match('arena(%d)') or self:GetID() or 0
local specID = GetArenaOpponentSpec(tonumber(ID))
if specID and specID > 0 then
local _, _, _, icon = GetSpecializationInfoByID(specID);
specIcon.Icon:SetTexture(icon)
else
specIcon.Icon:SetTexture([[INTERFACE\ICONS\INV_MISC_QUESTIONMARK]])
end
else
local unitFactionGroup = UnitFactionGroup(self.unit)
if unitFactionGroup == "Horde" then
specIcon.Icon:SetTexture([[Interface\Icons\INV_BannerPVP_01]])
elseif unitFactionGroup == 'Alliance' then
specIcon.Icon:SetTexture([[Interface\Icons\INV_BannerPVP_02]])
else
specIcon.Icon:SetTexture([[INTERFACE\ICONS\INV_MISC_QUESTIONMARK]])
end
end
if(specIcon.PostUpdate) then specIcon:PostUpdate(event) end
end
local Enable = function(self)
local specIcon = self.PVPSpecIcon
if specIcon then
self:RegisterEvent("ARENA_OPPONENT_UPDATE", Update, true)
self:RegisterEvent("PLAYER_ENTERING_WORLD", Update, true)
if not specIcon.Icon then
specIcon.Icon = specIcon:CreateTexture(nil, "OVERLAY")
specIcon.Icon:SetAllPoints(specIcon)
specIcon.Icon:SetTexCoord(0.07, 0.93, 0.07, 0.93)
end
specIcon:Show()
return true
end
end
local Disable = function(self)
local specIcon = self.PVPSpecIcon
if specIcon then
self:UnregisterEvent("ARENA_PREP_OPPONENT_SPECIALIZATIONS", Update)
self:UnregisterEvent("ARENA_OPPONENT_UPDATE", Update)
self:UnregisterEvent("PLAYER_ENTERING_WORLD", Update)
specIcon:Hide()
end
end
oUF:AddElement('PVPSpecIcon', Update, Enable, Disable)

View File

@@ -0,0 +1,9 @@
## Interface: 50001
## Title: oUF Arena Spec Icons
## Notes: Adds spec icons to arena frames.
## Author: Elv
## Version: 1.00
## X-Category: oUF
## Dependencies: oUF
oUF_PVPSpecIcons.lua

View File

@@ -0,0 +1,10 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/">
<Script file="oUF_AuraBars\oUF_AuraBars.lua"/>
<Script file="oUF_AuraHighlight\oUF_AuraHighlight.lua"/>
<Script file="oUF_AuraWatch\oUF_AuraWatch.lua"/>
<Script file="oUF_Cutaway\oUF_Cutaway.lua"/>
<Script file="oUF_Fader\oUF_Fader.lua"/>
<Script file="oUF_RaidDebuffs\oUF_RaidDebuffs.lua"/>
<Script file="oUF_Trinkets\oUF_Trinkets.lua"/>
<Script file='oUF_PVPSpecIcons\oUF_PVPSpecIcons.lua'/>
</Ui>

View File

@@ -0,0 +1,327 @@
local _, ns = ...
local oUF = ns.oUF or oUF
local _G = _G
local addon = {}
ns.oUF_RaidDebuffs = addon
_G.oUF_RaidDebuffs = ns.oUF_RaidDebuffs
if not _G.oUF_RaidDebuffs then
_G.oUF_RaidDebuffs = addon
end
local format, floor = format, floor
local type, pairs, wipe = type, pairs, wipe
local GetActiveSpecGroup = GetActiveSpecGroup
local GetSpecialization = GetSpecialization
local GetSpellInfo = GetSpellInfo
local GetTime = GetTime
local UnitAura = UnitAura
local UnitCanAttack = UnitCanAttack
local UnitIsCharmed = UnitIsCharmed
local debuff_data = {}
addon.DebuffData = debuff_data
addon.ShowDispellableDebuff = true
addon.FilterDispellableDebuff = true
addon.MatchBySpellName = false
addon.priority = 10
local function add(spell, priority, stackThreshold)
if addon.MatchBySpellName and type(spell) == 'number' then
spell = GetSpellInfo(spell)
end
if(spell) then
debuff_data[spell] = {
priority = (addon.priority + priority),
stackThreshold = (stackThreshold or 0),
}
end
end
function addon:RegisterDebuffs(t)
for spell, value in pairs(t) do
if type(t[spell]) == 'boolean' then
local oldValue = t[spell]
t[spell] = { enable = oldValue, priority = 0, stackThreshold = 0 }
else
if t[spell].enable then
add(spell, t[spell].priority, t[spell].stackThreshold)
end
end
end
end
function addon:ResetDebuffData()
wipe(debuff_data)
end
local DispellColor = {
['Magic'] = {.2, .6, 1},
['Curse'] = {.6, 0, 1},
['Disease'] = {.6, .4, 0},
['Poison'] = {0, .6, 0},
['none'] = { .23, .23, .23},
}
local DispellPriority = {
['Magic'] = 4,
['Curse'] = 3,
['Disease'] = 2,
['Poison'] = 1,
}
local DispellFilter
do
local dispellClasses = {
['PRIEST'] = {
['Magic'] = true,
['Disease'] = true,
},
['SHAMAN'] = {
['Magic'] = false,
['Curse'] = true,
},
['PALADIN'] = {
['Poison'] = true,
['Magic'] = false,
['Disease'] = true,
},
['DRUID'] = {
['Magic'] = false,
['Curse'] = true,
['Poison'] = true,
['Disease'] = false,
},
['MONK'] = {
['Magic'] = false,
['Disease'] = true,
['Poison'] = true,
},
}
DispellFilter = dispellClasses[select(2, UnitClass('player'))] or {}
end
local function CheckTalentTree(tree)
local activeGroup = GetActiveSpecGroup()
if activeGroup and GetSpecialization(false, false, activeGroup) then
return tree == GetSpecialization(false, false, activeGroup)
end
end
local playerClass = select(2, UnitClass('player'))
local function CheckSpec(self, event, levels)
-- Not interested in gained points from leveling
if event == "CHARACTER_POINTS_CHANGED" and levels > 0 then return end
--Check for certain talents to see if we can dispel magic or not
if playerClass == "PALADIN" then
if CheckTalentTree(1) then
DispellFilter.Magic = true
else
DispellFilter.Magic = false
end
elseif playerClass == "SHAMAN" then
if CheckTalentTree(3) then
DispellFilter.Magic = true
else
DispellFilter.Magic = false
end
elseif playerClass == "DRUID" then
if CheckTalentTree(4) then
DispellFilter.Magic = true
else
DispellFilter.Magic = false
end
elseif playerClass == "MONK" then
if CheckTalentTree(2) then
DispellFilter.Magic = true
else
DispellFilter.Magic = false
end
end
end
local function formatTime(s)
if s > 60 then
return format('%dm', s/60), s%60
elseif s < 1 then
return format("%.1f", s), s - floor(s)
else
return format('%d', s), s - floor(s)
end
end
local abs = math.abs
local function OnUpdate(self, elapsed)
self.elapsed = (self.elapsed or 0) + elapsed
if self.elapsed >= 0.1 then
local timeLeft = self.endTime - GetTime()
if self.reverse then timeLeft = abs((self.endTime - GetTime()) - self.duration) end
if timeLeft > 0 then
local text = formatTime(timeLeft)
self.time:SetText(text)
else
self:SetScript('OnUpdate', nil)
self.time:Hide()
end
self.elapsed = 0
end
end
local function UpdateDebuff(self, name, icon, count, debuffType, duration, endTime, spellId, stackThreshold)
local f = self.RaidDebuffs
if name and (count >= stackThreshold) then
f.icon:SetTexture(icon)
f.icon:Show()
f.duration = duration
if f.count then
if count and (count > 1) then
f.count:SetText(count)
f.count:Show()
else
f.count:SetText("")
f.count:Hide()
end
end
if spellId and _G.ElvUI[1].ReverseTimer[spellId] then
f.reverse = true
else
f.reverse = nil
end
if f.time then
if duration and (duration > 0) then
f.endTime = endTime
f.nextUpdate = 0
f:SetScript('OnUpdate', OnUpdate)
f.time:Show()
else
f:SetScript('OnUpdate', nil)
f.time:Hide()
end
end
if f.cd then
if duration and (duration > 0) then
f.cd:SetCooldown(endTime - duration, duration)
f.cd:Show()
else
f.cd:Hide()
end
end
local c = DispellColor[debuffType] or DispellColor.none
f:SetBackdropBorderColor(c[1], c[2], c[3])
f:Show()
else
f:Hide()
end
end
local blackList = {
[105171] = true, -- Deep Corruption
[108220] = true, -- Deep Corruption
[116095] = true, -- Disable, Slow
[137637] = true, -- Warbringer, Slow
}
local function Update(self, event, unit)
if unit ~= self.unit then return end
local _name, _icon, _count, _dtype, _duration, _endTime, _spellId, _
local _priority, priority = 0, 0
local _stackThreshold = 0
--store if the unit its charmed, mind controlled units (Imperial Vizier Zor'lok: Convert)
local isCharmed = UnitIsCharmed(unit)
--store if we cand attack that unit, if its so the unit its hostile (Amber-Shaper Un'sok: Reshape Life)
local canAttack = UnitCanAttack("player", unit)
for i = 1, 40 do
local name, icon, count, debuffType, duration, expirationTime, unitCaster, isStealable, shouldConsolidate, spellId, canApplyAura, isBossDebuff = UnitAura(unit, i, 'HARMFUL')
if (not name) then break end
--we coudln't dispell if the unit its charmed, or its not friendly
if addon.ShowDispellableDebuff and (self.RaidDebuffs.showDispellableDebuff ~= false) and debuffType and (not isCharmed) and (not canAttack) then
if addon.FilterDispellableDebuff then
DispellPriority[debuffType] = (DispellPriority[debuffType] or 0) + addon.priority --Make Dispell buffs on top of Boss Debuffs
priority = DispellFilter[debuffType] and DispellPriority[debuffType] or 0
if priority == 0 then
debuffType = nil
end
else
priority = DispellPriority[debuffType] or 0
end
if priority > _priority then
_priority, _name, _icon, _count, _dtype, _duration, _endTime, _spellId = priority, name, icon, count, debuffType, duration, expirationTime, spellId
end
end
local debuff
if self.RaidDebuffs.onlyMatchSpellID then
debuff = debuff_data[spellId]
else
if debuff_data[spellId] then
debuff = debuff_data[spellId]
else
debuff = debuff_data[name]
end
end
priority = debuff and debuff.priority
if priority and not blackList[spellId] and (priority > _priority) then
_priority, _name, _icon, _count, _dtype, _duration, _endTime, _spellId = priority, name, icon, count, debuffType, duration, expirationTime, spellId
end
end
if self.RaidDebuffs.forceShow then
_spellId = 47540
_name, _, _icon = GetSpellInfo(_spellId)
_count, _dtype, _duration, _endTime, _stackThreshold = 5, 'Magic', 0, 60, 0
end
if _name then
_stackThreshold = debuff_data[addon.MatchBySpellName and _name or _spellId] and debuff_data[addon.MatchBySpellName and _name or _spellId].stackThreshold or _stackThreshold
end
UpdateDebuff(self, _name, _icon, _count, _dtype, _duration, _endTime, _spellId, _stackThreshold)
--Reset the DispellPriority
DispellPriority['Magic'] = 4
DispellPriority['Curse'] = 3
DispellPriority['Disease'] = 2
DispellPriority['Poison'] = 1
end
local function Enable(self)
self:RegisterEvent("PLAYER_TALENT_UPDATE", CheckSpec, true)
self:RegisterEvent("CHARACTER_POINTS_CHANGED", CheckSpec, true)
if self.RaidDebuffs then
self:RegisterEvent('UNIT_AURA', Update)
return true
end
end
local function Disable(self)
if self.RaidDebuffs then
self:UnregisterEvent('UNIT_AURA', Update)
self.RaidDebuffs:Hide()
end
self:UnregisterEvent("PLAYER_TALENT_UPDATE", CheckSpec)
self:UnregisterEvent("CHARACTER_POINTS_CHANGED", CheckSpec)
end
oUF:AddElement('RaidDebuffs', Update, Enable, Disable)

View File

@@ -0,0 +1,7 @@
## Interface: 30300
## Title: oUF RaidDebuffs
## Notes: Raid debuff mod for oUF
## Version: 1.2
## OptionalDeps: oUF
oUF_RaidDebuffs.lua

View File

@@ -0,0 +1,81 @@
local _, ns = ...
local oUF = ns.oUF or oUF
assert(oUF, 'oUF not loaded')
local trinketSpells = {
[311430] = 120, -- Re-Arm (PvP Trinket 9.0.1)
[59752] = 180, -- Will to Survive (Human Racial)
[7744] = 120, -- Will of the Forsaken (Undead Racial)
}
local GetTrinketIcon = function(unit)
if UnitFactionGroup(unit) == "Horde" then
return "Interface\\Icons\\INV_Jewelry_TrinketPVP_02"
else
return "Interface\\Icons\\INV_Jewelry_TrinketPVP_01"
end
end
local Update = function(self, event, ...)
local _, instanceType = IsInInstance();
if instanceType ~= 'arena' then
self.Trinket:Hide();
return;
else
self.Trinket:Show();
end
if(self.Trinket.PreUpdate) then self.Trinket:PreUpdate(event) end
if event == "COMBAT_LOG_EVENT_UNFILTERED" then
local _, eventType, _, sourceGUID, _, _, _, _, _, _, _, spellID = CombatLogGetCurrentEventInfo()
if eventType == "SPELL_CAST_SUCCESS" and sourceGUID == UnitGUID(self.unit) and trinketSpells[spellID] then
CooldownFrame_Set(self.Trinket.cooldownFrame, GetTime(), trinketSpells[spellID], 1)
end
elseif event == "ARENA_OPPONENT_UPDATE" then
local unit, type = ...
if type == "seen" then
if UnitExists(unit) and UnitIsPlayer(unit) then
self.Trinket.Icon:SetTexture(GetTrinketIcon(unit))
end
end
elseif event == 'PLAYER_ENTERING_WORLD' then
CooldownFrame_Set(self.Trinket.cooldownFrame, 1, 1, 1)
end
if(self.Trinket.PostUpdate) then self.Trinket:PostUpdate(event) end
end
local Enable = function(self)
if self.Trinket then
self:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED", Update, true)
self:RegisterEvent("ARENA_OPPONENT_UPDATE", Update, true)
self:RegisterEvent("PLAYER_ENTERING_WORLD", Update, true)
if not self.Trinket.cooldownFrame then
self.Trinket.cooldownFrame = CreateFrame("Cooldown", nil, self.Trinket, "CooldownFrameTemplate")
self.Trinket.cooldownFrame:SetAllPoints(self.Trinket)
ElvUI[1]:RegisterCooldown(self.Trinket.cooldownFrame)
end
if not self.Trinket.Icon then
self.Trinket.Icon = self.Trinket:CreateTexture(nil, "BORDER")
self.Trinket.Icon:SetAllPoints(self.Trinket)
self.Trinket.Icon:SetTexCoord(0.07, 0.93, 0.07, 0.93)
self.Trinket.Icon:SetTexture(GetTrinketIcon('player'))
end
return true
end
end
local Disable = function(self)
if self.Trinket then
self:UnregisterEvent("COMBAT_LOG_EVENT_UNFILTERED", Update)
self:UnregisterEvent("ARENA_OPPONENT_UPDATE", Update)
self:UnregisterEvent("PLAYER_ENTERING_WORLD", Update)
self.Trinket:Hide()
end
end
oUF:AddElement('Trinket', Update, Enable, Disable)

View File

@@ -0,0 +1,9 @@
## Interface: 50001
## Title: oUF Trinkets
## Notes: Adds PvP trinket status to oUF frames.
## Author: Elv
## Version: 1.00
## X-Category: oUF
## Dependencies: oUF
oUF_Trinkets.lua