···33F.Options = F.Options or {}
4455local panel
66+local content
67local controls = {}
88+local questRelatedKeys = {
99+ trackedOnly = true,
1010+ showQuestRestedText = true,
1111+ showIncompleteQuestXPText = true,
1212+ showCompletedQuestXPText = true,
1313+ showIncompleteQuestBar = true,
1414+ colorQuest = true,
1515+ colorQuestComplete = true,
1616+}
717818local function SetOption(key, value)
919 if F.InitDB then F.InitDB() end
···2535 end
26362737 if F.UpdateUI then F.UpdateUI() end
3838+3939+ if key == "questTrackingEnabled" or key == "trackedOnly" then
4040+ if F.State and F.State.UpdateQuestXP then
4141+ F.State:UpdateQuestXP()
4242+ end
4343+ if key == "questTrackingEnabled" and panel and panel:IsShown() then
4444+ F.Options.Refresh()
4545+ end
4646+ end
4747+end
4848+4949+local function SetNumericOption(key, value)
5050+ if F.InitDB then F.InitDB() end
5151+ if not F.DB then return end
5252+ F.DB[key] = value
5353+ if F.UpdateUI then F.UpdateUI() end
5454+end
5555+5656+local function SetColorOption(key, r, g, b, a)
5757+ if F.InitDB then F.InitDB() end
5858+ if not F.DB then return end
5959+ F.DB[key] = { r = r, g = g, b = b, a = a }
6060+ if F.UpdateUI then F.UpdateUI() end
6161+end
6262+6363+local function GetColorOption(key, fallback)
6464+ if F.InitDB then F.InitDB() end
6565+ if not F.DB then return fallback[1], fallback[2], fallback[3], fallback[4] end
6666+ local color = F.DB[key]
6767+ if type(color) == "table" then
6868+ if color.r then
6969+ return color.r or 1, color.g or 1, color.b or 1, color.a or 1
7070+ end
7171+ if color[1] then
7272+ return color[1] or 1, color[2] or 1, color[3] or 1, color[4] or 1
7373+ end
7474+ end
7575+ return fallback[1], fallback[2], fallback[3], fallback[4]
2876end
29773078local function CreateHeader(parent, text, y)
···4290 SetOption(key, self:GetChecked())
4391 end)
44924545- controls[key] = cb
9393+ controls[key] = { type = "checkbox", widget = cb }
4694 return y - 28
4795end
48969797+local function CreateSlider(parent, key, label, y, minValue, maxValue, step)
9898+ local name = "NXP_Options_" .. key .. "Slider"
9999+ local slider = CreateFrame("Slider", name, parent, "OptionsSliderTemplate")
100100+ slider:SetPoint("TOPLEFT", parent, "TOPLEFT", 16, y)
101101+ slider:SetMinMaxValues(minValue, maxValue)
102102+ slider:SetValueStep(step)
103103+ slider:SetObeyStepOnDrag(true)
104104+105105+ local labelText = _G[name .. "Text"]
106106+ local lowText = _G[name .. "Low"]
107107+ local highText = _G[name .. "High"]
108108+ if labelText then labelText:SetText(label) end
109109+ if lowText then lowText:SetText(tostring(minValue)) end
110110+ if highText then highText:SetText(tostring(maxValue)) end
111111+112112+ slider:SetScript("OnValueChanged", function(self, value)
113113+ if self._updating then return end
114114+ local rounded = math.floor(value + 0.5)
115115+ if step and step < 1 then
116116+ rounded = value
117117+ end
118118+ self._updating = true
119119+ self:SetValue(rounded)
120120+ self._updating = false
121121+ SetNumericOption(key, rounded)
122122+ end)
123123+124124+ controls[key] = { type = "slider", widget = slider }
125125+ return y - 52
126126+end
127127+128128+local function CreateColorPicker(parent, key, label, y, fallback)
129129+ local labelText = parent:CreateFontString(nil, "ARTWORK", "GameFontHighlight")
130130+ labelText:SetPoint("TOPLEFT", parent, "TOPLEFT", 16, y)
131131+ labelText:SetText(label)
132132+133133+ local swatch = CreateFrame("Button", nil, parent)
134134+ swatch:SetSize(16, 16)
135135+ swatch:SetPoint("LEFT", labelText, "RIGHT", 8, 0)
136136+ swatch:SetNormalTexture("Interface\\Buttons\\WHITE8x8")
137137+ swatch:SetHighlightTexture("Interface\\Buttons\\WHITE8x8", "ADD")
138138+ local swatchTex = swatch:GetNormalTexture()
139139+140140+ local border = swatch:CreateTexture(nil, "BORDER")
141141+ border:SetPoint("TOPLEFT", swatch, "TOPLEFT", -1, 1)
142142+ border:SetPoint("BOTTOMRIGHT", swatch, "BOTTOMRIGHT", 1, -1)
143143+ border:SetColorTexture(0, 0, 0, 1)
144144+ if swatchTex then
145145+ swatchTex:SetPoint("TOPLEFT", swatch, "TOPLEFT", 1, -1)
146146+ swatchTex:SetPoint("BOTTOMRIGHT", swatch, "BOTTOMRIGHT", -1, 1)
147147+ end
148148+149149+ swatch:SetScript("OnClick", function()
150150+ local r, g, b, a = GetColorOption(key, fallback)
151151+ local previous = { r = r, g = g, b = b, a = a }
152152+153153+ local function getPickerAlpha()
154154+ if ColorPickerFrame.GetColorAlpha then
155155+ return ColorPickerFrame:GetColorAlpha()
156156+ end
157157+ return 1 - (ColorPickerFrame.opacity or 0)
158158+ end
159159+160160+ local function applyColor()
161161+ local nr, ng, nb = ColorPickerFrame:GetColorRGB()
162162+ local na = getPickerAlpha()
163163+ SetColorOption(key, nr, ng, nb, na)
164164+ F.Options.Refresh()
165165+ end
166166+167167+ local function cancelColor()
168168+ local pv = previous
169169+ if pv then
170170+ SetColorOption(key, pv.r, pv.g, pv.b, pv.a)
171171+ F.Options.Refresh()
172172+ end
173173+ end
174174+175175+ if ColorPickerFrame.SetupColorPickerAndShow then
176176+ ColorPickerFrame:SetupColorPickerAndShow({
177177+ r = r,
178178+ g = g,
179179+ b = b,
180180+ opacity = 1 - (a or 1),
181181+ hasOpacity = true,
182182+ swatchFunc = applyColor,
183183+ opacityFunc = applyColor,
184184+ cancelFunc = cancelColor,
185185+ })
186186+ else
187187+ ColorPickerFrame.hasOpacity = true
188188+ ColorPickerFrame.opacity = 1 - (a or 1)
189189+ ColorPickerFrame.previousValues = previous
190190+ ColorPickerFrame.func = applyColor
191191+ ColorPickerFrame.opacityFunc = applyColor
192192+ ColorPickerFrame.cancelFunc = cancelColor
193193+ ColorPickerFrame:SetColorRGB(r, g, b)
194194+ ColorPickerFrame:Hide()
195195+ ColorPickerFrame:Show()
196196+ end
197197+ end)
198198+199199+ controls[key] = { type = "color", widget = swatch, label = labelText, fallback = fallback }
200200+ return y - 24
201201+end
202202+49203function F.Options.Refresh()
50204 if F.InitDB then F.InitDB() end
51205 if not F.DB then return end
522065353- for key, cb in pairs(controls) do
5454- cb:SetChecked(F.DB[key] and true or false)
207207+ local defaults = F.Config or {}
208208+209209+ for key, control in pairs(controls) do
210210+ if control.type == "checkbox" then
211211+ control.widget:SetChecked(F.DB[key] and true or false)
212212+ elseif control.type == "slider" then
213213+ local value = F.DB[key]
214214+ if value == nil then value = defaults[key] end
215215+ if value == nil then value = 0 end
216216+ control.widget._updating = true
217217+ control.widget:SetValue(tonumber(value) or 0)
218218+ control.widget._updating = false
219219+ elseif control.type == "color" then
220220+ local r, g, b, a = GetColorOption(key, control.fallback)
221221+ local tex = control.widget:GetNormalTexture()
222222+ if tex then tex:SetColorTexture(r, g, b, a) end
223223+ end
224224+ end
225225+226226+ local questEnabled = F.DB.questTrackingEnabled ~= false
227227+ for key, _ in pairs(questRelatedKeys) do
228228+ local control = controls[key]
229229+ if control then
230230+ if control.type == "checkbox" or control.type == "slider" then
231231+ control.widget:SetEnabled(questEnabled)
232232+ if control.widget.Text then
233233+ local color = questEnabled and NORMAL_FONT_COLOR or GRAY_FONT_COLOR
234234+ control.widget.Text:SetTextColor(color.r, color.g, color.b)
235235+ end
236236+ elseif control.type == "color" then
237237+ if questEnabled then
238238+ control.widget:Enable()
239239+ control.label:SetTextColor(NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b)
240240+ else
241241+ control.widget:Disable()
242242+ control.label:SetTextColor(GRAY_FONT_COLOR.r, GRAY_FONT_COLOR.g, GRAY_FONT_COLOR.b)
243243+ end
244244+ end
245245+ end
55246 end
56247end
57248···72263 panel = CreateFrame("Frame", "NXP_OptionsPanel", UIParent)
73264 panel.name = "NixxnuxXPBar"
742657575- local title = panel:CreateFontString(nil, "ARTWORK", "GameFontNormalLarge")
7676- title:SetPoint("TOPLEFT", panel, "TOPLEFT", 16, -16)
266266+ local scroll = CreateFrame("ScrollFrame", "NXP_OptionsScrollFrame", panel, "UIPanelScrollFrameTemplate")
267267+ scroll:SetPoint("TOPLEFT", panel, "TOPLEFT", 0, -8)
268268+ scroll:SetPoint("BOTTOMRIGHT", panel, "BOTTOMRIGHT", -30, 8)
269269+270270+ content = CreateFrame("Frame", nil, scroll)
271271+ content:SetSize(1, 1)
272272+ scroll:SetScrollChild(content)
273273+274274+ local title = content:CreateFontString(nil, "ARTWORK", "GameFontNormalLarge")
275275+ title:SetPoint("TOPLEFT", content, "TOPLEFT", 16, -8)
77276 title:SetText("NixxnuxXPBar")
782777979- local y = -48
8080- y = CreateHeader(panel, "General", y)
8181- y = CreateCheckbox(panel, "enabled", "Enable addon", y)
8282- y = CreateCheckbox(panel, "trackedOnly", "Count tracked (pinned) quests only", y)
278278+ local y = -40
279279+ y = CreateHeader(content, "General", y)
280280+ y = CreateCheckbox(content, "enabled", "Enable addon", y)
281281+ y = CreateCheckbox(content, "questTrackingEnabled", "Enable quest tracking", y)
282282+ y = CreateCheckbox(content, "trackedOnly", "Count tracked (pinned) quests only", y)
283283+ y = CreateCheckbox(content, "showIncompleteQuestBar", "Show uncompleted quest XP bar", y)
284284+285285+ y = y - 10
286286+ y = CreateHeader(content, "Bar Size", y)
287287+ y = y - 6
288288+ y = CreateSlider(content, "barWidth", "Bar width", y, 200, 900, 1)
289289+ y = CreateSlider(content, "barHeight", "Bar height", y, 8, 60, 1)
290290+291291+ y = y - 6
292292+ y = CreateHeader(content, "Bar Colors", y)
293293+ y = CreateColorPicker(content, "colorMain", "Normal XP", y, { 0.76, 0.38, 1, 1 })
294294+ y = CreateColorPicker(content, "colorRested", "Rested XP", y, { 0.34, 0.61, 0.99, 0.8 })
295295+ y = CreateColorPicker(content, "colorQuest", "Uncompleted Quest XP", y, { 1, 0.64, 0.0078, 0.25 })
296296+ y = CreateColorPicker(content, "colorQuestComplete", "Completed Quest XP", y, { 1, 0.64, 0.0078, 0.8 })
8329784298 y = y - 10
8585- y = CreateHeader(panel, "Text Labels", y)
8686- y = CreateCheckbox(panel, "showLevelText", "Level text", y)
8787- y = CreateCheckbox(panel, "showXPText", "XP text", y)
8888- y = CreateCheckbox(panel, "showPercentText", "Percent text", y)
8989- y = CreateCheckbox(panel, "showQuestRestedText", "Quest/rested percent text", y)
9090- y = CreateCheckbox(panel, "showLevelingText", "Leveling info text", y)
9191- y = CreateCheckbox(panel, "showIncompleteQuestXPText", "Uncompleted quest XP text", y)
9292- y = CreateCheckbox(panel, "showCompletedQuestXPText", "Completed quest XP text", y)
9393- y = CreateCheckbox(panel, "showRestedXPText", "Rested XP text", y)
299299+ y = CreateHeader(content, "Text Labels", y)
300300+ y = CreateCheckbox(content, "showLevelText", "Level text", y)
301301+ y = CreateCheckbox(content, "showXPText", "XP text", y)
302302+ y = CreateCheckbox(content, "showPercentText", "Percent text", y)
303303+ y = CreateCheckbox(content, "showQuestRestedText", "Quest/rested percent text", y)
304304+ y = CreateCheckbox(content, "showLevelingText", "Leveling info text", y)
305305+ y = CreateCheckbox(content, "showIncompleteQuestXPText", "Uncompleted quest XP text", y)
306306+ y = CreateCheckbox(content, "showCompletedQuestXPText", "Completed quest XP text", y)
307307+ y = CreateCheckbox(content, "showRestedXPText", "Rested XP text", y)
308308+309309+ content:SetHeight(-y + 20)
9431095311 panel:SetScript("OnShow", function()
96312 F.Options.Refresh()
+7
State.lua
···6565end
66666767function F.State:UpdateQuestXP()
6868+ if F.DB and F.DB.questTrackingEnabled == false then
6969+ self.questXP = 0
7070+ self.completeXP = 0
7171+ self.incompleteXP = 0
7272+ return
7373+ end
7474+6875 local numEntries = C_QuestLog.GetNumQuestLogEntries()
6976 local qXP, cXP, iXP = 0, 0, 0
7077
+31-6
UI.lua
···216216 local s = F.State
217217 local db = F.DB
218218219219+ if db and db.barWidth and db.barHeight then
220220+ F.Frame:SetSize(db.barWidth, db.barHeight)
221221+ end
222222+223223+ local function resolveColor(color, fallback)
224224+ if type(color) == "table" then
225225+ if color.r then
226226+ return color.r or 1, color.g or 1, color.b or 1, color.a or 1
227227+ end
228228+ if color[1] then
229229+ return color[1] or 1, color[2] or 1, color[3] or 1, color[4] or 1
230230+ end
231231+ end
232232+ return fallback[1], fallback[2], fallback[3], fallback[4]
233233+ end
234234+235235+ if db then
236236+ F.BarMain:SetStatusBarColor(resolveColor(db.colorMain, CFG.colorMain))
237237+ F.BarRested:SetStatusBarColor(resolveColor(db.colorRested, CFG.colorRested))
238238+ F.BarQuest:SetStatusBarColor(resolveColor(db.colorQuest, CFG.colorQuest))
239239+ F.BarQuestComplete:SetStatusBarColor(resolveColor(db.colorQuestComplete, CFG.colorQuestComplete))
240240+ end
241241+219242 if s.isMaxLevel and not db.showAtMaxLevel then
220243 F.Frame:Hide()
221244 return
···316339 local infoParts = {}
317340318341 if db.showQuestRestedText and s.maxXP > 0 then
319319- if (s.completeXP or 0) > 0 then
342342+ if db.questTrackingEnabled ~= false and (s.completeXP or 0) > 0 then
320343 table.insert(infoParts, string.format("Completed Quests: %.1f%%", ((s.completeXP or 0) / s.maxXP * 100)))
321344 end
322345 if (s.restedXP or 0) > 0 then
···350373351374 do
352375 local xpParts = {}
353353- if db.showIncompleteQuestXPText and (s.incompleteXP or 0) > 0 then
354354- table.insert(xpParts, string.format("Uncompleted Quest XP: %s", FormatLargeNumber(s.incompleteXP or 0)))
355355- end
356356- if db.showCompletedQuestXPText and (s.completeXP or 0) > 0 then
357357- table.insert(xpParts, string.format("Completed Quest XP: %s", FormatLargeNumber(s.completeXP or 0)))
376376+ if db.questTrackingEnabled ~= false then
377377+ if db.showIncompleteQuestXPText and (s.incompleteXP or 0) > 0 then
378378+ table.insert(xpParts, string.format("Uncompleted Quest XP: %s", FormatLargeNumber(s.incompleteXP or 0)))
379379+ end
380380+ if db.showCompletedQuestXPText and (s.completeXP or 0) > 0 then
381381+ table.insert(xpParts, string.format("Completed Quest XP: %s", FormatLargeNumber(s.completeXP or 0)))
382382+ end
358383 end
359384 if db.showRestedXPText and (s.restedXP or 0) > 0 then
360385 table.insert(xpParts, string.format("Rested XP: %s", FormatLargeNumber(s.restedXP or 0)))