BulwarkFrame v0.3.1

This commit is contained in:
2026-08-30 23:24:22 +02:00
parent 2596721daf
commit 03e0fe13a8
4 changed files with 53 additions and 12 deletions
+1 -1
View File
@@ -2,7 +2,7 @@
## Title: BulwarkFrame ## Title: BulwarkFrame
## Notes: Compact real-time readout for the shaman Earthen Bulwark. Requires SuperWoW. ## Notes: Compact real-time readout for the shaman Earthen Bulwark. Requires SuperWoW.
## Author: ShempError ## Author: ShempError
## Version: 0.3.0 ## Version: 0.3.1
## SavedVariables: BulwarkFrameDB ## SavedVariables: BulwarkFrameDB
core\env.lua core\env.lua
+16
View File
@@ -2,6 +2,22 @@
All notable changes to BulwarkFrame are documented here. All notable changes to BulwarkFrame are documented here.
## v0.3.1 — 2026-08-31
### Fixed
- **Aura-id edit boxes no longer accept 0.** A QA pass on the options panel
found that `tonumber("0")` is truthy, so typing `0` into the pool or time
aura spell-id field was accepted as a valid id and silently written --
spell ids never start at 0, so this was a silent no-op buffer. `0` (and
negative values) are now rejected exactly like any unparsable entry: the
field reverts to the currently stored id.
- **Pool/expiry red and yellow thresholds can no longer cross.** The four
threshold sliders had no cross-validation, so dragging the red slider
past yellow (or yellow past red) inverted the colour chain in
`core/calc.lua`'s bucket logic. The slider being moved now pulls its
partner along with it instead of letting the pair invert, and the panel
display re-syncs immediately.
## v0.3.0 — 2026-08-30 ## v0.3.0 — 2026-08-30
### Added ### Added
+7 -5
View File
@@ -10,15 +10,17 @@ stands. Three thin bars, nothing else. No dependencies beyond SuperWoW; adopts t
<img src="screenshots/readout-hit.png" alt="The readout: hit threshold, expiry bar with the swing marker riding on it" width="100%"> <img src="screenshots/readout-hit.png" alt="The readout: hit threshold, expiry bar with the swing marker riding on it" width="100%">
## What's new — v0.3.0 · 2026-08-30 ## What's new — v0.3.1 · 2026-08-31
- **Every setting has a control now.** Ten saved settings could only be changed by editing the - **Aura-id edit boxes no longer accept 0.** `0` and negative values are now rejected like any
SavedVariables file; the options panel now covers bar spacing, the attack-speed text, expiry unparsable entry instead of being written as a spell id.
bar opacity, background colour and opacity, the four colour thresholds, the set-bonus value, - **Pool/expiry red and yellow thresholds can no longer cross.** Dragging one past its partner
the latency share and the two aura ids. now pulls the partner along instead of inverting the colour chain.
**Version history** — details in [CHANGELOG.md](CHANGELOG.md): **Version history** — details in [CHANGELOG.md](CHANGELOG.md):
- **v0.3.1** (2026-08-31) — aura-id edit boxes reject `0`; pool/expiry threshold sliders can
no longer cross.
- **v0.3.0** (2026-08-30) — options-panel controls for every setting that had none. - **v0.3.0** (2026-08-30) — options-panel controls for every setting that had none.
- **v0.2.0** (2026-08-15) — max health stays accurate through stamina buffs and level-ups, - **v0.2.0** (2026-08-15) — max health stays accurate through stamina buffs and level-ups,
"Combat only" no longer sticks off after a mid-fight reload, `/bulwark reset` really moves a "Combat only" no longer sticks off after a mid-fight reload, `/bulwark reset` really moves a
+29 -6
View File
@@ -218,7 +218,10 @@ local function CreateEditBox(parent, label, tip, getter, setter)
local function commit() local function commit()
local v = tonumber(eb:GetText()) local v = tonumber(eb:GetText())
if v then -- Spell ids start at 1 -- 0 (or negative) is never a real aura id, and tonumber("0")
-- is truthy, so it has to be rejected explicitly rather than falling through as if it
-- were a valid id. Treated exactly like any other unparsable entry: revert, don't write.
if v and math.floor(v) >= 1 then
eb.bfSet(math.floor(v)) eb.bfSet(math.floor(v))
else else
eb:SetText(tostring(getter())) eb:SetText(tostring(getter()))
@@ -481,30 +484,50 @@ local function BuildPanel()
headR("Thresholds") headR("Thresholds")
-- Keeps a red/yellow threshold pair from inverting (red > yellow would break the colour
-- chain in core/calc.lua's poolColorName/timeColorName -- values below "green" would never
-- reach it, since "red" already claims everything up to its now-higher bound). The slider
-- the user is actively moving wins; its partner is pulled along to match instead of being
-- left crossed. Only refreshes the panel when a clamp actually fired, so an ordinary
-- (non-crossing) drag stays a single write. This is the one place both keys of a pair are
-- ever written from the panel -- there is no slash-command path for these -- so the clamp
-- lives here rather than in a shared config setter.
local function clampPair(loKey, hiKey, movedKey, v)
local d = db()
d[movedKey] = v
if movedKey == loKey and d[hiKey] and d[loKey] > d[hiKey] then
d[hiKey] = d[loKey]
BF.RefreshOptions()
elseif movedKey == hiKey and d[loKey] and d[hiKey] < d[loKey] then
d[loKey] = d[hiKey]
BF.RefreshOptions()
end
end
local poolRed = CreateSlider(panel, "Pool red threshold", 0, 100, 5, "Pool turns red below: %.0f%%", local poolRed = CreateSlider(panel, "Pool red threshold", 0, 100, 5, "Pool turns red below: %.0f%%",
"The threshold bar turns red at or below this fraction of the pool.", "The threshold bar turns red at or below this fraction of the pool.",
function() return (db().poolRed or 0.30) * 100 end, function() return (db().poolRed or 0.30) * 100 end,
function(v) db().poolRed = v / 100 end) function(v) clampPair("poolRed", "poolYellow", "poolRed", v / 100) end)
sliderR(poolRed) sliderR(poolRed)
local poolYellow = CreateSlider(panel, "Pool yellow threshold", 0, 100, 5, "Pool turns green above: %.0f%%", local poolYellow = CreateSlider(panel, "Pool yellow threshold", 0, 100, 5, "Pool turns green above: %.0f%%",
"The threshold bar turns green above this fraction of the pool (yellow in between).", "The threshold bar turns green above this fraction of the pool (yellow in between).",
function() return (db().poolYellow or 0.70) * 100 end, function() return (db().poolYellow or 0.70) * 100 end,
function(v) db().poolYellow = v / 100 end) function(v) clampPair("poolRed", "poolYellow", "poolYellow", v / 100) end)
sliderR(poolYellow) sliderR(poolYellow)
local timeRed = CreateSlider(panel, "Expiry red threshold", 0, BF.BUFFER_DURATION, 0.5, local timeRed = CreateSlider(panel, "Expiry red threshold", 0, BF.BUFFER_DURATION, 0.5,
"Expiry turns red below: %.1fs", "Expiry turns red below: %.1fs",
"The expiry bar turns red once fewer than this many seconds remain.", "The expiry bar turns red once fewer than this many seconds remain.",
function() return db().timeRed or 2.0 end, function() return db().timeRed or 2.0 end,
function(v) db().timeRed = v end) function(v) clampPair("timeRed", "timeYellow", "timeRed", v) end)
sliderR(timeRed) sliderR(timeRed)
local timeYellow = CreateSlider(panel, "Expiry yellow threshold", 0, BF.BUFFER_DURATION, 0.5, local timeYellow = CreateSlider(panel, "Expiry yellow threshold", 0, BF.BUFFER_DURATION, 0.5,
"Expiry turns green above: %.1fs", "Expiry turns green above: %.1fs",
"The expiry bar turns green once more than this many seconds remain (yellow in between).", "The expiry bar turns green once more than this many seconds remain (yellow in between).",
function() return db().timeYellow or 5.0 end, function() return db().timeYellow or 5.0 end,
function(v) db().timeYellow = v end) function(v) clampPair("timeRed", "timeYellow", "timeYellow", v) end)
sliderR(timeYellow) sliderR(timeYellow)
headR("Absorb model") headR("Absorb model")
@@ -609,7 +632,7 @@ local function BuildPanel()
probeBtn:SetWidth(btnW) probeBtn:SetWidth(btnW)
resetBtn:SetWidth(btnW) resetBtn:SetWidth(btnW)
local ver = (GetAddOnMetadata and GetAddOnMetadata("BulwarkFrame", "Version")) or "0.2.0" local ver = (GetAddOnMetadata and GetAddOnMetadata("BulwarkFrame", "Version")) or "0.3.1"
local verFS = panel:CreateFontString("BulwarkFrameOptionsVersion", "OVERLAY", "GameFontNormalSmall") local verFS = panel:CreateFontString("BulwarkFrameOptionsVersion", "OVERLAY", "GameFontNormalSmall")
ApplyFont(verFS, 10) ApplyFont(verFS, 10)
verFS:SetPoint("BOTTOM", panel, "BOTTOM", 0, 6) verFS:SetPoint("BOTTOM", panel, "BOTTOM", 0, 6)