---------------
-- Globals --
---------------
DBM.InfoFrame = { }
-------------------
-- Local Globals --
-------------------
local isRetail = WOW_PROJECT_ID == ( WOW_PROJECT_MAINLINE or 1 )
local DBM = DBM
local L = DBM_CORE_L
local UnitClass , GetTime , GetPartyAssignment , UnitGroupRolesAssigned , GetRaidTargetIndex , UnitExists , UnitGetTotalAbsorbs , UnitName , UnitHealth , UnitPower , UnitPowerMax , UnitIsDeadOrGhost , UnitThreatSituation , UnitPosition , UnitIsUnit , UIDropDownMenu_CreateInfo , UIDropDownMenu_AddButton = UnitClass , GetTime , GetPartyAssignment , UnitGroupRolesAssigned , GetRaidTargetIndex , UnitExists , UnitGetTotalAbsorbs , UnitName , UnitHealth , UnitPower , UnitPowerMax , UnitIsDeadOrGhost , UnitThreatSituation , UnitPosition , UnitIsUnit , UIDropDownMenu_CreateInfo , UIDropDownMenu_AddButton
local error , tostring , type , pairs , ipairs , select , tonumber , tsort , twipe , mfloor , mmax , mmin , mrandom , schar , ssplit = error , tostring , type , pairs , ipairs , select , tonumber , table.sort , table.wipe , math.floor , math.max , math.min , math.random , string.char , string.split
local NORMAL_FONT_COLOR , SPELL_FAILED_OUT_OF_RANGE = NORMAL_FONT_COLOR , SPELL_FAILED_OUT_OF_RANGE
local RAID_CLASS_COLORS = _G [ " CUSTOM_CLASS_COLORS " ] or RAID_CLASS_COLORS -- for Phanx' Class Colors
--Hard code STANDARD_TEXT_FONT since skinning mods like to taint it (or worse, set it to nil, wtf?)
local standardFont
if LOCALE_koKR then
standardFont = " Fonts \\ 2002.TTF "
elseif LOCALE_zhCN then
standardFont = " Fonts \\ ARKai_T.ttf "
elseif LOCALE_zhTW then
standardFont = " Fonts \\ blei00d.TTF "
elseif LOCALE_ruRU then
standardFont = " Fonts \\ FRIZQT___CYR.TTF "
else
standardFont = " Fonts \\ FRIZQT__.TTF "
end
--------------
-- Locals --
--------------
local infoFrame = DBM.InfoFrame
local frame , initializeDropdown , currentMapId , currentEvent , createFrame
local maxLines , modLines , maxCols , modCols , prevLines = 5 , 5 , 1 , 1 , 0
local sortMethod = 1 --1 Default, 2 SortAsc, 3 GroupId
local lines , sortedLines , icons , value = { } , { } , { } , { }
local playerName = UnitName ( " player " )
local maxIcon = 8
---------------------
-- Dropdown Menu --
---------------------
do
local function toggleLocked ( )
DBM.Options . InfoFrameLocked = not DBM.Options . InfoFrameLocked
end
local function toggleShowSelf ( )
DBM.Options . InfoFrameShowSelf = not DBM.Options . InfoFrameShowSelf
end
local function setLines ( _ , line )
prevLines = 0
DBM.Options . InfoFrameLines = line
if line ~= 0 then
maxLines = line
else
maxLines = modLines or 5
end
end
local function setCols ( _ , col )
prevLines = 0
DBM.Options . InfoFrameCols = col
if col ~= 0 then
maxCols = col
else
maxCols = modCols or 5
end
end
function initializeDropdown ( _ , level , menu )
local info
if level == 1 then
info = UIDropDownMenu_CreateInfo ( )
info.text = LOCK_FRAME
if DBM.Options . InfoFrameLocked then
info.checked = true
end
info.func = toggleLocked
UIDropDownMenu_AddButton ( info , 1 )
info = UIDropDownMenu_CreateInfo ( )
info.keepShownOnClick = true
info.text = L.INFOFRAME_SHOW_SELF
if DBM.Options . InfoFrameShowSelf then
info.checked = true
end
info.func = toggleShowSelf
UIDropDownMenu_AddButton ( info , 1 )
info = UIDropDownMenu_CreateInfo ( )
info.text = L.INFOFRAME_SETLINES
info.notCheckable = true
info.hasArrow = true
info.keepShownOnClick = true
info.menuList = " lines "
UIDropDownMenu_AddButton ( info , 1 )
info = UIDropDownMenu_CreateInfo ( )
info.text = L.INFOFRAME_SETCOLS
info.notCheckable = true
info.hasArrow = true
info.keepShownOnClick = true
info.menuList = " cols "
UIDropDownMenu_AddButton ( info , 1 )
info = UIDropDownMenu_CreateInfo ( )
info.text = HIDE
info.notCheckable = true
info.func = infoFrame.Hide
info.arg1 = infoFrame
UIDropDownMenu_AddButton ( info , 1 )
elseif level == 2 then
if menu == " lines " then
info = UIDropDownMenu_CreateInfo ( )
info.text = L.INFOFRAME_LINESDEFAULT
info.func = setLines
info.arg1 = 0
info.checked = ( DBM.Options . InfoFrameLines == 0 )
UIDropDownMenu_AddButton ( info , 2 )
info = UIDropDownMenu_CreateInfo ( )
info.text = L.INFOFRAME_LINES_TO : format ( 3 )
info.func = setLines
info.arg1 = 3
info.checked = ( DBM.Options . InfoFrameLines == 3 )
UIDropDownMenu_AddButton ( info , 2 )
info = UIDropDownMenu_CreateInfo ( )
info.text = L.INFOFRAME_LINES_TO : format ( 5 )
info.func = setLines
info.arg1 = 5
info.checked = ( DBM.Options . InfoFrameLines == 5 )
UIDropDownMenu_AddButton ( info , 2 )
info = UIDropDownMenu_CreateInfo ( )
info.text = L.INFOFRAME_LINES_TO : format ( 8 )
info.func = setLines
info.arg1 = 8
info.checked = ( DBM.Options . InfoFrameLines == 8 )
UIDropDownMenu_AddButton ( info , 2 )
info = UIDropDownMenu_CreateInfo ( )
info.text = L.INFOFRAME_LINES_TO : format ( 10 )
info.func = setLines
info.arg1 = 10
info.checked = ( DBM.Options . InfoFrameLines == 10 )
UIDropDownMenu_AddButton ( info , 2 )
info = UIDropDownMenu_CreateInfo ( )
info.text = L.INFOFRAME_LINES_TO : format ( 15 )
info.func = setLines
info.arg1 = 15
info.checked = ( DBM.Options . InfoFrameLines == 15 )
UIDropDownMenu_AddButton ( info , 2 )
info = UIDropDownMenu_CreateInfo ( )
info.text = L.INFOFRAME_LINES_TO : format ( 20 )
info.func = setLines
info.arg1 = 20
info.checked = ( DBM.Options . InfoFrameLines == 20 )
UIDropDownMenu_AddButton ( info , 2 )
info = UIDropDownMenu_CreateInfo ( )
info.text = L.INFOFRAME_LINES_TO : format ( isRetail and 30 or 40 )
info.func = setLines
info.arg1 = isRetail and 30 or 40 -- Use 40 in classic for full man raids
info.checked = ( DBM.Options . InfoFrameLines == 30 )
UIDropDownMenu_AddButton ( info , 2 )
elseif menu == " cols " then
info = UIDropDownMenu_CreateInfo ( )
info.text = L.INFOFRAME_LINESDEFAULT
info.func = setCols
info.arg1 = 0
info.checked = ( DBM.Options . InfoFrameCols == 0 )
UIDropDownMenu_AddButton ( info , 2 )
info = UIDropDownMenu_CreateInfo ( )
info.text = L.INFOFRAME_COLS_TO : format ( 1 )
info.func = setCols
info.arg1 = 1
info.checked = ( DBM.Options . InfoFrameCols == 1 )
UIDropDownMenu_AddButton ( info , 2 )
info = UIDropDownMenu_CreateInfo ( )
info.text = L.INFOFRAME_COLS_TO : format ( 2 )
info.func = setCols
info.arg1 = 2
info.checked = ( DBM.Options . InfoFrameCols == 2 )
UIDropDownMenu_AddButton ( info , 2 )
info = UIDropDownMenu_CreateInfo ( )
info.text = L.INFOFRAME_COLS_TO : format ( 3 )
info.func = setCols
info.arg1 = 3
info.checked = ( DBM.Options . InfoFrameCols == 3 )
UIDropDownMenu_AddButton ( info , 2 )
info = UIDropDownMenu_CreateInfo ( )
info.text = L.INFOFRAME_COLS_TO : format ( 4 )
info.func = setCols
info.arg1 = 4
info.checked = ( DBM.Options . InfoFrameCols == 4 )
UIDropDownMenu_AddButton ( info , 2 )
info = UIDropDownMenu_CreateInfo ( )
info.text = L.INFOFRAME_COLS_TO : format ( 5 )
info.func = setCols
info.arg1 = 5
info.checked = ( DBM.Options . InfoFrameCols == 5 )
UIDropDownMenu_AddButton ( info , 2 )
info = UIDropDownMenu_CreateInfo ( )
info.text = L.INFOFRAME_COLS_TO : format ( 6 )
info.func = setCols
info.arg1 = 6
info.checked = ( DBM.Options . InfoFrameCols == 6 )
UIDropDownMenu_AddButton ( info , 2 )
end
end
end
end
------------------------
-- Create the frame --
------------------------
function createFrame ( )
frame = CreateFrame ( " Frame " , " DBMInfoFrame " , UIParent , " BackdropTemplate " )
frame : Hide ( )
frame : SetFrameStrata ( " DIALOG " )
frame.backdropInfo = {
bgFile = " Interface \\ DialogFrame \\ UI-DialogBox-Background " , -- 131071
tile = true ,
tileSize = 16
}
frame : ApplyBackdrop ( )
frame : SetPoint ( DBM.Options . InfoFramePoint , UIParent , DBM.Options . InfoFramePoint , DBM.Options . InfoFrameX , DBM.Options . InfoFrameY )
frame : SetSize ( 10 , 10 )
frame : SetClampedToScreen ( true )
frame : EnableMouse ( true )
frame : SetToplevel ( true )
frame : SetMovable ( true )
frame : RegisterForDrag ( " LeftButton " )
frame : SetScript ( " OnDragStart " , function ( self )
if not DBM.Options . InfoFrameLocked then
self : StartMoving ( )
end
end )
frame : SetScript ( " OnDragStop " , function ( self )
self : StopMovingOrSizing ( )
local point , _ , _ , x , y = self : GetPoint ( 1 )
DBM.Options . InfoFrameX = x
DBM.Options . InfoFrameY = y
DBM.Options . InfoFramePoint = point
end )
frame : SetScript ( " OnEvent " , function ( self , event , ... )
if infoFrame [ event ] then
infoFrame [ event ] ( self , ... )
end
end )
frame : SetScript ( " OnMouseDown " , function ( _ , button )
if button == " RightButton " then
local dropdownFrame = CreateFrame ( " Frame " , " DBMInfoFrameDropdown " , frame , " UIDropDownMenuTemplate " )
UIDropDownMenu_Initialize ( dropdownFrame , initializeDropdown )
ToggleDropDownMenu ( 1 , nil , dropdownFrame , " cursor " , 5 , - 10 )
end
end )
local header = frame : CreateFontString ( nil , " OVERLAY " , " GameFontNormal " )
header : SetTextColor ( 1 , 1 , 1 )
header : SetPoint ( " BOTTOMLEFT " , frame , " TOPLEFT " , 2 , 2 )
frame.header = header
infoFrame : SetHeader ( )
frame.lines = { }
end
------------------------
-- Update functions --
------------------------
local updateCallbacks = { }
local function sortFuncDesc ( a , b )
return lines [ a ] > lines [ b ]
end
local function sortFuncAsc ( a , b )
return lines [ a ] < lines [ b ]
end
local function sortGroupId ( a , b )
return DBM.GetGroupId ( DBM , a ) < DBM.GetGroupId ( DBM , b )
end
local function updateLines ( preSorted )
twipe ( sortedLines )
if preSorted then
-- Copy table as code from mod keeps around references this this and the "normal" table is wiped regularly
for i , v in ipairs ( preSorted ) do
sortedLines [ i ] = v
end
else
for i in pairs ( lines ) do
sortedLines [ # sortedLines + 1 ] = i
end
if sortMethod == 3 then
tsort ( sortedLines , sortGroupId )
elseif sortMethod == 2 then
tsort ( sortedLines , sortFuncAsc )
else
tsort ( sortedLines , sortFuncDesc )
end
end
for _ , v in ipairs ( updateCallbacks ) do
v ( sortedLines )
end
end
--[[
local function namesortFuncAsc ( a , b )
return a < b
end
local function updateNamesortLines ( )
twipe ( sortedLines )
for i in pairs ( lines ) do
sortedLines [ # sortedLines + 1 ] = i
end
tsort ( sortedLines , namesortFuncAsc )
for _ , v in ipairs ( updateCallbacks ) do
v ( sortedLines )
end
end
] ] --
local function updateLinesCustomSort ( sortFunc )
twipe ( sortedLines )
for i in pairs ( lines ) do
sortedLines [ # sortedLines + 1 ] = i
end
tsort ( sortedLines , sortFunc )
for _ , v in ipairs ( updateCallbacks ) do
v ( sortedLines )
end
end
local function updateIcons ( )
twipe ( icons )
for uId in DBM : GetGroupMembers ( ) do
local icon = GetRaidTargetIndex ( uId )
local icon2 = GetRaidTargetIndex ( uId .. " target " )
if icon and icon <= maxIcon then
icons [ DBM : GetUnitFullName ( uId ) ] = ( " |TInterface \\ TargetingFrame \\ UI-RaidTargetingIcon_%d:0|t " ) : format ( icon )
end
if icon2 and icon2 <= maxIcon then
icons [ DBM : GetUnitFullName ( uId .. " target " ) ] = ( " |TInterface \\ TargetingFrame \\ UI-RaidTargetingIcon_%d:0|t " ) : format ( icon2 )
end
end
for i = 1 , 5 do
local icon = GetRaidTargetIndex ( " boss " .. i )
if icon then
icons [ UnitName ( " boss " .. i ) ] = ( " |TInterface \\ TargetingFrame \\ UI-RaidTargetingIcon_%d:0|t " ) : format ( icon )
end
end
end
local function updateHealth ( )
twipe ( lines )
local threshold = value [ 1 ]
for uId in DBM : GetGroupMembers ( ) do
if UnitHealth ( uId ) < threshold and not UnitIsDeadOrGhost ( uId ) then
lines [ DBM : GetUnitFullName ( uId ) ] = UnitHealth ( uId ) - threshold
end
end
updateLines ( )
updateIcons ( )
end
local function updatePlayerPower ( )
twipe ( lines )
local threshold = value [ 1 ]
local powerType = value [ 2 ]
local spellFilter = value [ 3 ]
-- Value 4 is the noUpdate handler
-- Value 5 is sorting method, handled in show handler
for uId in DBM : GetGroupMembers ( ) do
if not spellFilter or not DBM : UnitDebuff ( uId , spellFilter ) then
local maxPower = UnitPowerMax ( uId , powerType )
if maxPower ~= 0 and not UnitIsDeadOrGhost ( uId ) and UnitPower ( uId , powerType ) / UnitPowerMax ( uId , powerType ) * 100 >= threshold then
lines [ DBM : GetUnitFullName ( uId ) ] = UnitPower ( uId , powerType )
end
end
end
if DBM.Options . InfoFrameShowSelf and not lines [ playerName ] and UnitPower ( " player " , powerType ) > 0 then
lines [ playerName ] = UnitPower ( " player " , powerType )
end
updateLines ( )
updateIcons ( )
end
local function updateEnemyPower ( )
twipe ( lines )
local threshold = value [ 1 ]
local powerType = value [ 2 ]
local specificUnit = value [ 3 ]
if powerType then -- Only do power type defined
if specificUnit then
if not isRetail then
specificUnit = UnitExists ( specificUnit ) or DBM : GetUnitIdFromGUID ( specificUnit ) --unitID already passed or GUID we convert into unitID
end
if UnitExists ( specificUnit ) then
local currentPower , maxPower = UnitPower ( specificUnit , powerType ) , UnitPowerMax ( specificUnit , powerType )
if maxPower and maxPower > 0 then
local percent = currentPower / maxPower * 100
if percent >= threshold then
lines [ UnitName ( specificUnit ) ] = mfloor ( percent ) .. " % "
end
end
end
else
for i = 1 , 5 do
local uId = " boss " .. i
local currentPower , maxPower = UnitPower ( uId ) , UnitPowerMax ( uId )
if maxPower and maxPower > 0 then
local percent = currentPower / maxPower * 100
if percent >= threshold then
lines [ UnitName ( uId ) ] = mfloor ( percent ) .. " % "
end
end
end
end
else -- Check primary power type and alternate power types together. This should only be used if BOTH power types exist on same boss
if specificUnit then
if not isRetail then
specificUnit = UnitExists ( specificUnit ) or DBM : GetUnitIdFromGUID ( specificUnit ) --unitID already passed or GUID we convert into unitID
end
if UnitExists ( specificUnit ) then
-- Primary Power
local currentPower , maxPower = UnitPower ( specificUnit ) , UnitPowerMax ( specificUnit )
if maxPower and maxPower > 0 then
local percent = currentPower / maxPower * 100
if percent >= threshold then
lines [ UnitName ( specificUnit ) ] = mfloor ( percent ) .. " % "
end
end
-- Alternate Power
local currentAltPower , maxAltPower = UnitPower ( specificUnit , 10 ) , UnitPowerMax ( specificUnit , 10 )
if maxAltPower and maxAltPower > 0 then
if currentAltPower / maxAltPower * 100 >= threshold then
lines [ UnitName ( specificUnit ) ] = L.INFOFRAME_ALT .. currentAltPower
end
end
end
else
for i = 1 , 5 do
local uId = " boss " .. i
-- Primary Power
local currentPower , maxPower = UnitPower ( uId ) , UnitPowerMax ( uId )
if maxPower and maxPower > 0 then
if currentPower / maxPower * 100 >= threshold then
lines [ UnitName ( uId ) ] = currentPower
end
end
-- Alternate Power
local currentAltPower , maxAltPower = UnitPower ( uId , 10 ) , UnitPowerMax ( uId , 10 )
if maxAltPower and maxAltPower > 0 then
if currentAltPower / maxAltPower * 100 >= threshold then
lines [ UnitName ( uId ) ] = L.INFOFRAME_ALT .. currentAltPower
end
end
end
end
end
updateLines ( )
updateIcons ( )
end
local function updateEnemyAbsorb ( )
twipe ( lines )
local spellInput = value [ 1 ]
local totalAbsorb = value [ 2 ]
local specificUnit = value [ 3 ]
if specificUnit then
specificUnit = UnitExists ( specificUnit ) or DBM : GetUnitIdFromGUID ( specificUnit ) --unitID already passed or GUID we convert into unitID
if UnitExists ( specificUnit ) then
local absorbAmount
if spellInput then -- Get specific spell absorb
absorbAmount = select ( 16 , DBM : UnitBuff ( specificUnit , spellInput ) ) or select ( 16 , DBM : UnitDebuff ( specificUnit , spellInput ) )
else -- Get all of them
absorbAmount = UnitGetTotalAbsorbs ( specificUnit )
end
if absorbAmount and absorbAmount > 0 then
if totalAbsorb then
lines [ UnitName ( specificUnit ) ] = mfloor ( absorbAmount / totalAbsorb * 100 ) .. " % "
else
lines [ UnitName ( specificUnit ) ] = mfloor ( absorbAmount )
end
end
end
else --Generic absorbs for bosses. Not to be mistaken for updateMultiEnemyAbsorb, which supports checking multiple units that might or might not be bosses
for i = 1 , 5 do
local uId = " boss " .. i
if UnitExists ( uId ) then
local absorbAmount
if spellInput then -- Get specific spell absorb
absorbAmount = select ( 16 , DBM : UnitBuff ( uId , spellInput ) ) or select ( 16 , DBM : UnitDebuff ( uId , spellInput ) )
else -- Get all of them
absorbAmount = UnitGetTotalAbsorbs ( uId )
end
if absorbAmount and absorbAmount > 0 then
if totalAbsorb then
lines [ UnitName ( uId ) ] = mfloor ( totalAbsorb and absorbAmount / totalAbsorb * 100 ) .. " % "
else
lines [ UnitName ( uId ) ] = mfloor ( absorbAmount )
end
end
end
end
end
updateLines ( )
updateIcons ( )
end
--Really hate splitting this off from updateEnemyAbsorb but having them merged was even uglier
--Note, this method also less efficient than boss only or single unit absorb tracking.
--Don't use this function to be lazy (ie just passing 1 guid instead of finding valid unit at mod level)
local function updateMultiEnemyAbsorb ( )
twipe ( lines )
local spellInput = value [ 1 ]
local totalAbsorb = value [ 2 ]
local guidTable = value [ 3 ] --Multi target by table
local guidTracked = { }
for i = 1 , 5 do
if # guidTable == # guidTracked then --Stop searching, found everything we're looking for.
break
end
local uId = " boss " .. i
if UnitExists ( uId ) then
local targetGUID = UnitGUID ( uId )
if guidTable [ targetGUID ] and not guidTracked [ targetGUID ] then
guidTracked [ targetGUID ] = true
local absorbAmount
if spellInput then -- Get specific spell absorb
absorbAmount = select ( 16 , DBM : UnitBuff ( uId , spellInput ) ) or select ( 16 , DBM : UnitDebuff ( uId , spellInput ) )
else -- Get all of them
absorbAmount = UnitGetTotalAbsorbs ( uId )
end
if absorbAmount and absorbAmount > 0 then
if totalAbsorb then
lines [ UnitName ( uId ) ] = mfloor ( totalAbsorb and absorbAmount / totalAbsorb * 100 ) .. " % "
else
lines [ UnitName ( uId ) ] = mfloor ( absorbAmount )
end
end
end
end
end
for unitId in DBM : GetGroupMembers ( ) do --Do not use self on this function, because self might be bossModPrototype
if # guidTable == # guidTracked then --Stop searching, found everything we're looking for.
break
end
local uId = unitId .. " target "
local targetGUID = UnitGUID ( unitId )
if guidTable [ targetGUID ] and not guidTracked [ targetGUID ] then
guidTracked [ targetGUID ] = true
local absorbAmount
if spellInput then -- Get specific spell absorb
absorbAmount = select ( 16 , DBM : UnitBuff ( uId , spellInput ) ) or select ( 16 , DBM : UnitDebuff ( uId , spellInput ) )
else -- Get all of them
absorbAmount = UnitGetTotalAbsorbs ( uId )
end
if absorbAmount and absorbAmount > 0 then
if totalAbsorb then
lines [ UnitName ( uId ) ] = mfloor ( totalAbsorb and absorbAmount / totalAbsorb * 100 ) .. " % "
else
lines [ UnitName ( uId ) ] = mfloor ( absorbAmount )
end
end
end
end
updateLines ( )
updateIcons ( )
end
local function updateAllAbsorb ( )
twipe ( lines )
local spellInput = value [ 1 ]
local totalAbsorb = value [ 2 ]
for i = 1 , 5 do
local uId = " boss " .. i
if UnitExists ( uId ) then
local absorbAmount
if spellInput then -- Get specific spell absorb
absorbAmount = select ( 16 , DBM : UnitBuff ( uId , spellInput ) ) or select ( 16 , DBM : UnitDebuff ( uId , spellInput ) )
else -- Get all of them
absorbAmount = UnitGetTotalAbsorbs ( uId )
end
if absorbAmount and absorbAmount > 0 then
if totalAbsorb then
lines [ UnitName ( uId ) ] = mfloor ( totalAbsorb and absorbAmount / totalAbsorb * 100 ) .. " % "
else
lines [ UnitName ( uId ) ] = mfloor ( absorbAmount )
end
end
end
end
if spellInput then
for uId in DBM : GetGroupMembers ( ) do
local absorbAmount = select ( 16 , DBM : UnitBuff ( uId , spellInput ) ) or select ( 16 , DBM : UnitDebuff ( uId , spellInput ) )
if absorbAmount and absorbAmount > 0 then
if totalAbsorb then
lines [ UnitName ( uId ) ] = mfloor ( totalAbsorb and absorbAmount / totalAbsorb * 100 ) .. " % "
else
lines [ UnitName ( uId ) ] = mfloor ( absorbAmount )
end
end
end
end
updateLines ( )
updateIcons ( )
end
local function updatePlayerAbsorb ( )
twipe ( lines )
local spellInput = value [ 1 ]
local totalAbsorb = value [ 2 ]
for uId in DBM : GetGroupMembers ( ) do
local absorbAmount
if spellInput then -- Get specific spell absorb
absorbAmount = select ( 16 , DBM : UnitBuff ( uId , spellInput ) ) or select ( 16 , DBM : UnitDebuff ( uId , spellInput ) )
else --Not even spell input given, this is a very generic infoframe
absorbAmount = UnitGetTotalAbsorbs ( uId )
end
if absorbAmount and absorbAmount > 0 then
if totalAbsorb then
lines [ UnitName ( uId ) ] = mfloor ( totalAbsorb and absorbAmount / totalAbsorb * 100 ) .. " % "
else
lines [ UnitName ( uId ) ] = mfloor ( absorbAmount )
end
end
end
updateLines ( )
updateIcons ( )
end
-- Buffs that are good to have, therefor bad not to have them.
local function updatePlayerBuffs ( )
twipe ( lines )
local spellName = value [ 1 ]
local tankIgnored = value [ 2 ]
for uId in DBM : GetGroupMembers ( ) do
if tankIgnored and ( UnitGroupRolesAssigned ( uId ) == " TANK " or GetPartyAssignment ( " MAINTANK " , uId , 1 ) ) then
else
if not DBM : UnitBuff ( uId , spellName ) and not UnitIsDeadOrGhost ( uId ) then
lines [ DBM : GetUnitFullName ( uId ) ] = " "
end
end
end
updateLines ( )
updateIcons ( )
end
-- Debuffs that are good to have, therefor it's bad NOT to have them.
local function updateGoodPlayerDebuffs ( )
twipe ( lines )
local spellInput = value [ 1 ]
local tankIgnored = value [ 2 ]
for uId in DBM : GetGroupMembers ( ) do
if tankIgnored and ( UnitGroupRolesAssigned ( uId ) == " TANK " or GetPartyAssignment ( " MAINTANK " , uId , 1 ) ) then
else
if not DBM : UnitDebuff ( uId , spellInput ) and not UnitIsDeadOrGhost ( uId ) then
lines [ DBM : GetUnitFullName ( uId ) ] = " "
end
end
end
updateLines ( )
updateIcons ( )
end
-- Debuffs that are bad to have, therefor it is bad to have them.
-- Function will auto handle spellName or spellId via DBMs unit debuff handler and spellInput type
local function updateBadPlayerDebuffs ( )
twipe ( lines )
local spellInput = value [ 1 ]
local tankIgnored = value [ 2 ]
for uId in DBM : GetGroupMembers ( ) do
if tankIgnored and ( UnitGroupRolesAssigned ( uId ) == " TANK " or GetPartyAssignment ( " MAINTANK " , uId , 1 ) ) then
else
if DBM : UnitDebuff ( uId , spellInput ) and not UnitIsDeadOrGhost ( uId ) then
lines [ DBM : GetUnitFullName ( uId ) ] = " "
end
end
end
updateLines ( )
updateIcons ( )
end
--Debuffs with important durations that we track
local function updatePlayerDebuffRemaining ( )
twipe ( lines )
local spellInput = value [ 1 ]
for uId in DBM : GetGroupMembers ( ) do
local expires = select ( 6 , DBM : UnitDebuff ( uId , spellInput ) )
if expires then
if expires == 0 then
lines [ DBM : GetUnitFullName ( uId ) ] = 9000 --Force sorting the unknowns under the ones we do know.
else
local debuffTime = expires - GetTime ( )
lines [ DBM : GetUnitFullName ( uId ) ] = mfloor ( debuffTime )
end
end
end
updateLines ( )
updateIcons ( )
end
-- Buffs with important durations that we track
local function updatePlayerBuffRemaining ( )
twipe ( lines )
local spellInput = value [ 1 ]
for uId in DBM : GetGroupMembers ( ) do
local expires = select ( 6 , DBM : UnitBuff ( uId , spellInput ) )
if expires then
if expires == 0 then
lines [ DBM : GetUnitFullName ( uId ) ] = 9000 --Force sorting the unknowns under the ones we do know.
else
local debuffTime = expires - GetTime ( )
lines [ DBM : GetUnitFullName ( uId ) ] = mfloor ( debuffTime )
end
end
end
updateLines ( )
updateIcons ( )
end
-- Debuffs that are bad to have, but we want to show players who do NOT have them
-- Function will auto handle spellName or spellId via DBMs unit debuff handler and spellInput type
local function updateReverseBadPlayerDebuffs ( )
twipe ( lines )
local spellInput = value [ 1 ]
local tankIgnored = value [ 2 ]
for uId in DBM : GetGroupMembers ( ) do
if tankIgnored and ( UnitGroupRolesAssigned ( uId ) == " TANK " or GetPartyAssignment ( " MAINTANK " , uId , 1 ) ) then
else
if not DBM : UnitDebuff ( uId , spellInput ) and not UnitIsDeadOrGhost ( uId ) and not DBM : UnitBuff ( uId , 27827 ) then --27827 Spirit of Redemption. This particular info frame wants to ignore this
lines [ DBM : GetUnitFullName ( uId ) ] = " "
end
end
end
updateLines ( )
updateIcons ( )
end
local function updatePlayerBuffStacks ( )
twipe ( lines )
local spellInput = value [ 1 ]
for uId in DBM : GetGroupMembers ( ) do
local spellName , _ , count = DBM : UnitBuff ( uId , spellInput )
if spellName and count then
lines [ DBM : GetUnitFullName ( uId ) ] = count
end
end
updateIcons ( )
updateLines ( )
end
local function updatePlayerDebuffStacks ( )
twipe ( lines )
local spellInput = value [ 1 ]
for uId in DBM : GetGroupMembers ( ) do
local spellName , _ , count = DBM : UnitDebuff ( uId , spellInput )
if spellName and count then
lines [ DBM : GetUnitFullName ( uId ) ] = count
end
end
updateIcons ( )
updateLines ( )
end
local function updatePlayerAggro ( )
twipe ( lines )
local aggroType = value [ 1 ]
local tankIgnored = value [ 2 ]
for uId in DBM : GetGroupMembers ( ) do
if tankIgnored and ( UnitGroupRolesAssigned ( uId ) == " TANK " or GetPartyAssignment ( " MAINTANK " , uId , 1 ) ) then
else
local currentThreat = UnitThreatSituation ( uId ) or 0
if currentThreat >= aggroType then
lines [ DBM : GetUnitFullName ( uId ) ] = " "
end
end
end
updateLines ( )
updateIcons ( )
end
local function updatePlayerTargets ( )
twipe ( lines )
local cId = value [ 1 ]
for uId , _ in DBM : GetGroupMembers ( ) do
if DBM : GetUnitCreatureId ( uId .. " target " ) ~= cId and ( UnitGroupRolesAssigned ( uId ) == " DAMAGER " or UnitGroupRolesAssigned ( uId ) == " NONE " ) then
lines [ DBM : GetUnitFullName ( uId ) ] = " "
end
end
updateLines ( )
updateIcons ( )
end
local function updateByFunction ( )
local func = value [ 1 ]
local sortFunc = value [ 2 ]
local useIcon = value [ 3 ]
local presortedLines
lines , presortedLines = func ( )
if sortFunc then
if type ( sortFunc ) == " function " then
updateLinesCustomSort ( sortFunc )
else
updateLines ( )
end
else
updateLines ( presortedLines )
end
if useIcon then
updateIcons ( )
end
end
-- Unsorted table maintained by mod and just sent here.
-- Never updated by onupdate method, requires manual updates when mod updates table
local function updateByTable ( table )
twipe ( lines )
if table then
for i , v in pairs ( table ) do
lines [ i ] = v
end
end
updateLines ( )
updateIcons ( )
end
local function updateTest ( )
twipe ( lines )
lines [ " Alpha " ] = 1
lines [ " Beta " ] = 10
lines [ " Gamma " ] = 25
lines [ " Delta " ] = 50
lines [ " Epsilon " ] = 100
updateLines ( )
end
local test2Table
local function updateTest2 ( )
twipe ( lines )
if not test2Table then
test2Table = { }
for _ = 1 , 40 do
local ident = " "
for _ = 1 , mrandom ( 5 , 12 ) do
ident = ident .. schar ( mrandom ( 65 , 90 ) )
end
test2Table [ ident ] = mrandom ( 1 , 10 ) * 10
end
end
for k , v in pairs ( test2Table ) do
lines [ k ] = v
end
updateLines ( )
end
local test3Counter = 0
local function updateTest3 ( )
twipe ( lines )
if not test2Table then
test2Table = { }
for _ = 1 , 40 do
local ident = " "
for _ = 1 , mrandom ( 5 , 12 ) do
ident = ident .. schar ( mrandom ( 65 , 90 ) )
end
test2Table [ ident ] = mrandom ( 1 , 10 ) * 10
end
end
if test3Counter < 40 then
local count = 0
for k , _ in pairs ( test2Table ) do
if count > 40 - test3Counter then
break
end
count = count + 1
lines [ k ] = mrandom ( 1 , 10 ) * 10
end
test3Counter = test3Counter + 1
end
updateLines ( )
end
local events = {
[ " health " ] = updateHealth ,
[ " playerpower " ] = updatePlayerPower ,
[ " enemypower " ] = updateEnemyPower ,
[ " enemyabsorb " ] = updateEnemyAbsorb ,
[ " multienemyabsorb " ] = updateMultiEnemyAbsorb ,
[ " allabsorb " ] = updateAllAbsorb ,
[ " playerabsorb " ] = updatePlayerAbsorb ,
[ " playerbuff " ] = updatePlayerBuffs ,
[ " playergooddebuff " ] = updateGoodPlayerDebuffs ,
[ " playerbaddebuff " ] = updateBadPlayerDebuffs ,
[ " playerdebuffremaining " ] = updatePlayerDebuffRemaining ,
[ " playerbuffremaining " ] = updatePlayerBuffRemaining ,
[ " reverseplayerbaddebuff " ] = updateReverseBadPlayerDebuffs ,
[ " playeraggro " ] = updatePlayerAggro ,
[ " playerbuffstacks " ] = updatePlayerBuffStacks ,
[ " playerdebuffstacks " ] = updatePlayerDebuffStacks ,
[ " playertargets " ] = updatePlayerTargets ,
[ " function " ] = updateByFunction ,
[ " table " ] = updateByTable ,
[ " test " ] = updateTest ,
[ " test2 " ] = updateTest2 ,
[ " test3 " ] = updateTest3
}
----------------
-- OnUpdate --
----------------
local friendlyEvents = {
[ " health " ] = true ,
[ " playerpower " ] = true ,
[ " playerabsorb " ] = true ,
[ " playerbuff " ] = true ,
[ " playergooddebuff " ] = true ,
[ " playerbaddebuff " ] = true ,
[ " playerdebuffremaining " ] = true ,
[ " playerbuffremaining " ] = true ,
[ " reverseplayerbaddebuff " ] = true ,
[ " playeraggro " ] = true ,
[ " playerbuffstacks " ] = true ,
[ " playerdebuffstacks " ] = true ,
[ " playertargets " ] = true
}
local function onUpdate ( frame , table )
if events [ currentEvent ] then
events [ currentEvent ] ( table )
else
if frame then
frame : Hide ( )
end
end
local color = NORMAL_FONT_COLOR
infoFrame : ClearLines ( )
local linesShown = 0
for i = 1 , # sortedLines do
if linesShown >= maxLines * maxCols then
break
end
local leftText = sortedLines [ i ]
if not leftText then
error ( " DBM InfoFrame: leftText cannot be nil, Notify DBM author. Infoframe force shutting down " , 2 )
frame : Hide ( )
return
elseif leftText and type ( leftText ) ~= " string " then
leftText = tostring ( leftText )
end
local rightText = lines [ leftText ]
local extra , extraName = ssplit ( " * " , leftText ) -- Find just unit name, if extra info had to be added to make unique
local icon = icons [ extraName or leftText ] and icons [ extraName or leftText ] .. leftText
if friendlyEvents [ currentEvent ] then
local unitId = DBM : GetRaidUnitId ( DBM : GetUnitFullName ( extraName or leftText ) ) or " player " --Prevent nil logical error
if unitId then
local _ , _ , _ , mapId = UnitPosition ( unitId )
if mapId == currentMapId then
local _ , class = UnitClass ( unitId )
if class then
color = RAID_CLASS_COLORS [ class ]
if DBM.Options . StripServerName then -- StripServerName option is checked here, even though it's checked in GetShortServerName function, because we have to apply custom 3rd column hack reconstruction
local shortName = DBM : GetShortServerName ( extraName or leftText )
if extraName then -- 3 column hack is present, we need to reconstruct leftText with shortened name
leftText = extra .. " * " .. shortName
else -- LeftText is name, just replace it with shortname
leftText = shortName
end
end
end
linesShown = linesShown + 1
if unitId and UnitIsUnit ( unitId , " player " ) then -- It's player.
if currentEvent == " health " or currentEvent == " playerpower " or currentEvent == " playerabsorb " or currentEvent == " playerbuff " or currentEvent == " playergooddebuff " or currentEvent == " playerbaddebuff " or currentEvent == " playerdebuffremaining " or currentEvent == " playerdebuffstacks " or currentEvent == " playerbuffremaining " or currentEvent == " playertargets " or currentEvent == " playeraggro " then --Red
infoFrame : SetLine ( linesShown , icon or leftText , rightText , 255 , 0 , 0 , 255 , 255 , 255 )
else -- Green
infoFrame : SetLine ( linesShown , icon or leftText , rightText , 0 , 255 , 0 , 255 , 255 , 255 )
end
else -- It's not player, do nothing special with it. Ordinary class colored text.
if currentEvent == " playerdebuffremaining " or currentEvent == " playerbuffremaining " then
local numberValue = tonumber ( rightText )
if numberValue < 6 then
infoFrame : SetLine ( linesShown , icon or leftText , rightText , color.r , color.g , color.b , 255 , 0 , 0 ) --Red
elseif numberValue < 11 then
infoFrame : SetLine ( linesShown , icon or leftText , rightText , color.r , color.g , color.b , 255 , 127.5 , 0 ) --Orange
else
if numberValue == 9000 then -- Out of range players
infoFrame : SetLine ( linesShown , icon or leftText , SPELL_FAILED_OUT_OF_RANGE , color.r , color.g , color.b , 255 , 0 , 0 ) --Red
else
infoFrame : SetLine ( linesShown , icon or leftText , rightText , color.r , color.g , color.b , 255 , 255 , 255 ) --White
end
end
else
infoFrame : SetLine ( linesShown , icon or leftText , rightText , color.r , color.g , color.b , 255 , 255 , 255 )
end
end
end
end
else
local color2 = NORMAL_FONT_COLOR -- Only custom into frames will have chance of putting player names on right side
local unitId = DBM : GetRaidUnitId ( DBM : GetUnitFullName ( extraName or leftText ) )
local unitId2 = DBM : GetRaidUnitId ( DBM : GetUnitFullName ( rightText ) )
-- Class color names in custom functions too, IF unitID exists
if unitId then -- Check left text
local _ , class = UnitClass ( unitId )
if class then
color = RAID_CLASS_COLORS [ class ]
if DBM.Options . StripServerName then --StripServerName option is checked here, even though it's checked in GetShortServerName function, because we have to apply custom 3rd column hack reconstruction
local shortName = DBM : GetShortServerName ( extraName or leftText )
if extraName then -- 3 column hack is present, we need to reconstruct leftText with shortened name
leftText = extra .. " * " .. shortName
else -- LeftText is name, just replace it with shortname
leftText = shortName
end
end
end
else
color = NORMAL_FONT_COLOR
leftText = extraName or leftText
end
if unitId2 then -- Check right text
local _ , class = UnitClass ( unitId2 )
if class then
color2 = RAID_CLASS_COLORS [ class ]
rightText = DBM : GetShortServerName ( rightText )
end
end
linesShown = linesShown + 1
infoFrame : SetLine ( linesShown , icon or leftText , rightText , color.r , color.g , color.b , color2.r , color2.g , color2.b )
end
end
local maxWidth1 , maxWidth2 , linesPerRow = { } , { } , 5
if linesShown > 5 then
linesPerRow = mmin ( maxLines , mfloor ( linesShown / maxCols + 0.99 ) )
end
local shouldUpdate = prevLines ~= linesShown
for i = 1 , linesShown do
if shouldUpdate then
infoFrame : AlignLine ( i * 2 - 1 , linesPerRow * 2 )
infoFrame : AlignLine ( i * 2 , linesPerRow * 2 )
end
local m = mfloor ( i / linesPerRow + 0.99 )
frame.lines [ i * 2 - 1 ] : SetWidth ( 0 ) -- Hack here, because the string width doesn't calculate properly.
frame.lines [ i * 2 ] : SetWidth ( 0 )
maxWidth1 [ m ] = mmax ( maxWidth1 [ m ] or 0 , frame.lines [ i * 2 - 1 ] : GetStringWidth ( ) )
maxWidth2 [ m ] = mmax ( maxWidth2 [ m ] or 0 , frame.lines [ i * 2 ] : GetStringWidth ( ) )
end
local size = DBM.Options . InfoFrameFontSize
local width = 0
for i , _ in pairs ( maxWidth1 ) do
local maxWid , maxWid2 = maxWidth1 [ i ] , maxWidth2 [ i ]
width = width + maxWid + maxWid2 + size + ( size / 2 )
for ii = 1 , linesPerRow do
local m = ( ( i - 1 ) * linesPerRow * 2 ) + ( ii * 2 )
if not frame.lines [ m ] then
break
end
frame.lines [ m - 1 ] : SetSize ( maxWid , size )
frame.lines [ m ] : SetSize ( maxWid2 , size )
end
end
if width == 0 then
width = 105
end
local height = size
if linesShown > linesPerRow then
height = height + ( linesPerRow * size )
else
height = height + ( mmin ( linesShown , maxLines ) * size )
end
frame : SetSize ( width , height )
frame : Show ( )
prevLines = linesShown
end
---------------
-- Methods --
---------------
--Arg 1: spellName, health/powervalue, customfunction, table type. Arg 2: TankIgnore, Powertype, SortFunction, totalAbsorb, sortmethod (table/stacks). Arg 3: SpellFilter, UseIcon. Arg 4: disable onUpdate. Arg 5: sortmethod (playerpower)
function infoFrame : Show ( modMaxLines , event , ... )
if DBM.Options . DontShowInfoFrame and not ( event or " " ) : find ( " test " ) then
return
end
prevLines = 0
currentMapId = select ( 4 , UnitPosition ( " player " ) )
modLines = modMaxLines
if DBM.Options . InfoFrameLines and DBM.Options . InfoFrameLines ~= 0 then
maxLines = DBM.Options . InfoFrameLines
else
maxLines = modMaxLines or 5
end
maxIcon = DBM.Options . ExtendIcons and 16 or 8 --Updated on show, because we don't want to literally spam DBM.Options table in on update function
if DBM.Options . InfoFrameCols and DBM.Options . InfoFrameCols ~= 0 then
maxCols = DBM.Options . InfoFrameCols
else
-- TODO, still needs more finite control via gui later on
-- I think dynamic options modMaxLines/10 modMaxLines/5 are both valid options, as well as just capping at 2 >= 10
maxCols = modMaxLines and modMaxLines >= 10 and 2 or 1
end
twipe ( value )
for i = 1 , select ( " # " , ... ) do
value [ i ] = select ( i , ... )
end
if not frame then
createFrame ( )
end
-- Orders event to use spellID no matter what and not spell name
if event : find ( " byspellid " ) then
event = event : gsub ( " byspellid " , " " ) -- Strip off the byspellid, it served it's purpose, it simply told infoframe to not convert to spellName
if type ( value [ 1 ] ) ~= " number " then
error ( " DBM-InfoFrame: byspellid method must use spellId " , 2 )
return
end
-- If spellId is given as value one and it's not a byspellid event, convert to spellname
-- This also allows spell name to be given by mod, since value 1 verifies it's a number
elseif type ( value [ 1 ] ) == " number " and event ~= " health " and event ~= " function " and event ~= " table " and event ~= " playertargets " and event ~= " playeraggro " and event ~= " playerpower " and event ~= " enemypower " and event ~= " test " and event ~= " test2 " then
-- Outside of "byspellid" functions, typical frames will still use spell NAME matching not spellID.
-- This just determines if we convert the spell input to a spell Name, if a spellId was provided for a non byspellid infoframe
value [ 1 ] = DBM : GetSpellInfo ( value [ 1 ] )
end
currentEvent = event
if event == " playerbuff " or event == " playerbaddebuff " or event == " playergooddebuff " then
sortMethod = 3 -- Sort by group ID
elseif event == " health " or event == " playerdebuffremaining " then
sortMethod = 2 -- Sort lowest first
elseif ( event == " playerdebuffstacks " or event == " table " ) and value [ 2 ] and type ( value [ 2 ] ) == " number " then
sortMethod = value [ 2 ]
elseif event == " playerpower " and value [ 5 ] and type ( value [ 5 ] ) == " number " then
sortMethod = value [ 5 ]
else
sortMethod = 1 -- Sort highest first
end
if events [ currentEvent ] then
events [ currentEvent ] ( value [ 1 ] )
else
error ( " DBM-InfoFrame: Unsupported event " , 2 )
return
end
if not friendlyEvents [ currentEvent ] then
twipe ( icons )
end
frame : Show ( )
onUpdate ( frame , value [ 1 ] )
if not frame.ticker and not value [ 4 ] and event ~= " table " then
frame.ticker = C_Timer.NewTicker ( 0.5 , function ( )
onUpdate ( frame )
end )
elseif frame.ticker and value [ 4 ] then -- Redundancy, in event calling a non onupdate infoframe show without a hide event to unschedule ticker based infoframe
frame.ticker : Cancel ( )
frame.ticker = nil
end
end
function infoFrame : RegisterCallback ( cb )
updateCallbacks [ # updateCallbacks + 1 ] = cb
end
function infoFrame : Update ( time )
if not frame then
createFrame ( )
end
if frame : IsShown ( ) then
if time then
DBM : Unschedule ( onUpdate )
DBM : Schedule ( time , onUpdate , frame )
else
onUpdate ( frame )
end
end
end
function infoFrame : UpdateTable ( table , time )
if not frame then
createFrame ( )
end
if frame : IsShown ( ) and table then
if time then
DBM : Unschedule ( onUpdate )
DBM : Schedule ( time , onUpdate , frame , table )
else
onUpdate ( frame , table )
end
end
end
function infoFrame : SetHeader ( text )
if not frame then
createFrame ( )
end
frame.header : SetText ( text or " DBM Info Frame " )
end
function infoFrame : ClearLines ( )
if not frame then
createFrame ( )
end
for i = 1 , # frame.lines do
frame.lines [ i ] : SetText ( " " )
frame.lines [ i ] : Hide ( )
end
end
function infoFrame : AlignLine ( lineNum , linesPerRow )
local size = DBM.Options . InfoFrameFontSize
local line = frame.lines [ lineNum ]
line : SetJustifyH ( lineNum % 2 == 0 and " RIGHT " or " LEFT " )
if lineNum == 1 then -- 1st entry left
line : SetPoint ( " TOPLEFT " , frame , " TOPLEFT " , size / 2 , - ( size / 2 ) )
elseif lineNum == 2 then -- 1st entry right
line : SetPoint ( " TOPLEFT " , frame.lines [ 1 ] , " TOPRIGHT " , size / 2 , 0 )
else
if lineNum % linesPerRow == 1 then -- Column 2-x, 1st entry left
line : SetPoint ( " TOPLEFT " , frame.lines [ lineNum - linesPerRow + 1 ] , " TOPRIGHT " , size , 0 )
elseif lineNum % 2 == 0 then -- Column 2-x, Right entry
line : SetPoint ( " TOPLEFT " , frame.lines [ lineNum - 1 ] , " TOPRIGHT " , size / 2 , 0 )
else -- Column 2-x, Left entry
line : SetPoint ( " TOPLEFT " , frame.lines [ lineNum - 2 ] , " LEFT " , 0 , - ( size / 2 ) )
end
end
end
function infoFrame : UpdateStyle ( )
if not frame then
createFrame ( )
end
prevLines = 0
local font = DBM.Options . InfoFrameFont == " standardFont " and standardFont or DBM.Options . InfoFrameFont
local size = DBM.Options . InfoFrameFontSize
local style = DBM.Options . InfoFrameFontStyle == " none " and nil or DBM.Options . InfoFrameFontStyle
for i = 1 , # frame.lines do
frame.lines [ i ] : SetFont ( font , size , style )
end
end
function infoFrame : SetLine ( lineNum , leftText , rightText , colorR , colorG , colorB , color2R , color2G , color2B )
if not frame then
createFrame ( )
end
lineNum = lineNum * 2 - 1
if not frame.lines [ lineNum ] then
local font = DBM.Options . InfoFrameFont == " standardFont " and standardFont or DBM.Options . InfoFrameFont
local size = DBM.Options . InfoFrameFontSize
local style = DBM.Options . InfoFrameFontStyle == " none " and nil or DBM.Options . InfoFrameFontStyle
frame.lines [ lineNum ] = frame : CreateFontString ( " Line " .. lineNum , " OVERLAY " , " GameFontNormal " )
frame.lines [ lineNum ] : SetFont ( font , size , style )
frame.lines [ lineNum + 1 ] = frame : CreateFontString ( " Line " .. lineNum + 1 , " OVERLAY " , " GameFontNormal " )
frame.lines [ lineNum + 1 ] : SetFont ( font , size , style )
frame.lines [ lineNum + 1 ] : SetJustifyH ( " RIGHT " )
end
frame.lines [ lineNum ] : SetText ( leftText )
frame.lines [ lineNum ] : SetTextColor ( colorR or 255 , colorG or 255 , colorB or 255 )
frame.lines [ lineNum ] : Show ( )
frame.lines [ lineNum + 1 ] : SetText ( rightText )
frame.lines [ lineNum + 1 ] : SetTextColor ( color2R or 255 , color2G or 255 , color2B or 255 )
frame.lines [ lineNum + 1 ] : Show ( )
end
function infoFrame : Hide ( )
twipe ( lines )
twipe ( icons )
twipe ( sortedLines )
twipe ( updateCallbacks )
infoFrame : SetHeader ( )
twipe ( value )
if frame then
if frame.ticker then
frame.ticker : Cancel ( )
frame.ticker = nil
end
frame : Hide ( )
end
currentEvent = nil
sortMethod = 1
end
function infoFrame : SetLines ( lines )
modLines = lines
if DBM.Options . InfoFrameLines == 0 then
maxLines = lines
end
end
function infoFrame : SetColumns ( columns )
modCols = columns
if DBM.Options . InfoFrameCols == 0 then
maxCols = columns
end
end
function infoFrame : IsShown ( )
return frame and frame : IsShown ( )
end
function infoFrame : SetSortingAsc ( )
sortMethod = 2
end
function infoFrame : SetSortingGroupId ( )
sortMethod = 3
end