WoWInterface SVN fernir_UI

[/] [unitframes.lua] - Rev 2

Compare with Previous | Blame | View Log

--[[-------------------------------------------------------------------------
  Trond A Ekseth grants anyone the right to use this work for any purpose,
  without any conditions, unless such conditions are required by law.
  ALZA uses this right to conquer the whole world!
---------------------------------------------------------------------------]]

--[[     Options start here     ]]
local settings = oUF_Settings
--[[        Options end         ]]

--[[ Font creation func ]]
-- arguments: parent (parent frame of fontstring), justify (horisontal justification, optional)
-- returns: FontString
local createFs = function(parent, justify, ownfsize)
    local f = parent:CreateFontString(nil, "OVERLAY")
    f:SetFont(settings.font, ownfsize or settings.fsize, "THINOUTLINE")
    if(justify) then f:SetJustifyH(justify) end
    return f
end

local function SecondsToTimeAbbrev(time)
    local hr, m, s, text
    if time <= 0 then text = ""
    elseif(time < 3600 and time > 60) then
      hr = floor(time / 3600)
      m = floor(mod(time, 3600) / 60 + 1)
      s = mod(time, 60)
      text = format("%dм %dс", m, s)
    elseif time < 60 then
      m = floor(time / 60)
      s = mod(time, 60)
      text = (m == 0 and format("%dс", s))
    else
      hr = floor(time / 3600 + 1)
      text = format("%dч", hr)
    end
    return text
end

--[[ Right click menu ]]
local menu = function(self)
        local unit = self.unit:sub(1, -2)
        local cunit = self.unit:gsub("(.)", string.upper, 1)

        if(unit=="party" or unit=="partypet") then
                ToggleDropDownMenu(1, nil, _G["PartyMemberFrame"..self.id.."DropDown"], "cursor")
        elseif(_G[cunit.."FrameDropDown"]) then
                ToggleDropDownMenu(1, nil, _G[cunit.."FrameDropDown"], "cursor")
        end
end

--[[ Short numbarz! ]]
local format = string.format

local siValue = function(val)
    if val >= 10000000 then 
        return format("%.1fm", val / 1000000) 
    elseif val >= 1000000 then
        return format("%.2fm", val / 1000000) 
    elseif val >= 100000 then
        return format("%.0fk", val / 1000) 
    elseif val >= 10000 then
        return format("%.1fk", val / 1000) 
    else
        return val
    end
end

--[[ Health update ]]
local ColorGradient = oUF.ColorGradient -- we need it for hp and druid power coloring
local unpack = unpack

local OverrideUpdateHealth = function(self, event, unit, bar, min, max) -- this func replaces standart health update func
    local r, g, b = 1, 1, 1

    if(max~=0) then
        r, g, b = ColorGradient(min/max, 1, 0, 0, 1, 1, 0, 0, 1, 0) -- we color percent hp by color gradient from green to red
    end

    if(not UnitIsConnected(unit)) then
        bar:SetValue(0)
        bar.value:SetText("Off")
    elseif(UnitIsDead(unit)) then
        bar:SetValue(0)
        bar.value:SetText("Dead")
    elseif(UnitIsGhost(unit)) then
        bar:SetValue(0)
        bar.value:SetText("Ghost")
    else
        if(unit=="player") then
            bar.value:SetFormattedText("|cff%02x%02x%02x%s|r %s", r*255, g*255, b*255, siValue(min), siValue(max))    -- text for player: "curhp percenthp"
        elseif(unit=="pet") then
            bar.value:SetFormattedText("%s", siValue(min))  -- text for pet: "shortcurhp"
        elseif(unit=="target") then
            bar.value:SetFormattedText("%s |cff%02x%02x%02x%.1f|r", siValue(min), r*255, g*255, b*255, (min/max)*100)   -- text for target: "shortcurhp percenthp"
        else
            bar.value:SetText() -- no hp text for others. Feel free to add other units. Info about SetFormattedText can be found on wowwiki.com
        end
    end

    if(settings.ClassColor==true) then   -- determine what color to use
        if(UnitIsPlayer(unit)) then
            local _, englass = UnitClass(unit)
            if(self.colors.class[englass]) then
                r, g, b = unpack(self.colors.class[englass])
            end
        else
            r, g, b = UnitSelectionColor(unit)
        end
    else
        r, g, b = unpack(OwnColor)
    end
    
    if(UnitIsTapped(unit) and not UnitIsTappedByPlayer(unit)) then  -- grey color for tapped mobs
        r, g, b = .6, .6, .6
    end

    if(unit=="pet" and GetPetHappiness()) then  -- petframe is colored by happiness
        r, g, b = unpack(self.colors.happiness[GetPetHappiness()])
    end

    bar:SetStatusBarColor(r, g, b)          -- hp bar coloring
    bar.bg:SetVertexColor(r, g, b, .2)      -- hp background - same color but 20% opacity
    if(self.Castbar) then                   -- same with castbar
        self.Castbar:SetStatusBarColor(r, g, b)
        self.Castbar.bg:SetVertexColor(r, g, b, .2)
    end
    
    if settings.Portraits then
        self.Portrait:SetAlpha(.1)
    end
end

local PostUpdatePower = function(self, event, unit, bar, min, max)
    if(not UnitIsConnected(unit) or min==0) then    -- no unit - no mana!
        bar.value:SetText()
    elseif(UnitIsDead(unit) or UnitIsGhost(unit)) then  -- dead unit - no mana!
        bar:SetValue(0)
        bar.value:SetText()
    elseif(unit=="player" or unit=="target" or unit=="pet") then
        bar.value:SetFormattedText("%s", siValue(min))  -- text for player, pet, target: "shortcurrentmana"
    else
        bar.value:SetText() -- no text for other units
    end

    local r, g, b = 1, 1, 1 -- manabar coloring
    if(settings.PowerColorByType==true) then
        local _, ptype = UnitPowerType(unit)
        if(settings.powercolors[ptype]) then
            r, g, b = unpack(settings.powercolors[ptype])
        end
    else
        r, g, b = unpack(settings.OwnPowerColor)
    end

    bar:SetStatusBarColor(r, g, b)
    bar.value:SetTextColor(r, g, b)     -- power text colored with same color as power bar
    bar.bg:SetVertexColor(r, g, b, .2)
end

--[[ Druid power update. Credits to p3lim for code and idea ]]
oUF.TagEvents["[druidpower]"] = "UNIT_MANA UPDATE_SHAPESHIFT_FORM"
oUF.Tags["[druidpower]"] = function(unit) -- druid power text: "shortcurrentmana percentmana"
    local min, max = UnitPower(unit, 0), UnitPowerMax(unit, 0)
    local r, g, b = 0, 0, 1
    if(max~=0) then
        r, g, b = ColorGradient(min/max, 1, 0, 0, 1, 1, 0, 0, 1, 0) -- gradient for percent mp
    end
    return UnitPowerType(unit)~=0 and format("|cff0090ff%d |cff%02x%02x%02x%.1f|r", min, r*255, g*255, b*255, (min/max)*100)
end

--[[ Castbar time styling ]]
local CustomTimeText = function(self, duration)
    self.Time:SetFormattedText("%.1f", duration)   -- text for casts: "elapsed / casttime"
    --self.Time:SetFormattedText("%.1f / %.1f", duration, self.max)   -- text for casts: "elapsed / casttime"
end

--[[ Disabling default buff frames ]]
local _G = getfenv(0) -- speed up getting globals
--[[local buff = _G["BuffFrame"]
buff:Hide()
buff:UnregisterAllEvents()
buff:SetScript("OnUpdate", nil)]]

--[[ Aura settings ]]
local noHide = function(self)   -- we don't want aura border to hide on buffs
    self:SetVertexColor(0, 0, 0)
end

local CancelBuff = function(self, button) -- cancel buffs on right click
    if(button=="RightButton") then
        CancelUnitBuff("player", self:GetID())
    end
end

local PostCreateAuraIcon = function(self, button, icons, index, isDebuff)
    button.cd:SetReverse()
    
    button.count:ClearAllPoints()
    button.count:SetPoint("TOPLEFT")    -- Stacks text will be on top of icon
    button.count:SetFont(settings.font, settings.fsize, "THINOUTLINE")
    button.count:SetTextColor(.8, .8, .8)   -- Color for stacks text

    button.icon:SetTexCoord(0, 1, 0, 1)

    button.overlay:SetTexture(settings.buffTex)
    button.overlay:SetTexCoord(0, 1, 0, 1)   
    button.overlay.Hide = noHide
    
    if(not isDebuff and self.unit=="player") then     -- Cancel buffs on right click
        button:SetScript("OnMouseUp", CancelBuff)
    end
end

local MyUnits = { -- true to show cooldown for debuffs from that units, false to hide
    player = true,
    pet = true,
    vehicle = true
}

local PostUpdateAuraIcon = function(self, icons, unit, icon, index, offset, filter, isDebuff)
    if(icon.cd:IsShown() and self.unit=="target" and isDebuff and not MyUnits[icon.owner]) then
        icon.cd:Hide()
    end
end

local _, class = UnitClass("player")

--[[ Let's start! ]]
local func = function(self, unit)
    self.menu = menu
    self:SetScript("OnEnter", OnEnter)
    self:SetScript("OnLeave", OnLeave)
    self:RegisterForClicks("anyup")
    self:SetAttribute("*type2", "menu")
    self.disallowVehicleSwap = true
    
    local s = settings.Frames[unit]  -- Getting settings for every unit

    --[[ Frame sizes ]]
    self:SetAttribute("initial-width", s.Width)
    self:SetAttribute("initial-height", s.Height)
    
    self.FrameBackdrop = CreateFrame("Frame", nil, self)
    self.FrameBackdrop:SetPoint("TOPLEFT", self, "TOPLEFT", -4 , 4)
    self.FrameBackdrop:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", 4 , -4)
    self.FrameBackdrop:SetFrameStrata("BACKGROUND")
    self.FrameBackdrop:SetBackdrop {
        edgeFile = glowTex, edgeSize = 4,
        tile = true, tileSize = 16,
        insets = {left = 6, right = 6, top = 6, bottom = 6}
    }
    self.FrameBackdrop:SetBackdropColor(0, 0, 0, 0)
    self.FrameBackdrop:SetBackdropBorderColor(0, 0, 0)

    --[[ Healthbar ]]
    local hp = CreateFrame("StatusBar", nil, self)
    hp:SetStatusBarTexture(settings.texture)
    hp.frequentUpdates = true
    hp:SetPoint("TOPRIGHT")
    hp:SetPoint("TOPLEFT")
    hp:SetHeight(s.ManaBarHeight==0 and s.Height or (s.Height - s.ManaBarHeight - 1))

    local hpbg = hp:CreateTexture(nil, "BACKGROUND")
    hpbg:SetTexture(settings.texture)
    hpbg:SetAllPoints(hp)

    local hpp = createFs(hp)
    hpp:SetPoint("RIGHT", hp, "RIGHT", -5, 0)   -- health text for player - on right side
    
    hp.bg = hpbg
    hp.value = hpp
    self.Health = hp
    self.OverrideUpdateHealth = OverrideUpdateHealth

    --[[ Manabar ]]
    local pp = CreateFrame("StatusBar", nil, self)
    pp:SetStatusBarTexture(settings.texture)
    pp.frequentUpdates = true
    pp:SetPoint("BOTTOMLEFT")
    pp:SetPoint("BOTTOMRIGHT")
    pp:SetHeight(s.ManaBarHeight)

    local ppbg = pp:CreateTexture(nil, "BACKGROUND")
    ppbg:SetTexture(settings.texture)
    ppbg:SetAllPoints(pp)

    local ppp = createFs(pp)
    ppp:SetPoint("RIGHT", pp, "RIGHT", -2, 0)
   
    pp.bg = ppbg
    pp.value = ppp
    self.Power = pp
    self.PostUpdatePower = PostUpdatePower
    self.PostUpdateAuraIcon = PostUpdateAuraIcon
    
    --[[ Info text ]]
    local info = createFs(self)
    if(unit=="player") then
        info:SetPoint("BOTTOMLEFT", self, "TOPLEFT", 0, 3)
        self:Tag(info, "[name]")    -- look into \Interface\AddOns\oUF\elements\tags.lua for more tags
    elseif(unit=="target") then
        info:SetPoint("BOTTOMLEFT", self, "TOPLEFT", 0, 3)
        self:Tag(info, "[difficulty][smartlevel]|r [name]")    -- look into \Interface\AddOns\oUF\elements\tags.lua for more tags
    elseif(unit=="targettarget" or unit=="focus" or unit=="focustarget") then
        info:SetPoint("BOTTOM", self, "TOP", 0, 3)
        self:Tag(info, "[name]")
    elseif(not unit) then
        info:SetParent(self.Health)
        info:SetJustifyH("CENTER")
        self:Tag(info, "[name]")
    end

    --[[ Global bg, 2 px border ]]
    local allbg = self:CreateTexture(nil, "BORDER")
    allbg:SetPoint("BOTTOMRIGHT", 1, -1)
    allbg:SetPoint("TOPLEFT", -1, 1)
    allbg:SetTexture(0, 0, 0)   -- we want it black

    --[[ Castbar ]]
    if(unit=="player" or unit=="target" or unit=="pet" or unit=="focus") then
        local _, class = UnitClass(unit)
        local space = 0
        if  class == "DEATHKNIGHT" or class=="SHAMAN" then
            space = 12
        end
        
        local cb = CreateFrame("StatusBar", nil, self)
        cb:SetStatusBarTexture(settings.texture)
        cb:SetPoint("BOTTOMLEFT", self, "BOTTOMLEFT", 0, -30-space)
        cb:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", 0, -30-space)
        cb:SetHeight(s.ManaBarHeight==0 and s.Height or (s.Height / 2)) -- Castbar will be as big as healthbar
        
        local cbblackbg = cb:CreateTexture(nil, "BACKGROUND")   -- that's the black thingie like global background
        cbblackbg:SetPoint("TOPLEFT", -1, 1)
        cbblackbg:SetPoint("BOTTOMRIGHT", 1, -1)
        cbblackbg:SetTexture(0, 0, 0)

        local cbbg = cb:CreateTexture(nil, "BORDER")
        cbbg:SetTexture(settings.texture)
        cbbg:SetAllPoints(cb)

        local time = createFs(cb, "RIGHT", 12)
        time:SetPoint("RIGHT", cb, "RIGHT", -4, 0)

        local text = createFs(cb, "LEFT", 12)
        text:SetPoint("LEFT", cb, "LEFT", cb:GetHeight() + 4, 0)
        text:SetPoint("RIGHT", time, "LEFT")

        local spark = cb:CreateTexture(nil, "OVERLAY")
        spark:SetVertexColor(1, 1, 1)
        spark:SetBlendMode("ADD")
        spark:SetHeight(cb:GetHeight()*2.5)
        spark:SetWidth(20)
        
        cbicon = cb:CreateTexture(nil, "OVERLAY")
        cbicon:SetTexCoord(.1,.9,.1,.9)
        cbicon:SetWidth(cb:GetHeight())
        cbicon:SetHeight(cb:GetHeight())
        cbicon:SetPoint("LEFT")

        cb.bg = cbbg
        cb.Time = time
        cb.Text = text
        cb.Spark = spark
        cb.CustomTimeText = CustomTimeText
        cb.Icon = cbicon
        self.Castbar = cb
    end
    
    
    if unit=="player" then
        local _, class = UnitClass(unit)
        
        if  class == "DEATHKNIGHT" then
            self.Runes = CreateFrame('Frame', nil, self)
            self.Runes:SetPoint('TOPLEFT', self, 'BOTTOMLEFT', 0, -1)
            self.Runes:SetHeight(10)
            self.Runes:SetWidth(s.Width)
            self.Runes.anchor = "TOPLEFT"
            self.Runes.growth = "RIGHT"
            self.Runes.height = 10
            self.Runes.width = s.Width / 6 - 0.85
            self.Runes.spacing = 1


            for i = 1, 6 do
                self.Runes[i] = CreateFrame("StatusBar", "oUFRune"..i, self.Runes)
                self.Runes[i]:SetStatusBarTexture(settings.texture)
                self.Runes[i]:SetStatusBarColor(unpack(settings.runecolors[i]))
                self.Runes[i].bg = self.Runes[i]:CreateTexture(nil, "BACKGROUND")   -- that's the black thingie like global background
                self.Runes[i].bg:SetPoint("TOPLEFT", -1, 1)
                self.Runes[i].bg:SetPoint("BOTTOMRIGHT", 1, -1)
                self.Runes[i].bg:SetTexture(0, 0, 0)
            end     
         end
    end

    if settings.Portraits then
        self.Portrait = CreateFrame("PlayerModel", nil, self)
        self.Portrait:SetAllPoints(self.Health)
        self.Portrait:SetAlpha(.1)
    end
    
    
    if(unit=="player") then
    
        -- [[ Temporary enchants icons ]] --
        local ench = {}
        
        for i = 1,2 do
            ench[i] = _G["TempEnchant"..i]
             _G["TempEnchant"..i.."Border"]:Hide()
            
            ench[i]:ClearAllPoints()
            
            if (i==1) then
                ench[i]:SetPoint("TOPRIGHT", self, "TOPLEFT", -3, 1)
            else
                ench[i]:SetPoint("RIGHT", ench[i-1], "LEFT", -2, 0)
            end
            
            ench[i]:SetWidth(32)
            ench[i]:SetHeight(32)
            ench[i]:Show()
            
            ench[i].t = ench[i]:CreateTexture(nil,"BORDER")
            ench[i].t:SetTexture(settings.buffTex)
            ench[i].t:SetVertexColor(0.7, 0, 0.7)
            ench[i].t:SetAllPoints(ench[i])

            ench[i].dur = _G["TempEnchant"..i.."Duration"]
            ench[i].dur:ClearAllPoints()
            ench[i].dur:SetAllPoints(ench[i])
            ench[i].dur:SetFont(settings.font, 11, "THINOUTLINE")
            ench[i].dur:SetVertexColor(1, 1, 1)
            ench[i].dur.SetVertexColor = function() end
        end
         
        -- Hide old buffs
        _G["BuffFrame"]:Hide()
        _G["BuffFrame"]:UnregisterAllEvents()
        _G["BuffFrame"]:SetScript("OnUpdate", nil)
    
        local buffs = CreateFrame("Frame", nill, self)
        buffs:SetPoint("TOPRIGHT", Minimap, "TOPLEFT", -25, 0)
        buffs.initialAnchor = "TOPRIGHT"
        buffs["growth-y"] = "DOWN"
        buffs["growth-x"] = "LEFT"
        buffs:SetHeight(500)
        buffs:SetWidth(220)
        buffs.spacing = 4
        buffs.size = 30
        self.Buffs = buffs

        local debuffs = CreateFrame("Frame", nill, self)
        debuffs:SetPoint("TOPRIGHT", Minimap, "BOTTOMRIGHT", 0, -35)
        debuffs.initialAnchor = "TOPRIGHT"
        debuffs["growth-x"] = "LEFT"
        debuffs["growth-y"] = "DOWN"
        debuffs:SetHeight(500)
        debuffs:SetWidth(220)
        debuffs.spacing = 4
        debuffs.size = 45
        self.Debuffs = debuffs
    end
    
    if(unit=="target") then     -- For target we make one frame. Buffs first, then debuffs
        local auras = CreateFrame("Frame", nill, self)
        auras:SetPoint("BOTTOMLEFT", self, "TOPLEFT", -2, 20)
        auras.initialAnchor = "BOTTOMLEFT"
        auras["growth-x"] = "RIGHT"
        auras["growth-y"] = "UP"
        auras.numDebuffs = 16   -- Max amount of debuffs to show
        auras:SetHeight(373)
        auras:SetWidth(s.Width)
        auras.spacing = 1
        auras.size = 28
        auras.gap = false        -- A gap between buffs and debuffs
        
        self.Auras = auras
    end

    if(unit=="focus" or unit=="targettarget") then
        local debuffs = CreateFrame("Frame", nill, self)    -- Debuffs for focus
        debuffs:SetPoint("TOPLEFT", self, "BOTTOMLEFT", -2, -3)
        debuffs.initialAnchor = "TOPLEFT"
        debuffs["growth-x"] = "RIGHT"
        debuffs["growth-y"] = "DOWN"
        debuffs:SetHeight(20)
        debuffs:SetWidth(104)
        debuffs.spacing = 1
        debuffs.size = 20

        self.Debuffs = debuffs
    end
    
    
    local sentTime = 0
    local lagTime = 0

    local UNIT_SPELLCAST_SENT = function (self, event, unit, spell, spellrank)
        if(self.unit~=unit) then return end
        sentTime = GetTime()
    end

    local PostCastStart = function(self, event, unit, name, rank, text, castid)
        lagTime = GetTime() - sentTime
    end

    local PostChannelStart = function(self, event, unit, name, rank, text)
        lagTime = GetTime() - sentTime
    end

    local OnCastbarUpdate = function(self, elapsed)
        if(self.casting) then
            local duration = self.duration + elapsed
            if(duration>=self.max) then
                self.casting = nil
                self:Hide()
                return
            end

            local width = self:GetWidth()
            local safeZonePercent = lagTime / self.max
            if(safeZonePercent>1) then safeZonePercent=1 end
            self.SafeZone:SetWidth(width * safeZonePercent)

            if(self.delay~=0) then
                self.Time:SetFormattedText("%.1f|cffff0000-%.1f|r", duration, self.delay)
            else
                self.Time:SetFormattedText("%.1f / %.1f", duration, self.max)
                self.Lag:SetFormattedText("%d ms", lagTime * 1000)
            end

            self.duration = duration
            self:SetValue(duration)

            self.Spark:SetPoint("CENTER", self, "LEFT", (duration / self.max) * self:GetWidth(), 0)

        elseif(self.channeling) then
            local duration = self.duration - elapsed

            if(duration<=0) then
                self.channeling = nil
                self:Hide()
                return
            end

            if(lagTime > 1e5) then
                lagTime = 0
                self.SafeZone:SetWidth(0)
            else
                local width = self:GetWidth()
                local safeZonePercent = lagTime / self.max
                if(safeZonePercent > 1 or safeZonePercent<=0) then safeZonePercent = 1 end
                self.SafeZone:SetWidth(width * safeZonePercent)
            end

            if(self.delay~=0) then
                self.Time:SetFormattedText("%.1f|cffff0000-%.1f|r", duration, self.delay)
            else
                self.Time:SetFormattedText("%.1f / %.1f", duration, self.max)
                self.Lag:SetFormattedText( "%d ms ", lagTime * 1000 )
            end

            self.duration = duration
            self:SetValue(duration)

            self.Spark:SetPoint("CENTER", self, "LEFT", (duration / self.max) * self:GetWidth(), 0)
        else
            self.unitName = nil
            self.channeling = nil
            self:SetValue(1)
            self:Hide()
        end
    end

    if(unit=="player") then
        local sz = self.Castbar:CreateTexture(nil, "ARTWORK")
        sz:SetTexture(settings.texture)
        sz:SetVertexColor(1, 0.3, 0.3)
        sz:SetPoint("BOTTOMRIGHT")
        sz:SetPoint("TOPRIGHT")
        self.Castbar.SafeZone = sz

        local lag = createFs(self.Castbar)
        lag:SetFont(settings.font, 10, "THINOUTLINE")
        lag:SetPoint("LEFT", self.Castbar, "RIGHT", -2, 0)
        lag:SetJustifyH("RIGHT")
        self.Castbar.Lag = lag 

        self.PostCastStart = PostCastStart
        self.OnCastbarUpdate = OnCastbarUpdate
        self.PostChannelStart = PostChannelStart
        self:RegisterEvent("UNIT_SPELLCAST_SENT", UNIT_SPELLCAST_SENT)
    end
    
    self.PostCreateAuraIcon = PostCreateAuraIcon
    
    --[[ Druid mana ]]
    if(unit=="player" and class=="DRUID") then
        local druid = createFs(self)
        druid:SetPoint("BOTTOMRIGHT", self, "TOPRIGHT", -2, 3)

        self:Tag(druid, "[druidpower]")
        self.DruidPower = druid
    end

    --[[ Raid Target Icon ]]
    if(unit=="player" or unit=="target") then
        local ricon = self.Health:CreateTexture(nil, "OVERLAY")
        ricon:SetHeight(16)
        ricon:SetWidth(16)
        ricon:SetPoint("CENTER")

        self.RaidIcon = ricon
    end

    --[[ Resting icon ]]
    if(unit=="player") then
        local rest = self.Health:CreateTexture(nil, "OVERLAY")
        rest:SetHeight(20)
        rest:SetWidth(20)
        rest:SetPoint("LEFT")

        self.Resting = rest
    end

    --[[ Combat icon ]]
    if(unit=="player") then
        local combat = self.Health:CreateTexture(nil, "OVERLAY")
        combat:SetHeight(18)
        combat:SetWidth(18)
        combat:SetPoint("LEFT")

        self.Combat = combat
    end

    --[[ Leader icon ]]
    if(not unit) then   -- only for party frames
        local leader = self:CreateTexture(nil, "OVERLAY")
        leader:SetHeight(16)
        leader:SetWidth(16)
        leader:SetPoint("RIGHT", hp, "LEFT", -2, 0)

        self.Leader = leader
    end

    --[[ Combo Points ]]
    if(unit=="target") then -- this is for Malygos. Text will be shown on right of target healthbar
        local UpdateCPoints = function(self, event, unit)
           if unit == PlayerFrame.unit and unit ~= self.CPoints.unit then
              self.CPoints.unit = unit
           end
        end
    
        self.cpFrame = self.cpFrame or CreateFrame("Frame", nil, self)
        self.cpFrame:SetPoint("TOPLEFT",self,"BOTTOMLEFT",0,0)
        self.cpFrame:SetPoint("BOTTOMRIGHT",self,"BOTTOMRIGHT",0,-12)
        self.cpFrame:CreateTexture(nil):SetTexture(0,0,0)
        self.cpFrame:Show()
        self.CPoints = {}
        self.CPoints.unit = PlayerFrame.unit
        for i = 1, 5 do
                                self.CPoints[i] = self.cpFrame:CreateTexture(nil, "OVERLAY")
                                self.CPoints[i]:SetHeight(12)
                                self.CPoints[i]:SetWidth(12)
                                self.CPoints[i]:SetTexture(settings.indicator)
                                if i == 1 then
                                        self.CPoints[i]:SetPoint("LEFT")
                                        self.CPoints[i]:SetVertexColor(0.69, 0.31, 0.31)
                                else
                                        self.CPoints[i]:SetPoint("LEFT", self.CPoints[i-1], "RIGHT", 2, 0)
                                end
                        end
                        self.CPoints[2]:SetVertexColor(0.69, 0.31, 0.31)
                        self.CPoints[3]:SetVertexColor(0.65, 0.63, 0.35)
                        self.CPoints[4]:SetVertexColor(0.65, 0.63, 0.35)
                        self.CPoints[5]:SetVertexColor(0.33, 0.59, 0.33)
                        self:RegisterEvent("UNIT_COMBO_POINTS", UpdateCPoints)
    end
    
    --[[ Totems ]]--
    local _, pClass = UnitClass("player")

    if unit=="player" and pClass == "SHAMAN" then
        local GetTotemInfo, SetValue, GetTime = GetTotemInfo, SetValue, GetTime
        
        local Abbrev = function(name)   
           return (string.len(name) > 10) and string.gsub(name, "%s*(.)%S*%s*", "%1. ") or name
        end
        
        self.TotemBar = {}
        self.TotemBar.colors = {
           [1] = {0.752,0.172,0.02},
           [2] = {0.741,0.580,0.04},            
           [3] = {0,0.443,0.631},
           [4] = {0.6,1,0.945}, 
        }
        
        local total = 0
        local delay = 1
        
        self.TotemBarFrame = CreateFrame("frame", "oUF_TotemBarFrame",self)
        self.TotemBarFrame:SetPoint("TOPLEFT", self, "BOTTOMLEFT", -1, 0)
        self.TotemBarFrame:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", 1, -settings.Frames.player.ManaBarHeight+1)
        local tfbg = self.TotemBarFrame:CreateTexture(nil, "BACKGROUND")
        tfbg:SetAllPoints(self.TotemBarFrame)
        tfbg:SetTexture(settings.texture)
        tfbg:SetVertexColor(0,0,0)
        self.TotemBarFrame:Show()
            
        for i = 1, 4 do
            self.TotemBar[i] = CreateFrame("StatusBar", self:GetName().."_TotemBar"..i, self)
            self.TotemBar[i]:SetHeight(settings.Frames.player.ManaBarHeight-3)
            self.TotemBar[i]:SetWidth(s.Width/4-1)
            if (i==1) then
               self.TotemBar[i]:SetPoint("TOPLEFT", self, "BOTTOMLEFT", 0, -1)
            else
               self.TotemBar[i]:SetPoint("LEFT", self.TotemBar[i-1], "RIGHT", 1, 0)
            end
            self.TotemBar[i]:SetStatusBarTexture(settings.texture)
            self.TotemBar[i]:SetMinMaxValues(0, 1)

            self.TotemBar[i].bg = self.TotemBar[i]:CreateTexture(nil, "BORDER")
            self.TotemBar[i].bg:SetAllPoints(self.TotemBar[i])
            self.TotemBar[i].bg:SetTexture(settings.texture)
            self.TotemBar[i].bg:SetVertexColor(.2,.2,.2)
            
            self.TotemBar[i].fs = createFs(self.TotemBar[i], nil, 8)
            self.TotemBar[i].fs:SetAllPoints(self.TotemBar[i])
            
            self.TotemBar[i]:Hide()
        end
        
        local function TotemOnClick(self,...)
           local id = self.ID
           local mouse = ...
              if IsShiftKeyDown() then
                 for j = 1,4 do 
                   DestroyTotem(j)
                 end 
              else 
                 DestroyTotem(id)
              end
        end
        self.TotemBar.Destroy = true

        local function InitDestroy(self)
           local totem = self.TotemBar
           for i = 1 , 4 do
              local Destroy = CreateFrame("Button",nil, totem[i])
              Destroy:SetAllPoints(totem[i])
              Destroy:RegisterForClicks("LeftButtonUp", "RightButtonUp")
              Destroy.ID = i
              Destroy:SetScript("OnClick", TotemOnClick)
           end
        end

        local function UpdateSlot(self, slot)
           local totem = self.TotemBar
           self.TotemBar[slot]:Show()
           if(totem) then
              if totem.Destroy then
                 InitDestroy(self)
              end
           end
   
           haveTotem, name, startTime, duration, totemIcon = GetTotemInfo(slot)
           
           totem[slot]:SetStatusBarColor(unpack(totem.colors[slot]))
           totem[slot]:SetValue(0)
           
           totem[slot].ID = slot
           
           -- If we have a totem then set his value 
           if(haveTotem) then
              if totem[slot].Name then
                 totem[slot].Name:SetText(Abbrev(name))
              end
              if(duration >= 0) then
                 totem[slot]:SetValue(1 - ((GetTime() - startTime) / duration))
                 -- Status bar update
                 totem[slot]:SetScript("OnUpdate",function(self,elapsed)
                       total = total + elapsed
                       if total >= delay then
                          total = 0
                          haveTotem, name, startTime, duration, totemIcon = GetTotemInfo(self.ID)
                             if ((GetTime() - startTime) == 0) then
                                self:SetValue(0)
                                self.fs:SetText("")
                             else
                                self:SetValue(1 - ((GetTime() - startTime) / duration))
                                self.fs:SetText(SecondsToTimeAbbrev(floor(duration - (GetTime() - startTime))))
                             end
                       end
                    end)
              else
                 -- There's no need to update because it doesn't have any duration
                 totem[slot]:SetScript("OnUpdate",nil)
                 totem[slot]:SetValue(0)
                 totem[slot]:Hide()
              end 
           else
              -- No totem = no time 
              if totem[slot].Name then
                 totem[slot].Name:SetText(" ")
              end
              totem[slot]:SetValue(0)
              totem[slot]:Hide()
           end

        end
        
        local function Event(self,event,...)
           if event == "PLAYER_TOTEM_UPDATE" then
              UpdateSlot(self, ...)
           end
        end
        
        self:RegisterEvent("PLAYER_TOTEM_UPDATE", Event)
    end


    --[[ Fading for party ]]
    if(not unit) then
        self.Range = true 
        self.inRangeAlpha = 1.0 
        self.outsideRangeAlpha = 0.5
    end

    return self
end

oUF:RegisterStyle("style", func)
oUF:SetActiveStyle("style")

--[[ Positions ]]
oUF:Spawn("player", "oUF_player"):SetPoint(unpack(settings.Positions.player))
oUF:Spawn("target", "oUF_target"):SetPoint(unpack(settings.Positions.target))
oUF:Spawn("targettarget", "oUF_targettarget"):SetPoint(unpack(settings.Positions.targettarget))
oUF:Spawn("focus", "oUF_focus"):SetPoint(unpack(settings.Positions.focus))
oUF:Spawn("focustarget", "oUF_focustarget"):SetPoint(unpack(settings.Positions.focustarget))
oUF:Spawn("pet", "oUF_pet"):SetPoint("TOPRIGHT", oUF.units.player, "TOPLEFT", -5, 0)

Compare with Previous | Blame