fix(ui): OP6 rework — six range captions, un-invert Sound enabled flags, five font faces
Fixes all three MUST-FIX findings from the OP6 REJECT review (docs/research/2026-08-11-op6-review.md) plus its SHOULD-FIXes and NOTEs. M1 — the "retail ships zero range captions" claim was a Binary Ninja constant-folding artifact (the same class the header-string globals a few lines above already worked around). The six SetSliderLabel call sites byte-decode to reads of runtime-filled ID_Graphics_Value_* globals, not immediate zeros (PE-byte-verified against the PDB-paired acclient.exe, independently re-derived in this session, not just re-asserted from the review). ConfigOptionsPageController.BuildSliderRow gained optional rangeLowKey/rangeHighKey parameters wired for all six idx6 sliders (Camera Stiffness Soft/Hard, Adjustment Speed Slow/Fast, FOV Narrow/Wide, Screen Brightness Dark/Bright, Graphics Performance Speed/Detail, Degrade Distance Close/Far) via the same SetRangeLabel mechanism OP5's Chat opacity sliders already established. Mouse Look Sensitivity (idx3) correctly stays uncaptioned — the one genuine SetSliderLabel omission. Class doc corrected; gate-script lines 535/653-equivalent corrected in place. M2 — the three Sound "Disabled" toggles were semantically inverted: SoundManager::effect_sounds_enabled/ambient_sounds_enabled/ interface_sounds_enabled are all compiled = 1 in .data, and UserPreferences::RegisterPreference binds the checkbox's boolean value DIRECTLY onto those enabled-sense statics — checked-by-default means enabled-by-default, not disabled. AudioSettings.SfxDisabled/AmbientDisabled/ InterfaceDisabled renamed to SfxEnabled/AmbientEnabled/InterfaceEnabled (fresh JSON keys — the rejected slice's keys never shipped in an accepted build); RuntimeSettingsStartupTargets.ApplyAudio now computes effective volume through the extracted, independently-unit-tested pure function ComputeEffectiveCategoryVolumes (enabled ? slider : 0f). This closes the blast radius the review flagged: a missing key in an EXISTING settings.json now falls back to AudioSettings.Default, which is enabled=true, so a fresh launch is audible, not muted. AP-199's wording and gate-script step 6 corrected; the enshrined-inversion test rewritten to assert the correct default and a new SettingsStore test pins the legacy-file fallback path. M3 — UI_ChatFontFace now ships all five of retail's authored choices (Arial, CourierNew, PalatinoLinotype, Tahoma, TimesNewRoman — a fixed compile-time array at gmClient::InitUIPreferences, PE-byte-verified present verbatim in .rdata, not a per-machine runtime enumeration as the rejected slice's comment claimed). Default index 2 (PalatinoLinotype) now indexes a real entry. S1 — Bind() now emits the sixth trailing AddSeperator retail's own InitOptions ends with (0x0049E80D), matching retail's 39-item ListBox (6 headers + 6 separators + 27 option-widget-rows) instead of 38. S2 — Screen Brightness gets its own DisplaySettings.ScreenBrightness field ([-1,1], default 0) instead of overloading Gamma, which has a different unit system (default 1.0, legacy [0.5,2.0] slider) and its own live Settings-panel consumer. S3 — UiScrollbar and UiMenu gained a settable TooltipText surfaced through GetTooltipText (UiButton's existing pattern). Every slider and menu row's own interactive widget (not just toggle/trio rows) now carries retail's "<label>_Help" tooltip, verified as a universal suffix convention across every AttachPreference site touched by this tab. S4 — "800x600" added to DisplaySettings.AvailableResolutions: a genuine retail display mode (Device::ForceDisplayResolution(1,0x320,0x258) at startup) and the Config tab's own byte-verified Resolution row default, not an invented preset. Defaults now lands on a highlighted, re-selectable dropdown entry instead of an orphaned value. S5 — four new/extended tests: ComputeEffectiveCategoryVolumes gets a dedicated pure-function value assertion (Theory + a default-profile-is- audible Fact) in RuntimeSettingsControllerTests, closing the "only event order was asserted" gap that let M2 ship; a label/choice-key conformance table in ConfigOptionsPageControllerTests enumerates every key this tab queries (traced directly from the fixed code paths, not guessed) and fails on an invented OR a dropped key; a per-row DefaultValue pin asserts every row's default against the retail literal directly, independent of the underlying settings-record defaults; and the S1 separator fix gets its own 39-item stacked-ListBox count pin. NOTEs — AP-198's row count was always ten (its own enumeration never said nine); the commit-message inconsistency N1 flagged is reconciled in both the row and the section-summary line, and its Screen Brightness sub-clause now matches S2. N2: Bind() now reads the scrollbar id from UiTemplateListBox.ScrollbarElementId (dat property 0x72) instead of a hardcoded constant. N3 (batch Defaults writes) and N4 (AfterApply on Config-tab entry, needs no action) are left as recorded — out of this rework's scope per the review's own disposition. Full Release suite: 13,125 passed / 4 skipped / 0 failed (baseline 13,117/4/0 — net +8 tests added, 0 regressions, 0 removed). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
4996974cfd
commit
472525b99e
11 changed files with 774 additions and 168 deletions
|
|
@ -71,6 +71,7 @@ public sealed class SettingsStore
|
|||
Quality: ReadQuality (disp, "quality", d.Quality),
|
||||
ParticleRange: ReadParticleRange(
|
||||
disp, "particleRange", d.ParticleRange),
|
||||
ScreenBrightness: ReadFloat(disp, "screenBrightness", d.ScreenBrightness),
|
||||
AutomaticDegrades: ReadBool (disp, "automaticDegrades", d.AutomaticDegrades),
|
||||
GraphicsPerformance: ReadFloat(disp, "graphicsPerformance", d.GraphicsPerformance),
|
||||
DegradeDistance: ReadFloat(disp, "degradeDistance", d.DegradeDistance),
|
||||
|
|
@ -120,9 +121,16 @@ public sealed class SettingsStore
|
|||
Sfx: ReadFloat(audio, "sfx", d.Sfx),
|
||||
Ambient: ReadFloat(audio, "ambient", d.Ambient),
|
||||
SoundFeatures: ReadInt (audio, "soundFeatures", d.SoundFeatures),
|
||||
SfxDisabled: ReadBool (audio, "sfxDisabled", d.SfxDisabled),
|
||||
AmbientDisabled: ReadBool (audio, "ambientDisabled", d.AmbientDisabled),
|
||||
InterfaceDisabled: ReadBool (audio, "interfaceDisabled", d.InterfaceDisabled),
|
||||
// OP6 rework (review M2): fresh enabled-sense key names — the
|
||||
// rejected slice's "sfxDisabled"/"ambientDisabled"/
|
||||
// "interfaceDisabled" keys never shipped in an accepted
|
||||
// build, so there is no legacy key to migrate. A missing key
|
||||
// (including every pre-OP6 settings.json) falls back to
|
||||
// AudioSettings.Default, which is now enabled=true — sound
|
||||
// ON, matching retail.
|
||||
SfxEnabled: ReadBool (audio, "sfxEnabled", d.SfxEnabled),
|
||||
AmbientEnabled: ReadBool (audio, "ambientEnabled", d.AmbientEnabled),
|
||||
InterfaceEnabled: ReadBool (audio, "interfaceEnabled", d.InterfaceEnabled),
|
||||
InterfaceVolume: ReadFloat(audio, "interfaceVolume", d.InterfaceVolume),
|
||||
PlaySoundOnlyWhenActive: ReadBool (audio, "playSoundOnlyWhenActive", d.PlaySoundOnlyWhenActive));
|
||||
}
|
||||
|
|
@ -651,6 +659,7 @@ public sealed class SettingsStore
|
|||
["particleRange"] = d.ParticleRange.ToString(),
|
||||
["quality"] = d.Quality.ToString(),
|
||||
["resolution"] = d.Resolution,
|
||||
["screenBrightness"] = d.ScreenBrightness,
|
||||
["showFps"] = d.ShowFps,
|
||||
["textureFiltering"] = d.TextureFiltering,
|
||||
["vsync"] = d.VSync,
|
||||
|
|
@ -671,13 +680,13 @@ public sealed class SettingsStore
|
|||
=> new(StringComparer.Ordinal)
|
||||
{
|
||||
["ambient"] = a.Ambient,
|
||||
["ambientDisabled"] = a.AmbientDisabled,
|
||||
["interfaceDisabled"] = a.InterfaceDisabled,
|
||||
["ambientEnabled"] = a.AmbientEnabled,
|
||||
["interfaceEnabled"] = a.InterfaceEnabled,
|
||||
["interfaceVolume"] = a.InterfaceVolume,
|
||||
["master"] = a.Master,
|
||||
["playSoundOnlyWhenActive"] = a.PlaySoundOnlyWhenActive,
|
||||
["sfx"] = a.Sfx,
|
||||
["sfxDisabled"] = a.SfxDisabled,
|
||||
["sfxEnabled"] = a.SfxEnabled,
|
||||
["soundFeatures"] = a.SoundFeatures,
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue