Something went wrong. Try again.
A World of Warcraft Experience Bar addon
worldofwarcraft wow addon midnight
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407local AddonName, F = ...
F.UI = {}
local CFG = { width = 600, height = 24, texture = "Interface\\Buttons\\WHITE8x8", font = "Fonts\\FRIZQT__.TTF", fontSize = 14, barFontSize = 12,
-- Colors (R, G, B, A) colorBack = {0.0, 0.0, 0.0, 0.8}, colorBorder = {0, 0, 0, 1},
colorMain = {0.76, 0.38, 1, 1}, -- Base Purple colorRested = {0.34, 0.61, 0.99, .8}, -- Rested Blue colorQuest = {1, 0.64, 0.0078, 0.25}, -- Quest Yellow colorQuestComplete = {1, 0.64, 0.0078, 0.8}, -- Completed Quest}
function F.UI.CreateStatusBar(parent, layer, subLevel, color) local bar = CreateFrame("StatusBar", nil, parent) bar:SetAllPoints() bar:SetStatusBarTexture(CFG.texture) bar:SetStatusBarColor(unpack(color)) bar:GetStatusBarTexture():SetDrawLayer(layer, subLevel) return barend
function F.UI.Create() local f = CreateFrame("Frame", "NXP_Frame", UIParent) f:SetSize(CFG.width, CFG.height) f:SetPoint("TOP", UIParent, "TOP", 0, 100) -- Default Position f:SetFrameStrata("LOW")
f:SetMovable(false) f:EnableMouse(false)
F.Frame = f
-- 2. Background & Border local bg = f:CreateTexture(nil, "BACKGROUND") bg:SetAllPoints() bg:SetTexture(CFG.texture) bg:SetVertexColor(unpack(CFG.colorBack))
-- Rested XP Bar F.BarRested = F.UI.CreateStatusBar(f, "BACKGROUND", 2, CFG.colorRested)
-- Quest XP Bar F.BarQuest = F.UI.CreateStatusBar(f, "BORDER", 1, CFG.colorQuest)
-- Completed Quest Bar F.BarQuestComplete = F.UI.CreateStatusBar(f, "BORDER", 2, CFG.colorQuestComplete)
-- Main XP Bar F.BarMain = F.UI.CreateStatusBar(f, "ARTWORK", 1, CFG.colorMain)
-- XP Ticks (20 segments) local tickContainer = CreateFrame("Frame", nil, f) tickContainer:SetAllPoints() tickContainer.ticks = {} for i = 1, 19 do local tick = tickContainer:CreateTexture(nil, "OVERLAY") tick:SetColorTexture(0, 0, 0, 0.35) tick:SetWidth(1) tickContainer.ticks[i] = tick end F.TickContainer = tickContainer
local overlay = CreateFrame("Frame", nil, f) overlay:SetAllPoints() overlay:SetFrameLevel(f:GetFrameLevel() + 10) F.Overlay = overlay
-- level label F.LevelText = overlay:CreateFontString(nil, "OVERLAY") F.LevelText:SetFont(CFG.font, CFG.barFontSize, "OUTLINE") F.LevelText:SetPoint("LEFT", overlay, "LEFT", 8, 0) F.LevelText:SetJustifyH("LEFT") F.LevelText:SetDrawLayer("OVERLAY", 2) F.LevelText:SetTextColor(1, 1, 1, 1)
-- current / max XP F.TextCenter = overlay:CreateFontString(nil, "OVERLAY") F.TextCenter:SetFont(CFG.font, CFG.barFontSize, "OUTLINE") F.TextCenter:SetPoint("CENTER", overlay, "CENTER", 0, 0) F.TextCenter:SetJustifyH("CENTER") F.TextCenter:SetDrawLayer("OVERLAY", 2) F.TextCenter:SetTextColor(1, 1, 1, 1)
-- percent text F.TextRight = overlay:CreateFontString(nil, "OVERLAY") F.TextRight:SetFont(CFG.font, CFG.barFontSize, "OUTLINE") F.TextRight:SetPoint("RIGHT", overlay, "RIGHT", -8, 0) F.TextRight:SetJustifyH("RIGHT") F.TextRight:SetDrawLayer("OVERLAY", 2) F.TextRight:SetTextColor(1, 1, 1, 1)
-- text below the bar (completed quests/rested) F.InfoText = overlay:CreateFontString(nil, "OVERLAY") F.InfoText:SetFont(CFG.font, CFG.fontSize - 2, "OUTLINE") F.InfoText:SetPoint("TOP", overlay, "BOTTOM", 0, -8) F.InfoText:SetJustifyH("CENTER") F.InfoText:SetDrawLayer("OVERLAY", 2) F.InfoText:SetTextColor(1, 1, 1, 1)
-- quest/rested XP amounts F.QuestXPText = overlay:CreateFontString(nil, "OVERLAY") F.QuestXPText:SetFont(CFG.font, CFG.fontSize - 2, "OUTLINE") F.QuestXPText:SetPoint("TOP", overlay, "BOTTOM", 0, -22) F.QuestXPText:SetJustifyH("CENTER") F.QuestXPText:SetDrawLayer("OVERLAY", 2) F.QuestXPText:SetTextColor(1, 1, 1, 1)
-- Leveling info F.LevelingText = overlay:CreateFontString(nil, "OVERLAY") F.LevelingText:SetFont(CFG.font, CFG.fontSize - 2, "OUTLINE") F.LevelingText:SetPoint("BOTTOMLEFT", overlay, "TOPLEFT", 0, 6) F.LevelingText:SetJustifyH("LEFT") F.LevelingText:SetDrawLayer("OVERLAY", 2) F.LevelingText:SetTextColor(1, 1, 1, 1)
F.UI.Update()
F.UI.HideBlizzardBars()end
function F.UI.HideBlizzardBars() if not (F and F.DB and F.DB.hideBlizzardXPBar) then return end
if MainMenuExpBar then MainMenuExpBar:UnregisterAllEvents() MainMenuExpBar:Hide() end
if ReputationWatchBar then ReputationWatchBar:UnregisterAllEvents() ReputationWatchBar:Hide() end
if StatusTrackingBarManager then StatusTrackingBarManager:UnregisterAllEvents() StatusTrackingBarManager:Hide() end
if MainMenuBarPerformanceBar then MainMenuBarPerformanceBar:UnregisterAllEvents() MainMenuBarPerformanceBar:Hide() endend
function F.UI.Update() if not F.Frame then F.UI.Create() end
local s = F.State local db = F.DB
if db and db.barWidth and db.barHeight then local width = db.barWidth if width then local scale = F.Frame:GetEffectiveScale() or 1 local stepPixels = math.floor(((width / 20) * scale) + 0.5) width = (stepPixels / scale) * 20 end F.Frame:SetSize(width or db.barWidth, db.barHeight) end
if db then local anchor = db.anchorPoint or "TOP" local x = tonumber(db.offsetX) or 0 local y = tonumber(db.offsetY) or 0 if anchor == "TOP" then y = -y end F.Frame:ClearAllPoints() F.Frame:SetPoint(anchor, UIParent, anchor, x, y) end
if F.TickContainer then if db and db.showTicks then local width = F.Frame:GetWidth() local height = F.Frame:GetHeight() if width and width > 0 then local step = width / 20 local scale = F.Frame:GetEffectiveScale() or 1 local opacity = 0.35 if db and type(db.tickOpacity) == "number" then opacity = db.tickOpacity end for i = 1, 19 do local tick = F.TickContainer.ticks[i] if tick then local x = step * i x = math.floor((x * scale) + 0.5) / scale tick:ClearAllPoints() tick:SetColorTexture(0, 0, 0, opacity) tick:SetPoint("TOPLEFT", F.Frame, "TOPLEFT", x, 0) tick:SetPoint("BOTTOMLEFT", F.Frame, "BOTTOMLEFT", x, 0) tick:Show() end end F.TickContainer:Show() else F.TickContainer:Hide() end else F.TickContainer:Hide() end end
local function resolveColor(color, fallback) if type(color) == "table" then if color.r then return color.r or 1, color.g or 1, color.b or 1, color.a or 1 end if color[1] then return color[1] or 1, color[2] or 1, color[3] or 1, color[4] or 1 end end return fallback[1], fallback[2], fallback[3], fallback[4] end
if db then local fontPath = db.fontPath or CFG.font F.LevelText:SetFont(fontPath, CFG.barFontSize, "OUTLINE") F.TextCenter:SetFont(fontPath, CFG.barFontSize, "OUTLINE") F.TextRight:SetFont(fontPath, CFG.barFontSize, "OUTLINE") F.InfoText:SetFont(fontPath, CFG.fontSize - 2, "OUTLINE") F.LevelingText:SetFont(fontPath, CFG.fontSize - 2, "OUTLINE") if F.QuestXPText then F.QuestXPText:SetFont(fontPath, CFG.fontSize - 2, "OUTLINE") end
local mainTexture = db.barTextureMain or CFG.texture local restedTexture = db.barTextureRested or CFG.texture local questTexture = db.barTextureQuest or CFG.texture local questCompleteTexture = db.barTextureQuestComplete or CFG.texture F.BarMain:SetStatusBarTexture(mainTexture) F.BarRested:SetStatusBarTexture(restedTexture) F.BarQuest:SetStatusBarTexture(questTexture) F.BarQuestComplete:SetStatusBarTexture(questCompleteTexture)
F.BarMain:SetStatusBarColor(resolveColor(db.colorMain, CFG.colorMain)) F.BarRested:SetStatusBarColor(resolveColor(db.colorRested, CFG.colorRested)) F.BarQuest:SetStatusBarColor(resolveColor(db.colorQuest, CFG.colorQuest)) F.BarQuestComplete:SetStatusBarColor(resolveColor(db.colorQuestComplete, CFG.colorQuestComplete)) end
if s.isMaxLevel and not db.showAtMaxLevel then F.Frame:Hide() return else F.Frame:Show() end
if s.isMaxLevel then F.BarMain:Hide() F.BarQuest:Hide() F.BarRested:Hide() else F.BarMain:Show() end
local maxXP = (s.maxXP > 0) and s.maxXP or 1
F.BarMain:SetMinMaxValues(0, maxXP) F.BarMain:SetValue(math.min(s.currentXP, maxXP))
local projectedComplete = s.currentXP + (s.completeXP or 0) local projectedQuest = projectedComplete + (db.showIncompleteQuestBar and (s.incompleteXP or 0) or 0)
if s.maxXP > 0 and projectedComplete > s.currentXP then F.BarQuestComplete:Show() F.BarQuestComplete:SetMinMaxValues(0, maxXP) F.BarQuestComplete:SetValue(math.min(projectedComplete, s.maxXP)) else F.BarQuestComplete:Hide() end
if s.maxXP > 0 and projectedQuest > projectedComplete and projectedComplete < s.maxXP then F.BarQuest:Show() F.BarQuest:SetMinMaxValues(0, maxXP) F.BarQuest:SetValue(math.min(projectedQuest, s.maxXP)) else F.BarQuest:Hide() end
local projectedRested = s.currentXP + (s.restedXP or 0) if s.maxXP > 0 and (s.restedXP or 0) > 0 and s.currentXP < s.maxXP then F.BarRested:Show() F.BarRested:SetMinMaxValues(0, maxXP) F.BarRested:SetValue(math.min(projectedRested, s.maxXP)) else F.BarRested:Hide() end
local hourlyXP, timeToLevel, sessionTime = F.State:GetSessionStats() local percentXP = (s.maxXP > 0) and (s.currentXP / s.maxXP * 100) or 0 local percentRested = (s.maxXP > 0) and (s.restedXP / s.maxXP * 100) or 0
if db.showLevelText then F.LevelText:SetText("Level " .. s.level) F.LevelText:Show() else F.LevelText:SetText("") F.LevelText:Hide() end
if db.showXPText then if s.isMaxLevel then F.TextCenter:SetText("Level " .. s.level .. " (Max)") else F.TextCenter:SetText(string.format("%s / %s", FormatLargeNumber(s.currentXP), FormatLargeNumber(s.maxXP))) end F.TextCenter:Show() else F.TextCenter:SetText("") F.TextCenter:Hide() end
local percentStr = "" if not s.isMaxLevel and s.maxXP > 0 then local completedXP = (s.completeXP or 0) local percentCompleted = (s.maxXP > 0) and (completedXP / s.maxXP * 100) or 0 local percentWithComplete = percentXP + percentCompleted
if completedXP > 0 then percentStr = string.format("%.1f%% (%.1f%%)", percentXP, math.min(100, percentWithComplete)) elseif (s.restedXP or 0) > 0 and db.showQuestRestedText then local percentWithRest = percentXP + percentRested percentStr = string.format("%.1f%% (%.1f%%)", percentXP, math.min(100, percentWithRest)) else percentStr = string.format("%.1f%%", percentXP) end end
if db.showPercentText and percentStr ~= "" and s.maxXP > 0 then F.TextRight:SetText(percentStr) F.TextRight:Show() else F.TextRight:SetText("") F.TextRight:Hide() end
do local infoParts = {}
if db.showQuestRestedText and s.maxXP > 0 then if db.questTrackingEnabled ~= false and (s.completeXP or 0) > 0 then table.insert(infoParts, string.format("Completed Quests: %.1f%%", ((s.completeXP or 0) / s.maxXP * 100))) end if (s.restedXP or 0) > 0 then table.insert(infoParts, string.format("Rested Experience: %.1f%%", ((s.restedXP or 0) / s.maxXP * 100))) end end
local levelingStr = "" if db.showXPHourText and not s.isMaxLevel and hourlyXP > 0 then local xpRateText = hourlyXP > 10000 and (F.Utils.Round(hourlyXP / 1000, 1) .. "K") or FormatLargeNumber(hourlyXP) local timerText = timeToLevel > 0 and F.Utils.FormatTime(timeToLevel) or "--" levelingStr = string.format("Leveling in: %s (%s XP/Hr)", timerText, xpRateText) end
if db.showQuestRestedText and #infoParts > 0 then F.InfoText:SetText(table.concat(infoParts, " - ")) F.InfoText:Show() else F.InfoText:SetText("") F.InfoText:Hide() end
if db.showLevelingText and levelingStr ~= "" then F.LevelingText:SetText(levelingStr) F.LevelingText:Show() else F.LevelingText:SetText("") F.LevelingText:Hide() end end
do local xpParts = {} if db.questTrackingEnabled ~= false then if db.showIncompleteQuestXPText and (s.incompleteXP or 0) > 0 then table.insert(xpParts, string.format("Uncompleted Quest XP: %s", FormatLargeNumber(s.incompleteXP or 0))) end if db.showCompletedQuestXPText and (s.completeXP or 0) > 0 then table.insert(xpParts, string.format("Completed Quest XP: %s", FormatLargeNumber(s.completeXP or 0))) end end if db.showRestedXPText and (s.restedXP or 0) > 0 then table.insert(xpParts, string.format("Rested XP: %s", FormatLargeNumber(s.restedXP or 0))) end
if #xpParts > 0 then F.QuestXPText:SetText(table.concat(xpParts, " - ")) F.QuestXPText:Show() else F.QuestXPText:SetText("") F.QuestXPText:Hide() end endend