diff --git a/crates/benilla-app/assets/ui/OptionsFrame.xml b/crates/benilla-app/assets/ui/OptionsFrame.xml
index 9619b109..4a74478c 100644
--- a/crates/benilla-app/assets/ui/OptionsFrame.xml
+++ b/crates/benilla-app/assets/ui/OptionsFrame.xml
@@ -1,178 +1,17 @@
-
+
@@ -191,62 +30,17 @@
-
+
-
+
-
+
@@ -1828,13 +1109,9 @@
-
+
-
+
@@ -1891,12 +1162,8 @@
-
+
@@ -1923,29 +1190,11 @@
-
+
@@ -1968,10 +1217,8 @@
-
+
@@ -1989,9 +1236,7 @@
-
+
@@ -2027,18 +1272,9 @@
-
+
@@ -2061,8 +1297,7 @@
-
+
@@ -2079,18 +1314,13 @@
-
+
-
+
@@ -2098,28 +1328,9 @@
-
+
@@ -2129,20 +1340,15 @@
-
+
-
+
@@ -2151,19 +1357,10 @@
-
+
@@ -2198,19 +1395,10 @@
-
+
-
+
-
+
-
+
@@ -2312,8 +1496,7 @@
OptionsCategoryRow_OnLoad(self, "Keybindings", "Keybindings")
-
+
-
+
@@ -2345,13 +1528,8 @@
-
+
@@ -2362,17 +1540,14 @@
-
+
-
+
-
+
-
+
@@ -2439,54 +1592,28 @@
BenillaScroll_SyncBar(this)
-
+
-
+
-
+
-
+
@@ -2504,19 +1631,7 @@
self.invert = 1
-
-
+
@@ -2545,12 +1660,9 @@
OptionsRow_OnLoad(self, "BlockTrades", "Block Trades",
"OPTION_TOOLTIP_BLOCK_TRADES")
-
+
@@ -2566,10 +1678,7 @@
-
+
OptionsRow_OnLoad(self, "autoLootDefault", "Auto Loot")
@@ -2580,16 +1689,7 @@
OptionsRow_OnLoad(self, "mouseInvertPitch", "Invert Mouse",
"OPTION_TOOLTIP_INVERT_MOUSE")
-
+
@@ -2601,31 +1701,10 @@
OptionsSliderRow_Setup(self, 0.5, 1.5, 0.05)
-
-
+
@@ -2641,18 +1720,7 @@
})
-
+
@@ -2663,11 +1731,8 @@
"OPTION_TOOLTIP_FOLLOW_TERRAIN")
-
+
@@ -2678,18 +1743,9 @@
"OPTION_TOOLTIP_HEAD_BOB")
-
+
@@ -2701,10 +1757,9 @@
OptionsSliderRow_Setup(self, 90, 270, 10, "raw")
-
+
@@ -2725,12 +1780,8 @@
"OPTION_TOOLTIP_SMART_PIVOT")
-
+
@@ -2756,15 +1807,9 @@
-
+
@@ -2798,8 +1843,7 @@
OptionsRow_OnLoad(self, "SoundVolume", "Sound Volume",
"OPTION_TOOLTIP_SOUND_VOLUME", 1)
- -- era parentInitializer (search pulls Master in
- -- above a matched child, SettingsPanel.lua l.665)
+ -- Era parentInitializer (SettingsPanel.lua l.665).
self.parentRow = "RowMaster"
@@ -2847,11 +1891,7 @@
self.soundQuirk = 1
-
+
@@ -2863,14 +1903,9 @@
self.soundQuirk = 1
-
+
@@ -2885,23 +1920,9 @@
-
+
@@ -2919,10 +1940,8 @@
OptionsSliderRow_Setup(self, OptionsFrameSliders[1].minValue,
OptionsFrameSliders[1].maxValue,
OptionsFrameSliders[1].valueStep)
- -- era registers its uiscale row CommitFlag.Apply
- -- (Graphics.lua l.684): the one row whose live
- -- write would rescale the very slider mid-drag —
- -- it stages and commits through the Apply button.
+ -- Era CommitFlag.Apply (Graphics.lua l.684): a
+ -- live write would rescale the slider mid-drag.
self.deferred = 1
@@ -2947,42 +1966,24 @@
OptionsRow_OnLoad(self, "WorldDetail", "Environment Detail",
"OPTION_TOOLTIP_ENVIRONMENT_DETAIL")
- -- The stop names are the era preset ladder's (its
- -- quality dropdowns say Low/Medium/High); 1.12's
- -- slider had no stop labels to quote.
+ -- Stop names from the era quality ladder.
OptionsSliderRow_Setup(self, OptionsFrameSliders[3].minValue,
OptionsFrameSliders[3].maxValue,
OptionsFrameSliders[3].valueStep, nil,
{ "Low", "Medium", "High" })
-
+
- -- The default is the reference's own computation
- -- rather than a second copy of the number:
- -- OptionsFrame_SetDefaults displays this row as
- -- `1 - GetCVarDefault("gamma")` (OptionsFrame.lua
- -- l.441-445), so the CVar table stays the single
- -- source and Restore Defaults here lands exactly
- -- where the reference's would. The `or 1` is for a
- -- VM whose host registered nothing (a bare kit),
- -- where the reference would have had a record to
- -- read because its own lookup creates one.
+ -- OptionsFrame_SetDefaults' default (l.441-445);
+ -- `or 1` covers a VM with no CVars.
local gd = tonumber(GetCVarDefault("gamma")) or 1
OptionsNumFuncRow_OnLoad(self, GetGamma, SetGamma,
tostring(1 - gd), "Brightness",
@@ -2992,17 +1993,9 @@
OptionsFrameSliders[6].valueStep, "travel")
-
+
@@ -3011,16 +2004,9 @@
OptionsRow_OnLoad(self, "weatherDensity", "Weather Intensity",
"OPTION_TOOLTIP_WEATHER_DETAIL")
- -- The stop names are OURS, and they name the
- -- reference's own quality table rather than a
- -- borrowed preset ladder: `0x67b870` maps 0/1/2/3
- -- onto the spawn-rate gains {0.1, 0.33, 0.66, 1.0}
- -- in `[0x8680ec]`, so the top stop really is the
- -- full rate and the bottom is a tenth of it. 1.12
- -- labelled no stop on this slider -- it labelled
- -- the two ENDS -- but every slider row in this kit
- -- carries a readout, and "2" is the one thing that
- -- seat could say that means nothing to a player.
+ -- Our stop names for the reference's rates:
+ -- `0x67b870` maps 0 to 3 onto the spawn-rate gains
+ -- {0.1, 0.33, 0.66, 1.0} in `[0x8680ec]`.
OptionsSliderRow_Setup(self, OptionsFrameSliders[9].minValue,
OptionsFrameSliders[9].maxValue,
OptionsFrameSliders[9].valueStep, nil,
@@ -3033,32 +2019,11 @@
- -- Display Mode (1650): MODERN CLASSIC's row, not
- -- 1.12's, because 1627 already gave us modern
- -- Classic's two states and a checkbox could only
- -- name one of them.
- --
- -- Blizzard_SettingsDefinitions_Shared/Graphics.lua
- -- (live, classic AND classic_era, all identical):
- -- a BOOLEAN proxy rendered as a dropdown, with
- -- exactly two entries -- container:Add(true,
- -- VIDEO_OPTIONS_WINDOWED_FULLSCREEN) and
- -- container:Add(false, VIDEO_OPTIONS_WINDOWED).
- -- There is no Fullscreen entry anywhere in it;
- -- 8.0.1 removed the exclusive mode those clients
- -- had, which is the same reason 1627 ships none.
- --
- -- It rides gxWindow, OUR persisted CVar, not the
- -- gxMaximize the modern client uses -- that client
- -- deleted gxWindow entirely and had to move; we
- -- did not, and repointing would orphan every
- -- config.toml already holding the row for nothing.
- -- Polarity is gxWindow's own: "0" is not-windowed,
- -- which 1627 redefined as the borderless window.
- --
- -- Not deferred, for the same reason as Vertical
- -- Sync below: the reference row carries
- -- gxRestart = 1 and ours applies on the click.
+ -- Deviation: modern Classic's two-entry Display
+ -- Mode dropdown (Graphics.lua in
+ -- Blizzard_SettingsDefinitions_Shared), as there
+ -- is no exclusive fullscreen; gxWindow "0" is the
+ -- borderless window. Applies on the click.
OptionsRow_OnLoad(self, "gxWindow", "Display Mode",
"BENILLA_TOOLTIP_DISPLAY_MODE")
OptionsDropdownRow_Setup(self, {
@@ -3073,12 +2038,9 @@
- -- Vertical Sync: 1.12's own Video Options checkbox
- -- 5 (gxVSync), over the window's present mode.
- -- The reference row carries gxRestart = 1; ours
- -- does not and must not be marked deferred --
- -- wgpu swaps the presentation interval live, so
- -- the box takes effect as you click it.
+ -- 1.12's Video Options checkbox 5. Not deferred
+ -- despite its gxRestart = 1: the present mode
+ -- changes live.
OptionsRow_OnLoad(self, "gxVSync", "Vertical Sync",
"OPTION_TOOLTIP_VERTICAL_SYNC")
@@ -3089,33 +2051,11 @@
- -- Render Scale (decision 1639) -- benilla's own
- -- row, no 1.12 counterpart: the reference renders
- -- straight to the backbuffer and has no second
- -- image to size. It CLOSES the page, and it is
- -- the only antialiasing control on it: the
- -- reference's own Multisampling row was pulled
- -- 2026-08-27 (decision 1648, the director's call).
- -- gxMultisample survives as a CVar and $WOW_MSAA
- -- -- what went is the row, because multisampling
- -- cannot touch the alpha-tested cutouts that carry
- -- most of this game's visible aliasing, and above
- -- 100% this row can.
- --
- -- 50-200%, narrower than the CVar's own clamp
- -- (RENDER_SCALE_RANGE, 0.25-4.0). That clamp stops
- -- an absurd value and leaves room for the
- -- supersampling instrument; this is what a player
- -- should be offered, and it is where every engine
- -- puts the same slider.
- --
- -- DEFERRED, and for the reason the flag exists.
- -- Committing live would rebuild the world's render
- -- target on every drag tick -- tens of megabytes,
- -- thirty times across one sweep of the handle.
- -- Staging to Apply makes that exactly one rebuild,
- -- which is the same answer uiScale's row already
- -- reaches for a different reason.
+ -- Deviation: benilla's own row (the reference draws
+ -- to the backbuffer), and no Multisampling row,
+ -- which misses alpha-tested cutouts. Deferred: a
+ -- live write rebuilds the world render target on
+ -- every drag tick.
OptionsRow_OnLoad(self, "renderScale", "Render Scale",
"BENILLA_TOOLTIP_RENDER_SCALE")
OptionsSliderRow_Setup(self, 0.5, 2.0, 0.05)
@@ -3123,16 +2063,9 @@
-
+
for i, name in BENILLA_GRAPHICS_SLIDER_ROWS do
@@ -3146,18 +2079,8 @@
-
+
@@ -3172,12 +2095,10 @@
OptionsGlobalRow_OnLoad(self, "SHOW_COMBAT_TEXT",
"Enable Floating Combat Text", "OPTION_TOOLTIP_SHOW_COMBAT_TEXT")
- self.applyFunc = "CombatText_UpdateOrLoad" -- by NAME, resolved when applied: this file loads before its definer now (1938)
+ self.applyFunc = "CombatText_UpdateOrLoad"
-
+
@@ -3192,7 +2113,7 @@
{ text = "Arc", value = "3" },
})
self.parentRow = "RowCombatText"
- self.applyFunc = "CombatText_UpdateOrLoad" -- by NAME, resolved when applied: this file loads before its definer now (1938)
+ self.applyFunc = "CombatText_UpdateOrLoad"
@@ -3205,7 +2126,7 @@
"Show Low Mana and Health",
"OPTION_TOOLTIP_COMBAT_TEXT_SHOW_LOW_HEALTH_MANA", 1)
self.parentRow = "RowCombatText"
- self.applyFunc = "CombatText_UpdateOrLoad" -- by NAME, resolved when applied: this file loads before its definer now (1938)
+ self.applyFunc = "CombatText_UpdateOrLoad"
@@ -3217,7 +2138,7 @@
OptionsGlobalRow_OnLoad(self, "COMBAT_TEXT_SHOW_AURAS",
"Show Auras", "OPTION_TOOLTIP_COMBAT_TEXT_SHOW_AURAS", 1)
self.parentRow = "RowCombatText"
- self.applyFunc = "CombatText_UpdateOrLoad" -- by NAME, resolved when applied: this file loads before its definer now (1938)
+ self.applyFunc = "CombatText_UpdateOrLoad"
@@ -3229,7 +2150,7 @@
OptionsGlobalRow_OnLoad(self, "COMBAT_TEXT_SHOW_AURA_FADE",
"Show Fading Auras", "OPTION_TOOLTIP_COMBAT_TEXT_SHOW_AURA_FADE", 1)
self.parentRow = "RowCombatText"
- self.applyFunc = "CombatText_UpdateOrLoad" -- by NAME, resolved when applied: this file loads before its definer now (1938)
+ self.applyFunc = "CombatText_UpdateOrLoad"
@@ -3242,7 +2163,7 @@
"Show Combat State",
"OPTION_TOOLTIP_COMBAT_TEXT_SHOW_COMBAT_STATE", 1)
self.parentRow = "RowCombatText"
- self.applyFunc = "CombatText_UpdateOrLoad" -- by NAME, resolved when applied: this file loads before its definer now (1938)
+ self.applyFunc = "CombatText_UpdateOrLoad"
@@ -3255,7 +2176,7 @@
"Show Dodge/Parries/Misses",
"OPTION_TOOLTIP_COMBAT_TEXT_SHOW_DODGE_PARRY_MISS", 1)
self.parentRow = "RowCombatText"
- self.applyFunc = "CombatText_UpdateOrLoad" -- by NAME, resolved when applied: this file loads before its definer now (1938)
+ self.applyFunc = "CombatText_UpdateOrLoad"
@@ -3268,7 +2189,7 @@
"Show Damage Reduction",
"OPTION_TOOLTIP_COMBAT_TEXT_SHOW_RESISTANCES", 1)
self.parentRow = "RowCombatText"
- self.applyFunc = "CombatText_UpdateOrLoad" -- by NAME, resolved when applied: this file loads before its definer now (1938)
+ self.applyFunc = "CombatText_UpdateOrLoad"
@@ -3281,7 +2202,7 @@
"Show Reputation",
"OPTION_TOOLTIP_COMBAT_TEXT_SHOW_REPUTATION", 1)
self.parentRow = "RowCombatText"
- self.applyFunc = "CombatText_UpdateOrLoad" -- by NAME, resolved when applied: this file loads before its definer now (1938)
+ self.applyFunc = "CombatText_UpdateOrLoad"
@@ -3294,7 +2215,7 @@
"Show Reactive Spells and Abilities",
"OPTION_TOOLTIP_COMBAT_TEXT_SHOW_REACTIVES", 1)
self.parentRow = "RowCombatText"
- self.applyFunc = "CombatText_UpdateOrLoad" -- by NAME, resolved when applied: this file loads before its definer now (1938)
+ self.applyFunc = "CombatText_UpdateOrLoad"
@@ -3307,12 +2228,10 @@
"Show Friendly Healer Names",
"OPTION_TOOLTIP_COMBAT_TEXT_SHOW_FRIENDLY_NAMES", 1)
self.parentRow = "RowCombatText"
- self.applyFunc = "CombatText_UpdateOrLoad" -- by NAME, resolved when applied: this file loads before its definer now (1938)
+ self.applyFunc = "CombatText_UpdateOrLoad"
-
+
@@ -3323,7 +2242,7 @@
"Show Combo Points",
"OPTION_TOOLTIP_COMBAT_TEXT_SHOW_COMBO_POINTS", 1)
self.parentRow = "RowCombatText"
- self.applyFunc = "CombatText_UpdateOrLoad" -- by NAME, resolved when applied: this file loads before its definer now (1938)
+ self.applyFunc = "CombatText_UpdateOrLoad"
@@ -3336,7 +2255,7 @@
"Show Energy Gains",
"OPTION_TOOLTIP_COMBAT_TEXT_SHOW_MANA", 1)
self.parentRow = "RowCombatText"
- self.applyFunc = "CombatText_UpdateOrLoad" -- by NAME, resolved when applied: this file loads before its definer now (1938)
+ self.applyFunc = "CombatText_UpdateOrLoad"
@@ -3349,22 +2268,12 @@
"Show Honor Gained",
"OPTION_TOOLTIP_COMBAT_TEXT_SHOW_HONOR_GAINED", 1)
self.parentRow = "RowCombatText"
- self.applyFunc = "CombatText_UpdateOrLoad" -- by NAME, resolved when applied: this file loads before its definer now (1938)
+ self.applyFunc = "CombatText_UpdateOrLoad"
-
+
@@ -3375,12 +2284,8 @@
"OPTION_TOOLTIP_SHOW_DAMAGE")
-
+
@@ -3392,12 +2297,7 @@
self.parentRow = "RowShowDamage"
-
+
@@ -3412,45 +2312,11 @@
-
+
@@ -3517,15 +2383,8 @@
"0", "Show Right ActionBar", "OPTION_TOOLTIP_SHOW_MULTIBAR3")
-
+
@@ -3554,14 +2413,8 @@
OptionsGlobalRow_OnLoad(self, "ALWAYS_SHOW_MULTIBARS",
"Always Show ActionBars", "OPTION_TOOLTIP_ALWAYS_SHOW_MULTIBARS")
- -- A CLICK runs MultiActionBar_UpdateGridVisibility, the
- -- reference's own click arm (UIOptionsFrame.xml:683).
- -- The LOAD arm — which only ever SHOWS, because every hide
- -- is a counted decrement on each well (ActionButton_HideGrid)
- -- and a load-time hide against wells nobody opened would push
- -- the count negative — is the stock file's
- -- VARIABLES_LOADED arm now (UIOptionsFrame.lua l.218-220),
- -- which is why this row carries no `loadFunc` (2115).
+ -- The click arm (UIOptionsFrame.xml:683); the load
+ -- arm is the stock VARIABLES_LOADED one.
self.applyFunc = "MultiActionBar_UpdateGridVisibility"
@@ -3577,47 +2430,17 @@
-
+
-
-
+
@@ -3637,19 +2460,9 @@
self.cvarEvent = "STATUS_BAR_TEXT"
-
+
@@ -3658,17 +2471,11 @@
OptionsGlobalRow_OnLoad(self, "SHOW_TARGET_OF_TARGET",
"Show Target of Target", "OPTION_TOOLTIP_SHOW_TARGET_OF_TARGET")
- self.applyFunc = "TargetofTarget_Update" -- by NAME, resolved when applied: this file loads before its definer now (1938)
+ self.applyFunc = "TargetofTarget_Update"
-
+
@@ -3684,17 +2491,11 @@
{ text = "Party or Raid", value = "4", tip = "OPTION_TOOLTIP_TARGETOFTARGET4" },
{ text = "Always", value = "5", tip = "OPTION_TOOLTIP_TARGETOFTARGET5" },
})
- self.applyFunc = "TargetofTarget_Update" -- by NAME, resolved when applied: this file loads before its definer now (1938)
+ self.applyFunc = "TargetofTarget_Update"
-
+
@@ -3725,12 +2526,7 @@
"Instant Quest Text", "OPTION_TOOLTIP_SHOW_QUEST_FADING")
-
+
@@ -3739,7 +2535,7 @@
OptionsGlobalRow_OnLoad(self, "SHOW_BUFF_DURATIONS",
"Buff Durations", "OPTION_TOOLTIP_SHOW_BUFF_DURATION")
- self.applyFunc = "BuffButtons_UpdatePositions" -- by NAME, resolved when applied: this file loads before its definer now (1938)
+ self.applyFunc = "BuffButtons_UpdatePositions"
@@ -3752,19 +2548,8 @@
"Automatic Quest Tracking", "OPTION_TOOLTIP_AUTO_QUEST_WATCH")
-
+
@@ -3773,39 +2558,23 @@
OptionsRow_OnLoad(self, "profanityFilter", "Profanity Filter",
"OPTION_TOOLTIP_PROFANITY_FILTER")
-
+
-
+
OptionsFuncRow_OnLoad(self, TutorialsEnabled,
BenillaOptionsFrame_SetTutorialsEnabled, "1",
"Show Tutorials", "OPTION_TOOLTIP_SHOW_TUTORIALS")
-
+
@@ -3827,29 +2596,9 @@
-
-
+
@@ -3862,11 +2611,7 @@
-
+
OptionsRow_OnLoad(self, "guildMemberNotify",
"Guild Member Alert",
"OPTION_TOOLTIP_GUILDMEMBER_ALERT")
@@ -3878,17 +2623,12 @@
-
+
OptionsGlobalRow_OnLoad(self, "REMOVE_CHAT_DELAY",
"Remove Chat Hover Delay",
"OPTION_TOOLTIP_REMOVE_CHAT_DELAY")
- self.applyFunc = "ChatFrame_ApplyMouseOverDelay" -- by NAME, resolved when applied: this file loads before its definer now (1938)
+ self.applyFunc = "ChatFrame_ApplyMouseOverDelay"
@@ -3907,13 +2647,7 @@
-
+
OptionsRow_OnLoad(self, "showLootSpam",
"Detailed Loot Information",
"OPTION_TOOLTIP_SHOW_LOOT_SPAM")
@@ -3929,23 +2663,10 @@
"Show Party Chat Bubbles", "OPTION_TOOLTIP_PARTY_CHAT_BUBBLES")
-
+
@@ -3959,28 +2680,10 @@
-
+
@@ -4011,13 +2714,8 @@
OptionsRow_OnLoad(self, "UnitNamePlayer", "Player Names",
"OPTION_TOOLTIP_SHOW_PLAYER_NAMES")
-
+
@@ -4047,18 +2745,9 @@
-
-
+
@@ -4072,15 +2761,8 @@
-
+
@@ -4237,22 +2919,12 @@
-
+
-
+
@@ -4260,28 +2932,13 @@
ScrollFrame_OnLoad()
-
+
FauxScrollFrame_OnVerticalScroll(KEYBINDINGS_ROW_HEIGHT, KeyBindingsPage_Update)
-
+
if not KeyBindingsPage.selected then
ScrollFrameTemplate_OnMouseWheel(arg1)
@@ -4290,11 +2947,8 @@
-
+
if not KeyBindingsPage.selected then
@@ -4303,11 +2957,8 @@
-
+
-
+
@@ -4378,21 +3025,9 @@
-
+
@@ -4405,24 +3040,12 @@
-
+
-
+
@@ -4448,8 +3071,7 @@
-
+
@@ -4460,8 +3082,7 @@
-
+
-
if this:GetText() == "" then
BenillaOptionsFrameSearchBoxInstructions:Show()
@@ -4501,8 +3121,7 @@
-
+
-
+
-
+
BenillaOptionsFrame_UpdateScale()
BenillaOptionsFrame_SelectCategory(this.selectedCategory or "Controls")
if UpdateMicroButtons then UpdateMicroButtons() end
-
+
BenillaOptionsFrameSearchBox:SetText("")
OptionsPage_DiscardPending()
@@ -4548,70 +3159,16 @@
-
+
diff --git a/crates/benilla-app/src/cvars.rs b/crates/benilla-app/src/cvars.rs
index a0cf095b..72870728 100644
--- a/crates/benilla-app/src/cvars.rs
+++ b/crates/benilla-app/src/cvars.rs
@@ -210,6 +210,13 @@ pub(crate) fn registered_pairs() -> impl Iterator