Sulphur Unit Frames
In devPlayer, target, target of target, focus and pet on secure buttons, with 2D or 3D portraits and a live preview in settings.
/sufRetailMoPEraForever
SulphurUI is one suite of twenty-seven module addons — unit and raid frames, nameplates, action bars, a HUD you build row by row, meters, chat, a guild raid assistant and more — sharing one shell, one searchable settings panel, one first-run setup and one layout grid. Every module ships switched off until you turn it on.
A fake-roster preview fills the frames when you're not in a group, so you can size, sort and place them before raid night instead of during it.
/srfRetailMoPEraForeverUp to four meter windows. Drag one onto another and they dock into a single train; click any bar for that player's spell breakdown. Reads Blizzard's damage meter on Midnight and parses the combat log on MoP.
/smeterRetailMoPEraForeverEight bars built on Blizzard's own action buttons, so cooldowns, charges and range stay exactly right. Paging runs on secure drivers, keybinding has its own mode, and layout profiles remember spells rather than slots.
/sbars/skbRetailMoPEraForeverPlan Bloodlust per boss, catch missing consumables on every ready check, track BiS drops and pull timers, and sync it all across the raid automatically.
Every setting in every module lives in one registry. Type a word and each hit shows where it lives and its live control inline, so the search result is the place you change it.
/sui/sgridRetailMoPEraForeverEach module is its own addon sitting on the SulphurUI core, so they share one look, one settings panel, one first-run setup and one snap-and-dock layout grid. Status is shown honestly: GRA is live, and the rest is built and waiting on its in-game pass. Retail-only modules are the ones built on systems the Classic clients do not have.
Guild Raid Assistant: Hero Plan lust calls, pre-raid and ready checks, BiS tracking, guild-bank scan, loot popup and raid-wide sync.
Player, target, target of target, focus and pet on secure buttons, with 2D or 3D portraits and a live preview in settings.
/sufRetailMoPEraForeverRaid frames with cast bars and a fake-roster preview, so the layout is set before you ever zone in.
/srfRetailMoPEraForeverOur own plates on Blizzard's nameplate frames: health, cast bar, your debuffs with pandemic cues, and a taunt and CC row.
/snpRetailMoPEraForeverEight bars on Blizzard's own buttons, secure paging, a keybind mode, and layout profiles that remember spells.
/sbarsRetailMoPEraForeverBuild a HUD one row at a time per class and spec: health, power, pips, cast bar, cooldowns, auras, missing buffs.
/shbRetailMoPEraForeverA player-centred stack of class pips, health, power and your cast bar, with secret-safe text and engine-smoothed bars.
/sresRetailMoPEraForeverThree icon rows for the cooldowns, utility and procs you choose, including trinkets that show proc, then cooldown, on one icon.
/schudRetailMoPEraForeverBlizzard's own cooldown viewers moved into placeable Sulphur containers, with a reversible restyle and drawn buff bars.
/scdmRetailMoPEraForeverYour buffs and debuffs in two independently placed grids, with a fold-away header and a preview for placing them.
/sauraRetailMoPEraForeverA missing-buff row for your class raid buff, upkeep buffs, weapon imbue and Healthstone. Out of combat only.
/sremRetailMoPEraForeverA battle-res charge tracker and a movement-cooldown alert, both event-driven, both off until you want them.
/saidsRetailMoPEraForeverHold a key, a ring of up to eight spells opens at the cursor, aim and release to cast. Works in combat.
/sqdRetailMoPEraForeverA raid-leader bar: raid and world markers, ready check, role check, pull timer and raid convert.
/srtRetailMoPEraForeverUp to four thin meter windows that dock into a train. Click a bar for the spell breakdown.
/smeterRetailMoPEraForeverTwo chat docks, conversation on the left and the system firehose on the right, with routing picked once in first-run setup.
/schatRetailMoPEraForeverA square minimap with zone, spec and professions stacked beneath, plus one bag that collects minimap buttons.
/smapRetailMoPEraForeverA strip along the top or bottom edge: gold, durability, bag slots, zone, FPS and latency, clock, friends, guild.
/sinfoRetailMoPEraForeverOne experience bar with completed-quest, incomplete-quest and rested overlays and optional texts.
/sxpRetailMoPEraForeverDecorative bars, wedges and a clean top bar that frame your interface. Always underneath, never eats a click.
/shudRetailMoPEraForeverQuick loot, auto repair, sell junk, quest accept, keystone slotting, an item upgrade calculator and more, every switch off by default.
/sqolRetailMoPEraForeverA replacement bag window with flat item boxes and one search, sharing its container with Bank.
/sbagsRetailMoPEraForeverYour bank in the same container as Bags, plus a shared-storage window for the guild bank and your alts.
/sbankRetailMoPEraForeverA replacement mailbox window that stays out of the way until you open it.
/smailRetailMoPEraForever57 skin packs for Blizzard's own windows, now with Sulphur header bands and gear-slot boxes. Every pack is off until you pick it.
A small gliding HUD: vigor pips, speed, Whirling Surge and Second Wind. Hidden in instances.
/sskyRetailA Mythic+ run display: timer with chest thresholds, enemy forces, deaths and boss splits.
/smplusRetailThese are unretouched screenshots from our own test night on the WoW Forever client, on a level 3 character. The concepts below set the direction, and this is how far the build has come. It is still being worked on: some Blizzard art, like the gold option labels and the parchment map, has not been reskinned yet.
These are design mockups, not in-game captures. They set the direction for the Sulphur skin packs: dark flat panels, one green accent, hairline borders. The Great Vault and Character windows already ship in this style, and the rest follow.
These are real, unedited excerpts from the SulphurUI tree. Modules, blocks, switches and settings are all small tables that the core shell runs, so the rules below are built into how the code is written.
SulphurUI.Modules.Register("infobar", {
label = "Sulphur Info Bar",
default = false,
onEnable = function()
I.SetActive(true)
Build()
Bar.Apply()
frame:Show()
I.Blocks.SyncAll("module enabled")
Log("enabled", { blocks = I.Blocks.CountOn(), edge = I.Get("edge") })
end,
onDisable = function()
if not I.IsActive() then return end
I.SetActive(false)
I.Blocks.SyncAll("module disabled")
if frame then frame:Hide() end
Log("disabled")
end,
})
Every module is its own addon and joins the suite through one call. It defaults off, and switching it off releases what it built. That is rule 01 in code.
local DURABILITY_FIRST, DURABILITY_LAST = 1, 18
I.Block({
id = "durability", label = "Durability",
events = { "UPDATE_INVENTORY_DURABILITY", "UPDATE_INVENTORY_ALERTS" },
paint = function()
local lowest = 100
for slot = DURABILITY_FIRST, DURABILITY_LAST do
local cur, max = GetInventoryItemDurability(slot)
if cur and max and max > 0 then
local pct = cur / max * 100
if pct < lowest then lowest = pct end
end
end
return string.format("Durability %d%%", math.floor(lowest))
end,
})
A block is data: an id, the events that repaint it and a paint function. It registers those events only while it is switched on, and it has no timer.
-- Sell junk, through Compat.SellJunk: one server call on live, a stepped bag
-- walk on 5.5.4 that stops the moment the merchant closes.
local lastJunk
Q.Feature({
key = "autoSellJunk",
events = { "MERCHANT_SHOW", "MERCHANT_CLOSED" },
OnEvent = function(event)
if event == "MERCHANT_CLOSED" then
merchantOpen = false
return
end
merchantOpen = true
local branch, count = Compat.SellJunk(function()
return merchantOpen and Q.IsApplied("autoSellJunk")
end)
lastJunk = string.format("%s, %s item(s)", branch, tostring(count or "unknown"))
if count == 0 then
Q.LogThrottled("autoSellJunk-none", "no junk to sell", { branch = branch })
return
end
Log("junk sold", { branch = branch, items = count or "unknown" })
end,
describe = function() return "last visit: " .. (lastJunk or "none this session") end,
})
Sell junk is one server call on Retail and a bag walk on MoP that stops as soon as the merchant closes. Compat picks the path, and every sale is logged.
{
key = "durabilityWarn", type = "number", label = "Low durability warning",
min = limits.durabilityWarn[1], max = limits.durabilityWarn[2], step = 1, unit = " %",
description = "Warns once, out of combat, when your most worn item drops to this percentage. 0 switches the warning off.",
keywords = "durability repair warning low threshold percent",
hidden = hiddenUnless("durabilityWarn"),
get = function() return Q.Get("durabilityWarn") end,
set = function(v) Q.Set("durabilityWarn", v) end,
},
A setting is a table entry, not widget code. The panel draws it, and its keywords are how the search box finds it.
Every new module is reviewed against the same four rules before it ships.
A switched-off feature registers no events and builds no frames. Hidden means unregistered, not just invisible.
New settings ship off, so an update never rearranges your screen without you asking.
No per-frame polling. A timer exists only while the text that needs it is actually on screen.
Blizzard's protected frames are placed and hidden through secure drivers, never hooked, so no mystery errors mid-pull.