@@ -104,6 +104,13 @@ namespace
104104 return width;
105105 }
106106
107+ int QuantizeVolumePercent (float & value)
108+ {
109+ const int iPercent = std::clamp (static_cast <int >(value * 100 .0f + 0 .5f ), 0 , 100 );
110+ value = iPercent / 100 .0f ;
111+ return iPercent;
112+ }
113+
107114 void FinalizeSliderRow (float tabWidth, CGUIScrollBar* slider, CGUILabel* valueLabel, float preferredWidth, float labelSpacing = kSliderLabelSpacing ,
108115 CGUILabel* textLabel = nullptr )
109116 {
@@ -430,9 +437,48 @@ CSettings::CSettings()
430437{
431438 ResetGuiPointers ();
432439
433- CGameSettings* gameSettings = CCore::GetSingleton ().GetGame ()->GetSettings ();
434- m_fRadioVolume = (float )gameSettings->GetRadioVolume () / 64 .0f ;
435- m_fSFXVolume = (float )gameSettings->GetSFXVolume () / 64 .0f ;
440+ CClientVariables& clientVars = CClientVariables::GetSingleton ();
441+ CGameSettings* gameSettings = CCore::GetSingleton ().GetGame ()->GetSettings ();
442+
443+ float fRadioVolume = 0 .0f ;
444+ float fSFXVolume = 0 .0f ;
445+
446+ // Keep exact slider values in CVARs. Fall back to reconstructed values for
447+ // one-time migration when those keys do not exist yet.
448+ if (clientVars.Exists (" radiovolume" ) && clientVars.Exists (" sfxvolume" ))
449+ {
450+ CVARS_GET (" radiovolume" , fRadioVolume );
451+ CVARS_GET (" sfxvolume" , fSFXVolume );
452+ }
453+ else
454+ {
455+ // GTA stores radio/SFX as values already multiplied by master volume.
456+ // The UI sliders represent the unscaled channel volumes, so recover them
457+ // by dividing by the persisted master value during startup.
458+ const float fMasterVolume = std::max (0 .0f , std::min (CVARS_GET_VALUE<float >(" mastervolume" ), 1 .0f ));
459+ const float fStoredRadioVolume = (float )gameSettings->GetRadioVolume () / 64 .0f ;
460+ const float fStoredSFXVolume = (float )gameSettings->GetSFXVolume () / 64 .0f ;
461+
462+ if (fMasterVolume > 0 .0001f )
463+ {
464+ fRadioVolume = fStoredRadioVolume / fMasterVolume ;
465+ fSFXVolume = fStoredSFXVolume / fMasterVolume ;
466+ }
467+ else
468+ {
469+ // If master was zero we cannot recover hidden channel values.
470+ fRadioVolume = fStoredRadioVolume ;
471+ fSFXVolume = fStoredSFXVolume ;
472+ }
473+
474+ CVARS_SET (" radiovolume" , fRadioVolume );
475+ CVARS_SET (" sfxvolume" , fSFXVolume );
476+ }
477+
478+ m_fRadioVolume = std::max (0 .0f , std::min (fRadioVolume , 1 .0f ));
479+ m_fSFXVolume = std::max (0 .0f , std::min (fSFXVolume , 1 .0f ));
480+ QuantizeVolumePercent (m_fRadioVolume);
481+ QuantizeVolumePercent (m_fSFXVolume);
436482
437483 m_iMaxAnisotropic = g_pDeviceState->AdapterState .MaxAnisotropicSetting ;
438484 m_bBrowserListsChanged = false ;
@@ -5446,20 +5492,30 @@ bool CSettings::OnMasterVolumeChanged(CGUIElement* pElement)
54465492
54475493bool CSettings::OnRadioVolumeChanged (CGUIElement* pElement)
54485494{
5449- int iVolume = m_pAudioRadioVolume->GetScrollPosition () * 100 .0f ;
5495+ float fVolume = m_pAudioRadioVolume->GetScrollPosition ();
5496+ int iVolume = QuantizeVolumePercent (fVolume );
54505497 m_pLabelRadioVolumeValue->SetText (SString (" %i%%" , iVolume).c_str ());
54515498
5452- SetRadioVolume (m_pAudioRadioVolume->GetScrollPosition ());
5499+ if (std::abs (m_pAudioRadioVolume->GetScrollPosition () - fVolume ) > 0 .0001f )
5500+ m_pAudioRadioVolume->SetScrollPosition (fVolume );
5501+
5502+ CVARS_SET (" radiovolume" , fVolume );
5503+ SetRadioVolume (fVolume );
54535504
54545505 return true ;
54555506}
54565507
54575508bool CSettings::OnSFXVolumeChanged (CGUIElement* pElement)
54585509{
5459- int iVolume = m_pAudioSFXVolume->GetScrollPosition () * 100 .0f ;
5510+ float fVolume = m_pAudioSFXVolume->GetScrollPosition ();
5511+ int iVolume = QuantizeVolumePercent (fVolume );
54605512 m_pLabelSFXVolumeValue->SetText (SString (" %i%%" , iVolume).c_str ());
54615513
5462- SetSFXVolume (m_pAudioSFXVolume->GetScrollPosition ());
5514+ if (std::abs (m_pAudioSFXVolume->GetScrollPosition () - fVolume ) > 0 .0001f )
5515+ m_pAudioSFXVolume->SetScrollPosition (fVolume );
5516+
5517+ CVARS_SET (" sfxvolume" , fVolume );
5518+ SetSFXVolume (fVolume );
54635519
54645520 return true ;
54655521}
0 commit comments