Skip to content

Instantly share code, notes, and snippets.

@LiQiuDGG
Created December 26, 2025 00:40
Show Gist options
  • Select an option

  • Save LiQiuDGG/083f9b042b4ce63b15156e1c9628b0b4 to your computer and use it in GitHub Desktop.

Select an option

Save LiQiuDGG/083f9b042b4ce63b15156e1c9628b0b4 to your computer and use it in GitHub Desktop.
QuaziiUI - New Datatexts: Currencies & M+ Key Implementation Options

QuaziiUI - New Datatexts: Currencies & M+ Key

Add new datatext panels for tracking Currencies and Mythic+ Keystones.


Overview

QuaziiUI already has a robust datatext system in qui_datatexts.lua with registration API.

Existing Datatexts: time, fps, latency, gold, durability, friends, guild, lootspec, bags

New Datatexts:

  1. Currencies - Display tracked currencies
  2. Mythic+ Key - Display current keystone level and dungeon

File Structure Options

Option 1: Add to Existing File

Append new datatexts directly to utils/qui_datatexts.lua.

  • Simple, follows existing pattern, no TOC changes
  • File grows larger (but still manageable)

Option 2: Modular Folder Structure

Create new folder utils/datatexts/ with separate files.

QuaziiUI/
  utils/
    datatexts/
      datatexts.xml
      currencies.lua
      mythickey.lua
  • Cleaner separation, easier to maintain
  • Requires TOC/XML changes

Currency Selection Options

Option 1: Backpack Currencies (Simple)

Use the 3 currencies already configured on the player's backpack bar.

  • Zero configuration needed
  • Player already chose these in Blizzard UI
  • Limited to 3 currencies
for i = 1, 3 do
    local info = C_CurrencyInfo.GetBackpackCurrencyInfo(i)
    if info then
        -- Display currency
    end
end

Option 2: Checkbox Selection (ElvUI-style)

Add checkboxes in QuaziiUI options to select which currencies to display.

  • Full user control
  • Can show more than 3 currencies
  • Requires options panel integration and SavedVariables
defaults.profile.quiDatatexts.currencies = {
    enabled = {},  -- Table of currencyID = true/false
    displayStyle = "ICON",  -- ICON, ICON_TEXT, ICON_TEXT_ABBR
    maxDisplay = 5,
}

Option 3: Preset Categories + Custom

Offer preset currency groups with option to customize.

Presets:

  • M+ & Raid: Valorstones, Ethereal Crests
  • PvP: Honor, Conquest
  • Custom: User-selected

TWW Season 3 Currency IDs (Patch 11.2)

Currency ID Color
Valorstones 3008 Blue (Heirloom)
Weathered Ethereal Crest 3285 Green (Uncommon)
Carved Ethereal Crest 3287 Blue (Rare)
Runed Ethereal Crest 3289 Purple (Epic)
Gilded Ethereal Crest 3290 Orange (Legendary)
Honor 1792 -
Conquest 1602 -
-- TWW Season 3 Preset
local CURRENCY_PRESETS = {
    ["M+ & Raid"] = {
        { id = 3008, color = HEIRLOOM_BLUE_COLOR },      -- Valorstones
        { id = 3285, color = UNCOMMON_GREEN_COLOR },     -- Weathered Ethereal
        { id = 3287, color = RARE_BLUE_COLOR },          -- Carved Ethereal
        { id = 3289, color = EPIC_PURPLE_COLOR },        -- Runed Ethereal
        { id = 3290, color = LEGENDARY_ORANGE_COLOR },   -- Gilded Ethereal
    },
    ["PvP"] = {
        { id = 1792 },  -- Honor
        { id = 1602 },  -- Conquest
    },
}

Midnight Expansion Note (March 2026)

QuaziiUI is not officially supporting Retail Midnight. For reference:

Change TWW (Current) Midnight
Valorstones Required (3008) REMOVED
Crest Names Ethereal Crests Dawncrests
Weekly Cap 90 per type 100 per type
Upgrade Cost ~75 crests/track 150 crests/track

New Midnight currencies will be named after gear tracks:

  • Adventurer Dawncrest, Veteran Dawncrest, Champion Dawncrest, Hero Dawncrest, Myth Dawncrest

Currencies Datatext Code

Datatexts:Register("currencies", {
    displayName = "Currencies",
    category = "Character",
    description = "Displays tracked currencies",
    
    OnEnable = function(slotFrame, settings)
        local frame = CreateFrame("Frame", nil, slotFrame)
        frame:SetAllPoints()
        
        local text = slotFrame.text
        if not text then
            text = slotFrame:CreateFontString(nil, "OVERLAY")
            text:SetPoint("CENTER")
            slotFrame.text = text
        end
        
        local iconString = "|T%s:14:14:0:0:64:64:4:60:4:60|t"
        
        local function AbbrevNumber(value)
            if value >= 1000000 then
                return format("%.1fM", value / 1000000)
            elseif value >= 1000 then
                return format("%.1fK", value / 1000)
            end
            return tostring(value)
        end
        
        local function GetDisplayCurrencies()
            local currencies = {}
            for i = 1, 3 do
                local info = C_CurrencyInfo.GetBackpackCurrencyInfo(i)
                if info then
                    table.insert(currencies, info)
                end
            end
            return currencies
        end
        
        local function Update()
            local currencies = GetDisplayCurrencies()
            local displayString = ""
            
            for i, info in ipairs(currencies) do
                local icon = format(iconString, info.iconFileID)
                local quantity = AbbrevNumber(info.quantity)
                if i > 1 then
                    displayString = displayString .. "  "
                end
                displayString = displayString .. icon .. " " .. quantity
            end
            
            if displayString == "" then
                text:SetText("|cff666666No Currencies|r")
            else
                text:SetText(displayString)
            end
        end
        
        frame.Update = Update
        
        frame:RegisterEvent("CURRENCY_DISPLAY_UPDATE")
        frame:RegisterEvent("PLAYER_ENTERING_WORLD")
        frame:SetScript("OnEvent", Update)
        
        slotFrame:EnableMouse(true)
        slotFrame:SetScript("OnEnter", function(self)
            GameTooltip:SetOwner(self, "ANCHOR_BOTTOM")
            GameTooltip:ClearLines()
            GameTooltip:AddLine("Currencies", 1, 1, 1)
            GameTooltip:AddLine(" ")
            
            local currencies = GetDisplayCurrencies()
            for _, info in ipairs(currencies) do
                local icon = format(iconString, info.iconFileID)
                local quantityStr = BreakUpLargeNumbers(info.quantity)
                if info.maxQuantity and info.maxQuantity > 0 then
                    quantityStr = quantityStr .. " / " .. BreakUpLargeNumbers(info.maxQuantity)
                end
                GameTooltip:AddDoubleLine(icon .. " " .. info.name, quantityStr, 1, 1, 1, 1, 1, 1)
            end
            
            GameTooltip:AddLine(" ")
            GameTooltip:AddLine("|cffFFFFFFLeft Click:|r Open Currency Panel", 0.2, 1, 0.2)
            GameTooltip:Show()
        end)
        slotFrame:SetScript("OnLeave", function() GameTooltip:Hide() end)
        
        slotFrame:RegisterForClicks("AnyUp")
        slotFrame:SetScript("OnClick", function(self, button)
            if button == "LeftButton" then
                ToggleCharacter("TokenFrame")
            end
        end)
        
        Update()
        return frame
    end,
    
    OnDisable = function(frame)
        frame:UnregisterAllEvents()
    end,
})

M+ Key Datatext Code

Datatexts:Register("mythickey", {
    displayName = "Mythic+ Key",
    category = "Character",
    description = "Displays your current Mythic+ keystone",
    
    OnEnable = function(slotFrame, settings)
        local frame = CreateFrame("Frame", nil, slotFrame)
        frame:SetAllPoints()
        
        local text = slotFrame.text
        if not text then
            text = slotFrame:CreateFontString(nil, "OVERLAY")
            text:SetPoint("CENTER")
            slotFrame.text = text
        end
        
        local function GetKeyColor(level)
            if level >= 20 then return 1, 0.5, 0
            elseif level >= 15 then return 0.64, 0.21, 0.93
            elseif level >= 10 then return 0, 0.44, 0.87
            elseif level >= 7 then return 0.12, 1, 0
            else return 1, 1, 1 end
        end
        
        local function Update()
            local keyLevel = C_MythicPlus.GetOwnedKeystoneLevel()
            local mapID = C_MythicPlus.GetOwnedKeystoneChallengeMapID()
            
            if keyLevel and keyLevel > 0 and mapID then
                local mapName = C_ChallengeMode.GetMapUIInfo(mapID)
                local abbrev = mapName and mapName:gsub("(%a)[%a]*%s*", "%1") or "?"
                
                local r, g, b = GetKeyColor(keyLevel)
                text:SetFormattedText("|cff%02x%02x%02x+%d %s|r", 
                    r*255, g*255, b*255, keyLevel, abbrev)
            else
                text:SetText("|cff666666No Key|r")
            end
        end
        
        frame.Update = Update
        
        frame:RegisterEvent("PLAYER_ENTERING_WORLD")
        frame:RegisterEvent("CHALLENGE_MODE_COMPLETED")
        frame:RegisterEvent("MYTHIC_PLUS_NEW_WEEKLY_RECORD")
        frame:RegisterEvent("BAG_UPDATE")
        frame:SetScript("OnEvent", Update)
        
        slotFrame:EnableMouse(true)
        slotFrame:SetScript("OnEnter", function(self)
            GameTooltip:SetOwner(self, "ANCHOR_BOTTOM")
            GameTooltip:ClearLines()
            GameTooltip:AddLine("Mythic+ Keystone", 1, 1, 1)
            GameTooltip:AddLine(" ")
            
            local keyLevel = C_MythicPlus.GetOwnedKeystoneLevel()
            local mapID = C_MythicPlus.GetOwnedKeystoneChallengeMapID()
            
            if keyLevel and keyLevel > 0 and mapID then
                local mapName = C_ChallengeMode.GetMapUIInfo(mapID)
                local r, g, b = GetKeyColor(keyLevel)
                GameTooltip:AddDoubleLine("Your Key:", 
                    format("+%d %s", keyLevel, mapName or "Unknown"),
                    0.8, 0.8, 0.8, r, g, b)
            else
                GameTooltip:AddLine("No keystone in bags", 0.7, 0.7, 0.7)
            end
            
            local affixes = C_MythicPlus.GetCurrentAffixes()
            if affixes and #affixes > 0 then
                GameTooltip:AddLine(" ")
                GameTooltip:AddLine("This Week's Affixes:", 1, 0.8, 0)
                for _, affixInfo in ipairs(affixes) do
                    local name = C_ChallengeMode.GetAffixInfo(affixInfo.id)
                    if name then
                        GameTooltip:AddLine("  " .. name, 0.8, 0.8, 0.8)
                    end
                end
            end
            
            GameTooltip:AddLine(" ")
            GameTooltip:AddLine("|cffFFFFFFLeft Click:|r Open Group Finder", 0.2, 1, 0.2)
            GameTooltip:Show()
        end)
        slotFrame:SetScript("OnLeave", function() GameTooltip:Hide() end)
        
        slotFrame:RegisterForClicks("AnyUp")
        slotFrame:SetScript("OnClick", function(self, button)
            if button == "LeftButton" then
                PVEFrame_ToggleFrame("GroupFinderFrame", LFGListPVEStub)
            end
        end)
        
        Update()
        return frame
    end,
    
    OnDisable = function(frame)
        frame:UnregisterAllEvents()
    end,
})

Summary

Decision Options
File Structure 1) Add to existing file, 2) New folder
Currency Selection 1) Backpack only, 2) Checkbox selection, 3) Presets + custom
Currency Option Complexity Options Panel SavedVariables
Option 1: Backpack Easy None None
Option 2: Checkboxes Medium Currency picker UI enabled table
Option 3: Presets Medium Preset dropdown preset + enabled

Sources

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment