Please disclose if your mod was created primarily using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of UniversalVolumeController v1.0.8
UniversalVolumeController.dll
Decompiled 2 hours agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("UniversalVolumeController")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+489d69b9104fb88ad02a93746b3350734bd3d41e")] [assembly: AssemblyProduct("UniversalVolumeController")] [assembly: AssemblyTitle("UniversalVolumeController")] [assembly: AssemblyVersion("1.0.0.0")] [BepInPlugin("com.marij.universalvolumecontroller", "Universal Volume Controller", "1.0.0")] public class UniversalVolumeControllerPlugin : BaseUnityPlugin { private enum SoundCategory { Item, Environment, Other } [CompilerGenerated] private sealed class <DiscoEndOfFrameEnforceLoop>d__99 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public UniversalVolumeControllerPlugin <>4__this; private WaitForEndOfFrame <wait>5__2; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <DiscoEndOfFrameEnforceLoop>d__99(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <wait>5__2 = null; <>1__state = -2; } private bool MoveNext() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown int num = <>1__state; UniversalVolumeControllerPlugin universalVolumeControllerPlugin = <>4__this; if (num != 0) { if (num != 1) { return false; } <>1__state = -1; if (universalVolumeControllerPlugin._isAppFocused && universalVolumeControllerPlugin._realtimeRefreshEnabled) { try { VolumeRuntime.RefreshDiscoSourcesLate(); } catch { } } } else { <>1__state = -1; <wait>5__2 = new WaitForEndOfFrame(); } <>2__current = <wait>5__2; <>1__state = 1; return true; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <SplitLowercaseToken>d__130 : IEnumerable<string>, IEnumerable, IEnumerator<string>, IEnumerator, IDisposable { private int <>1__state; private string <>2__current; private int <>l__initialThreadId; private string token; public string <>3__token; private string <suffix>5__2; private List<string>.Enumerator <>7__wrap2; string IEnumerator<string>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <SplitLowercaseToken>d__130(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 5) { try { } finally { <>m__Finally1(); } } <suffix>5__2 = null; <>7__wrap2 = default(List<string>.Enumerator); <>1__state = -2; } private bool MoveNext() { try { switch (<>1__state) { default: return false; case 0: { <>1__state = -1; if (token.Length < 7 || token.Any((char c) => !char.IsLetter(c) || char.IsUpper(c))) { <>2__current = token; <>1__state = 1; return true; } int length = token.Length; int[] array = Enumerable.Repeat(-1, length + 1).ToArray(); array[0] = 0; for (int i = 0; i < length; i++) { if (array[i] == -1) { continue; } for (int j = i + 1; j <= length; j++) { string item = token.Substring(i, j - i); if (SplitWords.Contains(item) && array[j] == -1) { array[j] = i; } } } if (array[length] == -1) { string[] array2 = new string[10] { "container", "teleporter", "teleporta", "breakerbox", "door", "box", "bees", "crawler", "horn", "ball" }; for (int k = 0; k < array2.Length; k++) { <suffix>5__2 = array2[k]; if (token.Length > <suffix>5__2.Length + 2 && token.EndsWith(<suffix>5__2, StringComparison.Ordinal)) { string text = token.Substring(0, token.Length - <suffix>5__2.Length); if (SplitWords.Contains(text) || text.Length >= 3) { <>2__current = text; <>1__state = 2; return true; } } <suffix>5__2 = null; } <>2__current = token; <>1__state = 4; return true; } List<string> list = new List<string>(); for (int num = length; num > 0; num = array[num]) { int num2 = array[num]; list.Add(token.Substring(num2, num - num2)); } list.Reverse(); <>7__wrap2 = list.GetEnumerator(); <>1__state = -3; break; } case 1: <>1__state = -1; return false; case 2: <>1__state = -1; <>2__current = <suffix>5__2; <>1__state = 3; return true; case 3: <>1__state = -1; return false; case 4: <>1__state = -1; return false; case 5: <>1__state = -3; break; } if (<>7__wrap2.MoveNext()) { string current = <>7__wrap2.Current; <>2__current = current; <>1__state = 5; return true; } <>m__Finally1(); <>7__wrap2 = default(List<string>.Enumerator); return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; ((IDisposable)<>7__wrap2).Dispose(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<string> IEnumerable<string>.GetEnumerator() { <SplitLowercaseToken>d__130 <SplitLowercaseToken>d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; <SplitLowercaseToken>d__ = this; } else { <SplitLowercaseToken>d__ = new <SplitLowercaseToken>d__130(0); } <SplitLowercaseToken>d__.token = <>3__token; return <SplitLowercaseToken>d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<string>)this).GetEnumerator(); } } public const string PluginGuid = "com.marij.universalvolumecontroller"; public const string PluginName = "Universal Volume Controller"; public const string PluginVersion = "1.0.0"; internal static UniversalVolumeControllerPlugin Instance = null; internal static ManualLogSource Log = null; private const int MinPercent = 1; private const int MaxPercent = 100; private Harmony _harmony; private bool _uiVisible; private Rect _windowRect; private bool _windowRectInitialized; private bool _draggingWindow; private Vector2 _windowDragOffset; private bool _resizingWindow; private float _resizeStartHeight; private float _resizeStartMouseY; private bool _settingsVisible; private int _selectedTab; private Vector2 _scroll; private string _searchQuery = string.Empty; private bool _isAppFocused = true; private bool _cursorStateCaptured; private bool _previousCursorVisible; private CursorLockMode _previousCursorLockState; private bool _realtimeRefreshEnabled = true; private bool _loggedRealtimeFailure; private Coroutine _discoEndOfFrameEnforceCoroutine; private float _nextRealtimeRefreshAt; private float _nextRealtimeScanAt; private readonly object _lock = new object(); private readonly Dictionary<string, ConfigEntry<int>> _itemEntries = new Dictionary<string, ConfigEntry<int>>(); private readonly Dictionary<string, ConfigEntry<int>> _environmentEntries = new Dictionary<string, ConfigEntry<int>>(); private readonly Dictionary<string, ConfigEntry<int>> _otherEntries = new Dictionary<string, ConfigEntry<int>>(); private readonly Dictionary<string, int> _lastItemNonZeroPercent = new Dictionary<string, int>(); private readonly Dictionary<string, int> _lastEnvironmentNonZeroPercent = new Dictionary<string, int>(); private readonly Dictionary<string, int> _lastOtherNonZeroPercent = new Dictionary<string, int>(); private readonly Dictionary<string, string> _aliases = new Dictionary<string, string>(); private ConfigEntry<bool> _categoryEnableTipTarget; private string _categoryEnableTipText = string.Empty; private float _categoryEnableTipUntil; private int _lastGlobalNonZeroPercent = 100; internal ConfigEntry<bool> ModEnabled; internal ConfigEntry<int> GlobalPercent; internal ConfigEntry<bool> ItemSoundsEnabled; internal ConfigEntry<bool> EnvironmentSoundsEnabled; internal ConfigEntry<bool> OtherSoundsEnabled; internal ConfigEntry<int> ThemeColorIndex; internal ConfigEntry<int> OpacityPercent; internal ConfigEntry<bool> DebugAudioDiscovery; internal ConfigEntry<bool> DebugAudioResolution; internal ConfigEntry<bool> DebugInfoByDefault; private bool _stylesInitialized; private Texture2D _bgTex; private Texture2D _panelTex; private Texture2D _accentTex; private Texture2D _buttonTex; private Texture2D _buttonActiveTex; private Texture2D _sliderTex; private Texture2D _sliderThumbTex; private GUIStyle _windowStyle; private GUIStyle _headerStyle; private GUIStyle _labelStyle; private GUIStyle _buttonStyle; private GUIStyle _tabStyle; private GUIStyle _tabActiveStyle; private GUIStyle _tabDimStyle; private GUIStyle _toggleStyle; private GUIStyle _sliderStyle; private GUIStyle _sliderThumbStyle; private GUIStyle _searchFieldStyle; private GUIStyle _scrollViewStyle; private GUIStyle _vScrollbarStyle; private GUIStyle _vScrollbarThumbStyle; private GUIStyle _valueStyle; private GUIStyle _rowBoxStyle; private Texture2D _tabDimTex; private Texture2D _scrollbarTrackTex; private Texture2D _searchBgTex; private int _appliedThemeIndex = -1; private int _appliedOpacityPercent = -1; private float _nextDiscoProbeAt; private bool _sceneHasDiscoBall; private bool _dumpedDiscoAudioGraph; private bool _debugAudioPlayback; private bool _indepthDebugAudioPlayback; private bool _infoDebugAudioPlayback; private const float WindowDragStripHeight = 28f; private const float WindowResizeGripHeight = 20f; private const float CategoryEnableTipDuration = 5f; private static readonly HashSet<string> SplitWords = new HashSet<string> { "air", "horn", "clown", "disco", "ball", "double", "winged", "bird", "ship", "main", "entrance", "exit", "fire", "apparatus", "beacon", "camera", "helmet", "turret", "mine", "door", "battery", "flashlight", "boombox", "walkie", "talkie", "generator", "warning", "big", "breaker", "box", "canvas", "crawler", "docile", "locust", "bees", "container", "teleporter", "teleport", "teleporta", "player", "players", "light", "speaker", "music", "terminal", "monitor", "switch", "lever", "coil", "head", "mask", "hose", "metal" }; private static readonly string[] EnvironmentKeywords = new string[24] { "ambience", "ambient", "outside", "outdoor", "wind", "rain", "storm", "thunder", "forest", "cave", "factory", "birds", "nature", "ocean", "water", "drip", "reverb", "ship", "hangar", "thruster", "engine", "landing", "turbulence", "door" }; private static readonly string[] OtherKeywords = new string[11] { "terminal", "intercom", "alarm", "speaker", "jingle", "theme", "ui", "menu", "button", "diagetic", "nondiagetic" }; private static readonly string[] ThemeNames = new string[10] { "Orange", "Crimson", "Scarlet", "Amber", "Lime", "Cyan", "Blue", "Indigo", "Magenta", "Rose" }; private static readonly Color[] ThemeColors = (Color[])(object)new Color[10] { new Color(1f, 0.35f, 0f, 1f), new Color(0.85f, 0.08f, 0.16f, 1f), new Color(0.96f, 0.18f, 0.08f, 1f), new Color(0.92f, 0.62f, 0.08f, 1f), new Color(0.45f, 0.8f, 0.12f, 1f), new Color(0.12f, 0.78f, 0.86f, 1f), new Color(0.22f, 0.5f, 0.92f, 1f), new Color(0.42f, 0.33f, 0.92f, 1f), new Color(0.8f, 0.24f, 0.82f, 1f), new Color(0.95f, 0.3f, 0.52f, 1f) }; private void Awake() { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Expected O, but got Unknown //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Expected O, but got Unknown //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; ModEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable or disable this mod entirely."); GlobalPercent = ((BaseUnityPlugin)this).Config.Bind<int>("General", "GlobalPercent", 100, new ConfigDescription("Global volume percentage.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>())); ItemSoundsEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Categories", "ItemSoundsEnabled", true, "Enable Item Sounds category."); EnvironmentSoundsEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Categories", "EnvironmentSoundsEnabled", false, "Enable Environment category."); OtherSoundsEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Categories", "OtherSoundsEnabled", false, "Enable Other sounds category."); ThemeColorIndex = ((BaseUnityPlugin)this).Config.Bind<int>("UI", "ThemeColorIndex", 0, new ConfigDescription("Theme color index (0-9).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 9), Array.Empty<object>())); OpacityPercent = ((BaseUnityPlugin)this).Config.Bind<int>("UI", "OpacityPercent", 80, new ConfigDescription("Menu opacity in percent (25-100).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(25, 100), Array.Empty<object>())); DebugAudioDiscovery = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "AudioDiscoveryLogs", false, "Log newly tracked audio sources and resolved keys."); DebugAudioResolution = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "AudioResolutionLogs", false, "Log category/key/multiplier decisions for tracked audio sources."); DebugInfoByDefault = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "PlaybackInfoByDefault", false, "Enable additional playback info logs by default for F5 audio debugging."); _debugAudioPlayback = false; _indepthDebugAudioPlayback = false; _infoDebugAudioPlayback = DebugInfoByDefault.Value; if (GlobalPercent.Value > 0) { _lastGlobalNonZeroPercent = Mathf.Clamp(GlobalPercent.Value, 1, 100); } BuildDefaultAliases(); _harmony = new Harmony("com.marij.universalvolumecontroller"); _harmony.PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Universal Volume Controller loaded. Toggle UI with F10."); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Volume changes are client-side only (local AudioSource volume).\n"); ((BaseUnityPlugin)this).Logger.LogInfo((object)"F9+F10 prints all active audio sources. F5 toggles playback logs, LeftAlt+F5 toggles in-depth logs, LeftCtrl+F5 toggles info logs, LeftShift+F5 prints managed sound groups."); if (DebugAudioDiscovery.Value || DebugAudioResolution.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)$"[Debug] discovery={DebugAudioDiscovery.Value} resolution={DebugAudioResolution.Value} items={ItemSoundsEnabled.Value} env={EnvironmentSoundsEnabled.Value} other={OtherSoundsEnabled.Value} opacity={OpacityPercent.Value} theme={ThemeColorIndex.Value}"); } _discoEndOfFrameEnforceCoroutine = ((MonoBehaviour)this).StartCoroutine(DiscoEndOfFrameEnforceLoop()); } private void OnDestroy() { SetMenuVisible(visible: false); _harmony.UnpatchSelf(); if (_discoEndOfFrameEnforceCoroutine != null) { ((MonoBehaviour)this).StopCoroutine(_discoEndOfFrameEnforceCoroutine); _discoEndOfFrameEnforceCoroutine = null; } if ((Object)(object)_bgTex != (Object)null) { Object.Destroy((Object)(object)_bgTex); Object.Destroy((Object)(object)_panelTex); Object.Destroy((Object)(object)_accentTex); Object.Destroy((Object)(object)_buttonTex); Object.Destroy((Object)(object)_buttonActiveTex); Object.Destroy((Object)(object)_sliderTex); Object.Destroy((Object)(object)_sliderThumbTex); Object.Destroy((Object)(object)_tabDimTex); Object.Destroy((Object)(object)_scrollbarTrackTex); Object.Destroy((Object)(object)_searchBgTex); } } private void Update() { if (!_isAppFocused) { return; } Keyboard current = Keyboard.current; if (IsAudioDumpComboPressed(current)) { bool includeAllSources = current != null && (((ButtonControl)current.leftCtrlKey).isPressed || ((ButtonControl)current.rightCtrlKey).isPressed); DumpAllActiveAudioSources(includeHierarchy: false, includeExtraInfo: false, includeAllSources); return; } if (current != null && ((ButtonControl)current.f10Key).wasPressedThisFrame) { SetMenuVisible(!_uiVisible); } HandleAudioDebugHotkeys(current); if (_uiVisible && current != null && ((ButtonControl)current.escapeKey).wasPressedThisFrame) { SetMenuVisible(visible: false); } if (_realtimeRefreshEnabled && Time.unscaledTime >= _nextRealtimeRefreshAt) { _nextRealtimeRefreshAt = Time.unscaledTime + 0.08f; try { VolumeRuntime.RefreshKnownSources(); } catch (Exception arg) { if (!_loggedRealtimeFailure) { _loggedRealtimeFailure = true; ((BaseUnityPlugin)this).Logger.LogError((object)$"Realtime refresh hit an exception and will retry automatically: {arg}"); } } } if (_realtimeRefreshEnabled && Time.unscaledTime >= _nextRealtimeScanAt) { _nextRealtimeScanAt = Time.unscaledTime + 1f; try { VolumeRuntime.ScanActiveSources(); } catch (Exception arg2) { if (!_loggedRealtimeFailure) { _loggedRealtimeFailure = true; ((BaseUnityPlugin)this).Logger.LogError((object)$"Realtime scan hit an exception and will retry automatically: {arg2}"); } } } if (_uiVisible) { Cursor.lockState = (CursorLockMode)0; Cursor.visible = true; } } private void LateUpdate() { if (!_isAppFocused || !_realtimeRefreshEnabled) { return; } try { VolumeRuntime.RefreshDiscoSourcesLate(); } catch { } } [IteratorStateMachine(typeof(<DiscoEndOfFrameEnforceLoop>d__99))] private IEnumerator DiscoEndOfFrameEnforceLoop() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <DiscoEndOfFrameEnforceLoop>d__99(0) { <>4__this = this }; } private void HandleAudioDebugHotkeys(Keyboard keyboard) { if (keyboard != null && ((ButtonControl)keyboard.f5Key).wasPressedThisFrame) { bool flag = ((ButtonControl)keyboard.leftAltKey).isPressed || ((ButtonControl)keyboard.rightAltKey).isPressed; bool flag2 = ((ButtonControl)keyboard.leftCtrlKey).isPressed || ((ButtonControl)keyboard.rightCtrlKey).isPressed; if (((ButtonControl)keyboard.leftShiftKey).isPressed || ((ButtonControl)keyboard.rightShiftKey).isPressed) { PrintAllManagedSoundGroups(); } else if (flag) { ToggleIndepthAudioDebug(); } else if (flag2) { ToggleInfoAudioDebug(); } else if (flag) { ToggleIndepthAudioDebug(); } else { ToggleAudioDebug(); } } } private static bool IsAudioDumpComboPressed(Keyboard keyboard) { if (keyboard == null) { return false; } bool num = ((ButtonControl)keyboard.f9Key).isPressed && ((ButtonControl)keyboard.f10Key).isPressed; bool flag = ((ButtonControl)keyboard.f9Key).wasPressedThisFrame || ((ButtonControl)keyboard.f10Key).wasPressedThisFrame; return num && flag; } private void ToggleAudioDebug() { _debugAudioPlayback = !_debugAudioPlayback; if (!_debugAudioPlayback) { _indepthDebugAudioPlayback = false; } ((BaseUnityPlugin)this).Logger.LogInfo((object)("[AudioDebug] playback logs " + (_debugAudioPlayback ? "enabled" : "disabled"))); } private void ToggleIndepthAudioDebug() { _debugAudioPlayback = !_debugAudioPlayback; _indepthDebugAudioPlayback = _debugAudioPlayback; _infoDebugAudioPlayback = _debugAudioPlayback; ((BaseUnityPlugin)this).Logger.LogInfo((object)("[AudioDebug] in-depth playback logs " + (_debugAudioPlayback ? "enabled" : "disabled"))); } private void ToggleInfoAudioDebug() { _infoDebugAudioPlayback = !_infoDebugAudioPlayback; ((BaseUnityPlugin)this).Logger.LogInfo((object)("[AudioDebug] informational playback logs " + (_infoDebugAudioPlayback ? "enabled" : "disabled"))); } private void DumpAllActiveAudioSources(bool includeHierarchy, bool includeExtraInfo, bool includeAllSources) { AudioSource[] array = Object.FindObjectsOfType<AudioSource>(true); ((BaseUnityPlugin)this).Logger.LogInfo((object)" "); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"[AudioDump] Active audio snapshot started. sources={array.Length} includeHierarchy={includeHierarchy} includeExtraInfo={includeExtraInfo} includeAllSources={includeAllSources}"); int num = 0; int num2 = 0; foreach (AudioSource val in array) { if (!((Object)(object)val == (Object)null)) { bool num3 = (Object)(object)((Component)val).gameObject != (Object)null && ((Component)val).gameObject.activeInHierarchy; bool isPlaying = val.isPlaying; if (num3 && isPlaying) { num++; } if (num3 && isPlaying) { num2 += LogAudioDumpLine(val, includeHierarchy, includeExtraInfo); } } } if (includeAllSources) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"[AudioDump] Full source list follows (including non-playing sources)"); foreach (AudioSource val2 in array) { if (!((Object)(object)val2 == (Object)null)) { bool num4 = (Object)(object)((Component)val2).gameObject != (Object)null && ((Component)val2).gameObject.activeInHierarchy; bool isPlaying2 = val2.isPlaying; if (!(num4 && isPlaying2)) { num2 += LogAudioDumpLine(val2, includeHierarchy, includeExtraInfo); } } } } ((BaseUnityPlugin)this).Logger.LogInfo((object)$"[AudioDump] Active audio snapshot finished. activeAndPlaying={num}/{array.Length} printed={num2}"); ((BaseUnityPlugin)this).Logger.LogInfo((object)" "); } private int LogAudioDumpLine(AudioSource source, bool includeHierarchy, bool includeExtraInfo) { if ((Object)(object)source == (Object)null) { return 0; } bool flag = (Object)(object)((Component)source).gameObject != (Object)null && ((Component)source).gameObject.activeInHierarchy; bool isPlaying = source.isPlaying; string text = (((Object)(object)((Component)source).gameObject != (Object)null) ? ((Object)((Component)source).gameObject).name : "(none)"); string text2 = (((Object)(object)source.clip != (Object)null) ? ((Object)source.clip).name : "(null)"); string text3 = (((Object)(object)((Component)source).transform != (Object)null && (Object)(object)((Component)source).transform.root != (Object)null) ? ((Object)((Component)source).transform.root).name : "(none)"); string text4 = (((Object)(object)source.outputAudioMixerGroup != (Object)null) ? ((Object)source.outputAudioMixerGroup).name : "(none)"); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"[AudioDump] id={((Object)source).GetInstanceID()} name={text} clip={text2} playing={isPlaying} active={flag} enabled={((Behaviour)source).enabled} root={text3} volume={source.volume:0.000} pitch={source.pitch:0.000} mute={source.mute} loop={source.loop}"); int num = 1; if (includeExtraInfo) { ((BaseUnityPlugin)this).Logger.LogInfo((object)$"[AudioDumpInfo] playOnAwake={source.playOnAwake} spatialBlend={source.spatialBlend:0.00} priority={source.priority} time={source.time:0.000} timeSamples={source.timeSamples} doppler={source.dopplerLevel:0.00} spread={source.spread:0.00} mixer={text4}"); num++; } if (includeHierarchy) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("[AudioDumpPath] " + GetHierarchyPath(((Component)source).transform))); num++; } return num; } private void PrintAllManagedSoundGroups() { lock (_lock) { ((BaseUnityPlugin)this).Logger.LogInfo((object)" "); ((BaseUnityPlugin)this).Logger.LogInfo((object)"[AudioDebug] Printing all currently managed sound groups..."); PrintManagedGroup("Item", _itemEntries, _lastItemNonZeroPercent); PrintManagedGroup("Environment", _environmentEntries, _lastEnvironmentNonZeroPercent); PrintManagedGroup("Other", _otherEntries, _lastOtherNonZeroPercent); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"[AudioDebug] GlobalPercent={GlobalPercent.Value}% ModEnabled={ModEnabled.Value} Item={ItemSoundsEnabled.Value} Environment={EnvironmentSoundsEnabled.Value} Other={OtherSoundsEnabled.Value}"); ((BaseUnityPlugin)this).Logger.LogInfo((object)"[AudioDebug] Finished printing managed sound groups."); ((BaseUnityPlugin)this).Logger.LogInfo((object)" "); } } private void PrintManagedGroup(string label, Dictionary<string, ConfigEntry<int>> entries, Dictionary<string, int> lastNonZero) { ((BaseUnityPlugin)this).Logger.LogInfo((object)$"[AudioDebug] {label} groups: {entries.Count}"); foreach (KeyValuePair<string, ConfigEntry<int>> item in entries.OrderBy<KeyValuePair<string, ConfigEntry<int>>, string>((KeyValuePair<string, ConfigEntry<int>> p) => p.Key, StringComparer.OrdinalIgnoreCase)) { int value; int num = (lastNonZero.TryGetValue(item.Key, out value) ? value : item.Value.Value); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"[AudioDebug] - {label}/{item.Key} = {item.Value.Value}% lastNonZero={num}%"); } } internal void LogPlaybackEvent(string methodName, AudioSource source, AudioClip clip, float? volumeScale = null, Vector3? position = null) { //IL_0061: Unknown result type (might be due to invalid IL or missing references) if (_debugAudioPlayback) { string text = (((Object)(object)clip != (Object)null) ? ((Object)clip).name : "(null)"); string text2 = (((Object)(object)source != (Object)null && (Object)(object)((Component)source).gameObject != (Object)null) ? ((Object)((Component)source).gameObject).name : "(none)"); string text3 = (position.HasValue ? $" pos={position.Value}" : string.Empty); string text4 = (volumeScale.HasValue ? $" scale={volumeScale.Value:0.###}" : string.Empty); if (!_indepthDebugAudioPlayback) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("[AudioDebug] " + methodName + " source=" + text2 + " clip=" + text + text4 + text3)); } else { string text5 = (((Object)(object)source != (Object)null) ? GetHierarchyPath(((Component)source).transform) : "(none)"); ((BaseUnityPlugin)this).Logger.LogInfo((object)("[AudioDebug] " + methodName + " source=" + text2 + " path=" + text5 + " clip=" + text + text4 + text3)); } if (_infoDebugAudioPlayback && (Object)(object)source != (Object)null) { string text6 = (((Object)(object)source.outputAudioMixerGroup != (Object)null) ? ((Object)source.outputAudioMixerGroup).name : "(none)"); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"[AudioDebugInfo] enabled={((Behaviour)source).enabled} active={((Component)source).gameObject.activeInHierarchy} mute={source.mute} loop={source.loop} playOnAwake={source.playOnAwake} spatialBlend={source.spatialBlend:0.00} volume={source.volume:0.000} mixer={text6}"); } } } private void OnApplicationFocus(bool hasFocus) { _isAppFocused = hasFocus; if (!hasFocus) { SetMenuVisible(visible: false); return; } _nextRealtimeRefreshAt = Time.unscaledTime + 0.1f; _nextRealtimeScanAt = Time.unscaledTime + 0.5f; } private void OnApplicationPause(bool paused) { _isAppFocused = !paused; if (paused) { SetMenuVisible(visible: false); } } private void OnGUI() { //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Unknown result type (might be due to invalid IL or missing references) if (_uiVisible) { EnsureStyles(); float num = Mathf.Min(980f, (float)Screen.width - 24f); float num2 = Mathf.Min(680f, (float)Screen.height - 24f); float num3 = num2 * 2f; if (!_windowRectInitialized) { _windowRect = new Rect(((float)Screen.width - num) * 0.5f, ((float)Screen.height - num2) * 0.5f, num, num2); _windowRectInitialized = true; } else { ((Rect)(ref _windowRect)).width = num; ((Rect)(ref _windowRect)).height = Mathf.Clamp(((Rect)(ref _windowRect)).height, num2, num3); } HandleWindowDrag(_windowRect); HandleWindowResize(_windowRect, num2, num3); ((Rect)(ref _windowRect)).x = Mathf.Clamp(((Rect)(ref _windowRect)).x, 12f, Mathf.Max(12f, (float)Screen.width - ((Rect)(ref _windowRect)).width - 12f)); ((Rect)(ref _windowRect)).y = Mathf.Clamp(((Rect)(ref _windowRect)).y, 12f, Mathf.Max(12f, (float)Screen.height - 80f)); Rect windowRect = _windowRect; GUI.Box(windowRect, GUIContent.none, _windowStyle); GUI.Box(new Rect(((Rect)(ref windowRect)).x + 12f, ((Rect)(ref windowRect)).y + ((Rect)(ref windowRect)).height - 8f, ((Rect)(ref windowRect)).width - 24f, 4f), GUIContent.none); GUILayout.BeginArea(new Rect(((Rect)(ref windowRect)).x + 12f, ((Rect)(ref windowRect)).y + 10f, ((Rect)(ref windowRect)).width - 24f, ((Rect)(ref windowRect)).height - 20f)); GUILayout.Label("Universal Volume Controller", _headerStyle, Array.Empty<GUILayoutOption>()); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); DrawTabButton("Item Sounds", 0); DrawTabButton("Environment", 1); DrawTabButton("Other", 2); GUILayout.FlexibleSpace(); if (GUILayout.Button("Settings", _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(130f), GUILayout.Height(34f) })) { _settingsVisible = !_settingsVisible; } if (GUILayout.Button("X", _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(44f), GUILayout.Height(34f) })) { SetMenuVisible(visible: false); } GUILayout.EndHorizontal(); if (_settingsVisible) { DrawSettingsPanel(); GUILayout.EndArea(); return; } GUILayout.Space(8f); DrawMasterControls(); GUILayout.Space(8f); DrawActiveTab(); GUILayout.EndArea(); } } private void HandleWindowDrag(Rect windowRect) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Invalid comparison between Unknown and I4 //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Invalid comparison between Unknown and I4 //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Invalid comparison between Unknown and I4 Event current = Event.current; if (current != null) { Rect val = default(Rect); ((Rect)(ref val))..ctor(((Rect)(ref windowRect)).x + 12f, ((Rect)(ref windowRect)).y + 8f, ((Rect)(ref windowRect)).width - 24f, 28f); if ((int)current.type == 0 && current.button == 0 && ((Rect)(ref val)).Contains(current.mousePosition)) { _draggingWindow = true; _windowDragOffset = current.mousePosition - new Vector2(((Rect)(ref _windowRect)).x, ((Rect)(ref _windowRect)).y); current.Use(); } else if (_draggingWindow && (int)current.type == 3) { ((Rect)(ref _windowRect)).position = current.mousePosition - _windowDragOffset; current.Use(); } else if (_draggingWindow && ((int)current.type == 1 || (int)current.rawType == 1)) { _draggingWindow = false; current.Use(); } } } private void HandleWindowResize(Rect windowRect, float minHeight, float maxHeight) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Invalid comparison between Unknown and I4 //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Invalid comparison between Unknown and I4 //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Invalid comparison between Unknown and I4 Event current = Event.current; if (current != null) { Rect val = default(Rect); ((Rect)(ref val))..ctor(((Rect)(ref windowRect)).x + 12f, ((Rect)(ref windowRect)).y + ((Rect)(ref windowRect)).height - 20f, ((Rect)(ref windowRect)).width - 24f, 26f); if ((int)current.type == 0 && current.button == 0 && ((Rect)(ref val)).Contains(current.mousePosition)) { _resizingWindow = true; _resizeStartHeight = ((Rect)(ref _windowRect)).height; _resizeStartMouseY = current.mousePosition.y; current.Use(); } else if (_resizingWindow && (int)current.type == 3) { float num = current.mousePosition.y - _resizeStartMouseY; ((Rect)(ref _windowRect)).height = Mathf.Clamp(_resizeStartHeight + num, minHeight, maxHeight); current.Use(); } else if (_resizingWindow && ((int)current.type == 1 || (int)current.rawType == 1)) { _resizingWindow = false; current.Use(); } } } private void DrawMasterControls() { //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) GUILayout.BeginVertical(_rowBoxStyle, Array.Empty<GUILayoutOption>()); DrawToggleButtonRow("Mod Enabled", ModEnabled); DrawToggleButtonRow("Item Sounds Enabled", ItemSoundsEnabled); DrawToggleButtonRow("Environment Category Enabled", EnvironmentSoundsEnabled); DrawToggleButtonRow("Other Category Enabled", OtherSoundsEnabled); GUILayout.BeginHorizontal(_rowBoxStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(38f) }); GUILayout.Label("Search", _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(160f) }); GUI.SetNextControlName("UniversalVolumeController_SearchBox"); string text = GUILayout.TextField(_searchQuery, _searchFieldStyle, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Height(30f), GUILayout.ExpandWidth(true) }); if (string.IsNullOrWhiteSpace(text) && GUI.GetNameOfFocusedControl() != "UniversalVolumeController_SearchBox") { Rect lastRect = GUILayoutUtility.GetLastRect(); GUI.Label(new Rect(((Rect)(ref lastRect)).x + 8f, ((Rect)(ref lastRect)).y + 4f, ((Rect)(ref lastRect)).width - 8f, ((Rect)(ref lastRect)).height - 4f), "Search sounds...", _valueStyle); } if (!string.Equals(text, _searchQuery, StringComparison.Ordinal)) { _searchQuery = text; _scroll = Vector2.zero; } if (GUILayout.Button("Clear", _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(90f), GUILayout.Height(30f) })) { _searchQuery = string.Empty; _scroll = Vector2.zero; } GUILayout.EndHorizontal(); DrawGlobalPercentRow(); GUILayout.EndVertical(); } private void DrawSettingsPanel() { GUILayout.BeginVertical(_rowBoxStyle, Array.Empty<GUILayoutOption>()); GUILayout.Label("Settings", _labelStyle, Array.Empty<GUILayoutOption>()); GUILayout.Label("Theme Color", _valueStyle, Array.Empty<GUILayoutOption>()); for (int i = 0; i < 2; i++) { GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); for (int j = 0; j < 5; j++) { int num = i * 5 + j; if (num < ThemeNames.Length) { GUIStyle val = ((ThemeColorIndex.Value == num) ? _tabActiveStyle : _buttonStyle); if (GUILayout.Button(ThemeNames[num], val, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(150f), GUILayout.Height(30f) })) { ThemeColorIndex.Value = num; ((BaseUnityPlugin)this).Config.Save(); ApplyThemeNow(); } } } GUILayout.EndHorizontal(); } GUILayout.Space(6f); GUILayout.BeginHorizontal(_rowBoxStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(44f) }); GUILayout.Label("Opacity", _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(220f) }); int num2 = Mathf.Clamp(OpacityPercent.Value, 25, 100); int num3 = Mathf.RoundToInt(GUILayout.HorizontalSlider((float)num2, 25f, 100f, _sliderStyle, _sliderThumbStyle, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(420f), GUILayout.Height(22f) })); if (num3 != num2) { OpacityPercent.Value = num3; ((BaseUnityPlugin)this).Config.Save(); ApplyThemeNow(); } GUILayout.Label($"{num2}%", _valueStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(78f) }); GUILayout.EndHorizontal(); GUILayout.EndVertical(); } private void DrawActiveTab() { //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) SoundCategory categoryByTab = GetCategoryByTab(_selectedTab); Dictionary<string, ConfigEntry<int>> dictionaryByCategory = GetDictionaryByCategory(categoryByTab); bool flag = IsCategoryEnabled(categoryByTab); GUILayout.BeginVertical(_rowBoxStyle, Array.Empty<GUILayoutOption>()); GUILayout.Label(GetCategoryTitle(categoryByTab), _labelStyle, Array.Empty<GUILayoutOption>()); if (!flag) { GUILayout.Label(GetCategoryTitle(categoryByTab) + " is disabled. Enable its category toggle above to apply volume changes.", _valueStyle, Array.Empty<GUILayoutOption>()); } List<string> list; lock (_lock) { list = (from k in dictionaryByCategory.Keys where MatchesSearch(k) orderby k select k).ToList(); } GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); if (GUILayout.Button("Mute All", _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(140f), GUILayout.Height(34f) })) { if (!flag) { ShowEnableCategoryTip(categoryByTab); } else { SetCategoryMuteState(categoryByTab, dictionaryByCategory, mute: true); } } if (GUILayout.Button("Unmute All", _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(160f), GUILayout.Height(34f) })) { if (!flag) { ShowEnableCategoryTip(categoryByTab); } else { SetCategoryMuteState(categoryByTab, dictionaryByCategory, mute: false); } } GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); GUILayout.Space(6f); _scroll = GUILayout.BeginScrollView(_scroll, false, true, GUIStyle.none, _vScrollbarStyle, _scrollViewStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandHeight(true) }); if (list.Count == 0) { GUILayout.Label("No sounds found for this tab with current search.", _valueStyle, Array.Empty<GUILayoutOption>()); GUILayout.EndScrollView(); GUILayout.EndVertical(); return; } foreach (string item in list) { ConfigEntry<int> value; lock (_lock) { dictionaryByCategory.TryGetValue(item, out value); } if (value != null) { DrawCategoryPercentRow(categoryByTab, item, value, flag); } } GUILayout.EndScrollView(); GUILayout.EndVertical(); } private void DrawGlobalPercentRow() { GUILayout.BeginHorizontal(_rowBoxStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(44f) }); GUILayout.Label("Global", _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(220f) }); int value = GlobalPercent.Value; int num = Mathf.Clamp(value, 0, 100); int num2 = Mathf.RoundToInt(GUILayout.HorizontalSlider((float)num, 0f, 100f, _sliderStyle, _sliderThumbStyle, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Height(22f), GUILayout.Width(420f) })); if (num2 != num) { GlobalPercent.Value = num2; if (num2 > 0) { _lastGlobalNonZeroPercent = Mathf.Clamp(num2, 1, 100); } ((BaseUnityPlugin)this).Config.Save(); ApplyVolumeRefreshNow(); } bool flag = value <= 0; GUILayout.Label(flag ? "MUTE" : $"{value}%", _valueStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(78f) }); if (GUILayout.Button(flag ? "Unmute" : "Mute", _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(84f), GUILayout.Height(30f) })) { if (flag) { GlobalPercent.Value = Mathf.Clamp(_lastGlobalNonZeroPercent, 1, 100); } else { _lastGlobalNonZeroPercent = Mathf.Clamp(value, 1, 100); GlobalPercent.Value = 0; } ((BaseUnityPlugin)this).Config.Save(); ApplyVolumeRefreshNow(); } GUILayout.EndHorizontal(); } private void DrawCategoryPercentRow(SoundCategory category, string key, ConfigEntry<int> entry, bool categoryEnabled) { GUILayout.BeginHorizontal(_rowBoxStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(44f) }); GUILayout.Label(ToDisplayName(key), _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(220f) }); int num = Mathf.Clamp(entry.Value, 0, 100); int num2 = Mathf.RoundToInt(GUILayout.HorizontalSlider((float)num, 0f, 100f, _sliderStyle, _sliderThumbStyle, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Height(22f), GUILayout.Width(420f) })); if (num2 != num) { if (!categoryEnabled) { ShowEnableCategoryTip(category); } else { entry.Value = num2; if (num2 > 0) { RememberLastNonZero(category, key, num2); } ((BaseUnityPlugin)this).Config.Save(); ApplyVolumeRefreshNow(); } } bool flag = entry.Value <= 0; GUILayout.Label(flag ? "MUTE" : $"{entry.Value}%", _valueStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(78f) }); if (GUILayout.Button(flag ? "Unmute" : "Mute", _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(84f), GUILayout.Height(30f) })) { if (!categoryEnabled) { ShowEnableCategoryTip(category); } else { if (flag) { entry.Value = GetLastNonZero(category, key); } else { RememberLastNonZero(category, key, entry.Value); entry.Value = 0; } ((BaseUnityPlugin)this).Config.Save(); ApplyVolumeRefreshNow(); } } GUILayout.EndHorizontal(); } private void SetCategoryMuteState(SoundCategory category, Dictionary<string, ConfigEntry<int>> dictionary, bool mute) { lock (_lock) { foreach (KeyValuePair<string, ConfigEntry<int>> item in dictionary) { if (mute) { if (item.Value.Value > 0) { RememberLastNonZero(category, item.Key, item.Value.Value); } item.Value.Value = 0; } else { item.Value.Value = GetLastNonZero(category, item.Key); } } } ((BaseUnityPlugin)this).Config.Save(); ApplyVolumeRefreshNow(); } private void ApplyVolumeRefreshNow() { try { VolumeRuntime.RefreshKnownSources(); } catch { } } private void RememberLastNonZero(SoundCategory category, string key, int value) { if (value > 0) { int value2 = Mathf.Clamp(value, 1, 100); (category switch { SoundCategory.Environment => _lastEnvironmentNonZeroPercent, SoundCategory.Item => _lastItemNonZeroPercent, _ => _lastOtherNonZeroPercent, })[key] = value2; } } private int GetLastNonZero(SoundCategory category, string key) { if ((category switch { SoundCategory.Environment => _lastEnvironmentNonZeroPercent, SoundCategory.Item => _lastItemNonZeroPercent, _ => _lastOtherNonZeroPercent, }).TryGetValue(key, out var value) && value > 0) { return Mathf.Clamp(value, 1, 100); } return 100; } private void SetMenuVisible(bool visible) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) if (!visible) { _draggingWindow = false; _resizingWindow = false; } if (_uiVisible == visible) { return; } if (!visible) { _settingsVisible = false; } _uiVisible = visible; if (visible) { _previousCursorVisible = Cursor.visible; _previousCursorLockState = Cursor.lockState; _cursorStateCaptured = true; Cursor.lockState = (CursorLockMode)0; Cursor.visible = true; ApplyPlayerControlLock(locked: true); } else { if (_cursorStateCaptured) { Cursor.visible = _previousCursorVisible; Cursor.lockState = _previousCursorLockState; _cursorStateCaptured = false; } ApplyPlayerControlLock(locked: false); } } private void ApplyPlayerControlLock(bool locked) { object localPlayerController = GetLocalPlayerController(); if (localPlayerController != null) { SetBoolIfExists(localPlayerController, "disableMoveInput", locked); SetBoolIfExists(localPlayerController, "disableLookInput", locked); SetBoolIfExists(localPlayerController, "isTypingChat", locked); } } private object GetLocalPlayerController() { Type type = AccessTools.TypeByName("GameNetworkManager"); if (type != null) { object obj = AccessTools.Property(type, "Instance")?.GetValue(null) ?? AccessTools.Field(type, "Instance")?.GetValue(null); if (obj != null) { object obj2 = AccessTools.Field(type, "localPlayerController")?.GetValue(obj) ?? AccessTools.Property(type, "localPlayerController")?.GetValue(obj); if (obj2 != null) { return obj2; } } } Type type2 = AccessTools.TypeByName("StartOfRound"); if (type2 != null) { object obj3 = AccessTools.Property(type2, "Instance")?.GetValue(null) ?? AccessTools.Field(type2, "Instance")?.GetValue(null); if (obj3 != null) { object obj4 = AccessTools.Field(type2, "localPlayerController")?.GetValue(obj3) ?? AccessTools.Property(type2, "localPlayerController")?.GetValue(obj3); if (obj4 != null) { return obj4; } } } return null; } private static void SetBoolIfExists(object target, string fieldName, bool value) { FieldInfo fieldInfo = AccessTools.Field(target.GetType(), fieldName); if (fieldInfo != null && fieldInfo.FieldType == typeof(bool)) { fieldInfo.SetValue(target, value); return; } PropertyInfo propertyInfo = AccessTools.Property(target.GetType(), fieldName); if (propertyInfo != null && propertyInfo.CanWrite && propertyInfo.PropertyType == typeof(bool)) { propertyInfo.SetValue(target, value); } } private static void InvokeIfExists(object target, string methodName) { MethodInfo method = target.GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null); if (method != null && method.GetParameters().Length == 0) { method.Invoke(target, null); } } private static string ToDisplayName(string value) { if (string.IsNullOrWhiteSpace(value)) { return "Unknown"; } string text = Regex.Replace(Regex.Replace(Regex.Replace(Regex.Replace(value.Trim().Replace("_", " ").Replace("-", " "), "([a-z])([A-Z])", "$1 $2"), "([A-Za-z])([0-9])", "$1 $2"), "([0-9])([A-Za-z])", "$1 $2"), "\\s+", " ").Trim(); List<string> list = new List<string>(); string[] array = text.Split(' '); foreach (string text2 in array) { if (string.IsNullOrWhiteSpace(text2)) { continue; } foreach (string item in SplitLowercaseToken(text2.ToLowerInvariant())) { list.Add(UppercaseFirst(item)); } } if (list.Count != 0) { return string.Join(" ", list); } return "Unknown"; } [IteratorStateMachine(typeof(<SplitLowercaseToken>d__130))] private static IEnumerable<string> SplitLowercaseToken(string token) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <SplitLowercaseToken>d__130(-2) { <>3__token = token }; } private static string UppercaseFirst(string word) { if (string.IsNullOrEmpty(word)) { return word; } if (word.Length == 1) { return char.ToUpperInvariant(word[0]).ToString(); } return char.ToUpperInvariant(word[0]) + word.Substring(1).ToLowerInvariant(); } private bool MatchesSearch(string rawKey) { if (string.IsNullOrWhiteSpace(_searchQuery)) { return true; } string text = _searchQuery.Trim(); if (text.Length == 0) { return true; } string text2 = ToDisplayName(rawKey); if (rawKey.IndexOf(text, StringComparison.OrdinalIgnoreCase) < 0) { return text2.IndexOf(text, StringComparison.OrdinalIgnoreCase) >= 0; } return true; } private bool TabHasSearchMatches(int tab) { if (string.IsNullOrWhiteSpace(_searchQuery)) { return true; } SoundCategory categoryByTab = GetCategoryByTab(tab); Dictionary<string, ConfigEntry<int>> dictionaryByCategory = GetDictionaryByCategory(categoryByTab); lock (_lock) { return dictionaryByCategory.Keys.Any(MatchesSearch); } } private void DrawTabButton(string title, int index) { bool flag = TabHasSearchMatches(index); GUIStyle val = ((_selectedTab == index) ? _tabActiveStyle : (flag ? _tabStyle : _tabDimStyle)); if (GUILayout.Button(title, val, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(220f), GUILayout.Height(38f) })) { _settingsVisible = false; _selectedTab = index; } } private void DrawToggleButtonRow(string label, ConfigEntry<bool> entry) { //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) GUILayout.BeginHorizontal(_rowBoxStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(38f) }); GUILayout.Label(label, _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(320f) }); if (GUILayout.Button(entry.Value ? "On" : "Off", _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(84f), GUILayout.Height(30f) })) { entry.Value = !entry.Value; ((BaseUnityPlugin)this).Config.Save(); } Rect lastRect = GUILayoutUtility.GetLastRect(); if (_categoryEnableTipTarget == entry && Time.unscaledTime <= _categoryEnableTipUntil) { GUI.Label(new Rect(((Rect)(ref lastRect)).x - 270f, ((Rect)(ref lastRect)).y + 4f, 260f, Mathf.Max(22f, ((Rect)(ref lastRect)).height)), _categoryEnableTipText + " ->", _valueStyle); } GUILayout.EndHorizontal(); } private void ShowEnableCategoryTip(SoundCategory category) { ConfigEntry<bool> categoryToggleEntry = GetCategoryToggleEntry(category); if (categoryToggleEntry != null) { _categoryEnableTipTarget = categoryToggleEntry; _categoryEnableTipText = "Enable " + GetCategoryTitle(category) + " above"; _categoryEnableTipUntil = Time.unscaledTime + 5f; } } private ConfigEntry<bool> GetCategoryToggleEntry(SoundCategory category) { return (ConfigEntry<bool>)(category switch { SoundCategory.Item => ItemSoundsEnabled, SoundCategory.Environment => EnvironmentSoundsEnabled, _ => OtherSoundsEnabled, }); } private SoundCategory GetCategoryByTab(int tab) { return tab switch { 0 => SoundCategory.Item, 1 => SoundCategory.Environment, _ => SoundCategory.Other, }; } private Dictionary<string, ConfigEntry<int>> GetDictionaryByCategory(SoundCategory category) { return category switch { SoundCategory.Item => _itemEntries, SoundCategory.Environment => _environmentEntries, _ => _otherEntries, }; } private bool IsCategoryEnabled(SoundCategory category) { return category switch { SoundCategory.Item => ItemSoundsEnabled.Value, SoundCategory.Environment => EnvironmentSoundsEnabled.Value, _ => OtherSoundsEnabled.Value, }; } private static string GetCategoryTitle(SoundCategory category) { return category switch { SoundCategory.Item => "Item Sounds", SoundCategory.Environment => "Environment", _ => "Other", }; } private void EnsureStyles() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Expected O, but got Unknown //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Expected O, but got Unknown //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Expected O, but got Unknown //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Expected O, but got Unknown //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Expected O, but got Unknown //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Expected O, but got Unknown //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Expected O, but got Unknown //IL_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_01f8: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Expected O, but got Unknown //IL_022e: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Unknown result type (might be due to invalid IL or missing references) //IL_026c: Unknown result type (might be due to invalid IL or missing references) //IL_0276: Expected O, but got Unknown //IL_0290: Unknown result type (might be due to invalid IL or missing references) //IL_029a: Expected O, but got Unknown //IL_02a5: Unknown result type (might be due to invalid IL or missing references) //IL_02af: Expected O, but got Unknown //IL_02d9: Unknown result type (might be due to invalid IL or missing references) //IL_02e3: Expected O, but got Unknown //IL_02ee: Unknown result type (might be due to invalid IL or missing references) //IL_02f8: Expected O, but got Unknown //IL_0317: Unknown result type (might be due to invalid IL or missing references) //IL_0340: Unknown result type (might be due to invalid IL or missing references) //IL_0362: Unknown result type (might be due to invalid IL or missing references) //IL_036c: Expected O, but got Unknown //IL_0377: Unknown result type (might be due to invalid IL or missing references) //IL_0381: Expected O, but got Unknown //IL_039c: Unknown result type (might be due to invalid IL or missing references) //IL_03a6: Expected O, but got Unknown //IL_03c1: Unknown result type (might be due to invalid IL or missing references) //IL_03cb: Expected O, but got Unknown //IL_03d5: Unknown result type (might be due to invalid IL or missing references) //IL_03df: Expected O, but got Unknown //IL_03e9: Unknown result type (might be due to invalid IL or missing references) //IL_03f3: Expected O, but got Unknown if (_stylesInitialized) { ApplyThemeNow(); return; } _windowStyle = new GUIStyle(GUI.skin.box); _windowStyle.border = new RectOffset(2, 2, 2, 2); _headerStyle = new GUIStyle(GUI.skin.label); _headerStyle.fontSize = 36; _headerStyle.alignment = (TextAnchor)4; _headerStyle.normal.textColor = new Color(1f, 0.4f, 0.05f, 1f); _headerStyle.fontStyle = (FontStyle)1; _labelStyle = new GUIStyle(GUI.skin.label); _labelStyle.fontSize = 22; _labelStyle.normal.textColor = new Color(1f, 0.92f, 0.86f, 1f); _valueStyle = new GUIStyle(_labelStyle); _valueStyle.fontSize = 18; _valueStyle.alignment = (TextAnchor)4; _buttonStyle = new GUIStyle(GUI.skin.button); _buttonStyle.normal.textColor = Color.white; _buttonStyle.fontSize = 20; _buttonStyle.margin = new RectOffset(4, 4, 4, 4); _tabStyle = new GUIStyle(_buttonStyle); _tabStyle.fontSize = 22; _tabActiveStyle = new GUIStyle(_tabStyle); _tabActiveStyle.normal.textColor = new Color(0.12f, 0.02f, 0f, 1f); _tabDimStyle = new GUIStyle(_tabStyle); _tabDimStyle.normal.textColor = new Color(0.78f, 0.58f, 0.52f, 1f); _toggleStyle = new GUIStyle(GUI.skin.toggle); _toggleStyle.fontSize = 20; _toggleStyle.normal.textColor = new Color(1f, 0.9f, 0.82f, 1f); _toggleStyle.onNormal.textColor = new Color(1f, 0.9f, 0.82f, 1f); _sliderStyle = new GUIStyle(GUI.skin.horizontalSlider); _sliderStyle.fixedHeight = 20f; _sliderStyle.margin = new RectOffset(6, 6, 8, 8); _sliderThumbStyle = new GUIStyle(GUI.skin.horizontalSliderThumb); _sliderThumbStyle.fixedWidth = 20f; _sliderThumbStyle.fixedHeight = 20f; _sliderThumbStyle.margin = new RectOffset(0, 0, 0, 0); _searchFieldStyle = new GUIStyle(GUI.skin.textField); _searchFieldStyle.normal.textColor = new Color(1f, 0.92f, 0.86f, 1f); _searchFieldStyle.focused.textColor = new Color(1f, 0.92f, 0.86f, 1f); _searchFieldStyle.fontSize = 18; _scrollViewStyle = new GUIStyle(GUI.skin.scrollView); _vScrollbarStyle = new GUIStyle(GUI.skin.verticalScrollbar); _vScrollbarStyle.fixedWidth = 14f; _vScrollbarThumbStyle = new GUIStyle(GUI.skin.verticalScrollbarThumb); _vScrollbarThumbStyle.fixedWidth = 14f; _rowBoxStyle = new GUIStyle(GUI.skin.box); _rowBoxStyle.margin = new RectOffset(2, 2, 2, 2); _rowBoxStyle.padding = new RectOffset(8, 8, 6, 6); ApplyThemeNow(); _stylesInitialized = true; } private void ApplyThemeNow() { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: Unknown result type (might be due to invalid IL or missing references) //IL_0208: Unknown result type (might be due to invalid IL or missing references) //IL_0216: Unknown result type (might be due to invalid IL or missing references) //IL_0224: Unknown result type (might be due to invalid IL or missing references) //IL_0232: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_0244: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Unknown result type (might be due to invalid IL or missing references) //IL_0268: Unknown result type (might be due to invalid IL or missing references) //IL_0276: Unknown result type (might be due to invalid IL or missing references) //IL_0284: Unknown result type (might be due to invalid IL or missing references) //IL_02ac: Unknown result type (might be due to invalid IL or missing references) //IL_02be: Unknown result type (might be due to invalid IL or missing references) //IL_02d0: Unknown result type (might be due to invalid IL or missing references) //IL_033a: Unknown result type (might be due to invalid IL or missing references) //IL_03a4: Unknown result type (might be due to invalid IL or missing references) //IL_041f: Unknown result type (might be due to invalid IL or missing references) //IL_048c: Unknown result type (might be due to invalid IL or missing references) int num = Mathf.Clamp(ThemeColorIndex.Value, 0, ThemeColors.Length - 1); int num2 = Mathf.Clamp(OpacityPercent.Value, 25, 100); if (num != _appliedThemeIndex || num2 != _appliedOpacityPercent) { _appliedThemeIndex = num; _appliedOpacityPercent = num2; Color val = ThemeColors[num]; float num3 = (float)num2 / 100f; Color val2 = new Color(0.07f, 0.05f, 0.07f, 1f); Color color = Color.Lerp(val2, val, 0.18f); color.a = 0.9f * num3; Color color2 = Color.Lerp(val2, val, 0.28f); color2.a = 0.95f * num3; Color color3 = Color.Lerp(val2, val, 0.4f); color3.a = 0.98f * num3; Color color4 = Color.Lerp(val, Color.white, 0.12f); color4.a = 1f * num3; Color color5 = Color.Lerp(val2, val, 0.34f); color5.a = 0.96f * num3; Color color6 = Color.Lerp(val2, val, 0.16f); color6.a = 0.86f * num3; Color color7 = Color.Lerp(val2, val, 0.24f); color7.a = 1f * num3; Color color8 = Color.Lerp(val2, val, 0.14f); color8.a = 1f * num3; float num4 = Mathf.Clamp01(num3 * 0.95f); Color textColor = default(Color); ((Color)(ref textColor))..ctor(val.r, val.g, val.b, num4); Color textColor2 = default(Color); ((Color)(ref textColor2))..ctor(1f, 0.96f, 0.94f, num4); Color textColor3 = default(Color); ((Color)(ref textColor3))..ctor(0.84f, 0.76f, 0.74f, num4); ReplaceTexture(ref _bgTex, color); ReplaceTexture(ref _panelTex, color2); ReplaceTexture(ref _accentTex, new Color(val.r, val.g, val.b, 1f * num3)); ReplaceTexture(ref _buttonTex, color3); ReplaceTexture(ref _buttonActiveTex, color4); ReplaceTexture(ref _sliderTex, color5); ReplaceTexture(ref _sliderThumbTex, new Color(val.r, val.g * 0.95f, val.b * 0.7f, 1f * num3)); ReplaceTexture(ref _tabDimTex, color6); ReplaceTexture(ref _scrollbarTrackTex, color7); ReplaceTexture(ref _searchBgTex, color8); _windowStyle.normal.background = _bgTex; _headerStyle.normal.textColor = textColor; _labelStyle.normal.textColor = textColor2; _valueStyle.normal.textColor = textColor2; _buttonStyle.normal.background = _buttonTex; _buttonStyle.active.background = _buttonActiveTex; _buttonStyle.hover.background = _buttonActiveTex; _buttonStyle.focused.background = _buttonActiveTex; _buttonStyle.normal.textColor = textColor2; _tabStyle.normal.background = _panelTex; _tabStyle.active.background = _buttonActiveTex; _tabStyle.hover.background = _buttonActiveTex; _tabStyle.focused.background = _buttonActiveTex; _tabStyle.normal.textColor = textColor2; _tabActiveStyle.normal.background = _accentTex; _tabActiveStyle.active.background = _accentTex; _tabActiveStyle.hover.background = _accentTex; _tabActiveStyle.focused.background = _accentTex; _tabActiveStyle.normal.textColor = new Color(0.1f, 0.08f, 0.08f, num4); _tabDimStyle.normal.background = _tabDimTex; _tabDimStyle.active.background = _tabDimTex; _tabDimStyle.hover.background = _tabDimTex; _tabDimStyle.focused.background = _tabDimTex; _tabDimStyle.normal.textColor = textColor3; _sliderStyle.normal.background = _sliderTex; _sliderStyle.active.background = _sliderTex; _sliderStyle.hover.background = _sliderTex; _sliderStyle.focused.background = _sliderTex; _sliderThumbStyle.normal.background = _sliderThumbTex; _sliderThumbStyle.active.background = _sliderThumbTex; _sliderThumbStyle.hover.background = _sliderThumbTex; _sliderThumbStyle.focused.background = _sliderThumbTex; _searchFieldStyle.normal.background = _searchBgTex; _searchFieldStyle.focused.background = _searchBgTex; _scrollViewStyle.normal.background = _panelTex; _vScrollbarStyle.normal.background = _scrollbarTrackTex; _vScrollbarThumbStyle.normal.background = _accentTex; _vScrollbarThumbStyle.active.background = _accentTex; _vScrollbarThumbStyle.hover.background = _accentTex; _vScrollbarThumbStyle.focused.background = _accentTex; _rowBoxStyle.normal.background = _panelTex; GUI.skin.verticalScrollbar = _vScrollbarStyle; GUI.skin.verticalScrollbarThumb = _vScrollbarThumbStyle; } } private void ReplaceTexture(ref Texture2D target, Color color) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)target != (Object)null) { Object.Destroy((Object)(object)target); } target = MakeTex(color); } private static Texture2D MakeTex(Color color) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown Texture2D val = new Texture2D(1, 1, (TextureFormat)4, false); val.SetPixel(0, 0, color); val.Apply(false, true); return val; } internal string GetHierarchyPath(Transform transform) { if ((Object)(object)transform == (Object)null) { return "(none)"; } List<string> list = new List<string>(); Transform val = transform; while ((Object)(object)val != (Object)null) { list.Add(((Object)val).name); val = val.parent; } list.Reverse(); return string.Join("/", list); } internal float GetMultiplierForSource(AudioSource source, AudioClip explicitClip = null) { if (!ModEnabled.Value || (Object)(object)source == (Object)null) { return 1f; } if (!TryResolveGroup(source, explicitClip, out var category, out var groupKey)) { return 1f; } ConfigEntry<int> orCreateGroupEntry = GetOrCreateGroupEntry(category, groupKey); if (!IsCategoryEnabled(category)) { return 1f; } float num = ((GlobalPercent.Value <= 0) ? 0f : ((float)Mathf.Clamp(GlobalPercent.Value, 1, 100))) / 100f; return Mathf.Clamp(((orCreateGroupEntry.Value <= 0) ? 0f : ((float)Mathf.Clamp(orCreateGroupEntry.Value, 1, 100))) / 100f * num, 0f, 2f); } internal bool IsDiscoSource(AudioSource source, AudioClip explicitClip = null) { if ((Object)(object)source == (Object)null) { return false; } if (TryResolveGroup(source, explicitClip, out var category, out var groupKey) && category == SoundCategory.Item) { return string.Equals(groupKey, "discoball", StringComparison.Ordinal); } return false; } internal bool ShouldForceDiscoMute(AudioSource source, AudioClip explicitClip = null) { if (!ModEnabled.Value || !ItemSoundsEnabled.Value) { return false; } if (GetOrCreateGroupEntry(SoundCategory.Item, "discoball").Value > 0) { return false; } AudioClip val = (((Object)(object)explicitClip != (Object)null) ? explicitClip : (((Object)(object)source != (Object)null) ? source.clip : null)); string text = NormalizePreserveDigits(((Object)(object)val != (Object)null) ? ((Object)val).name : string.Empty); if (text.StartsWith("boomboxmusic", StringComparison.Ordinal) || text.StartsWith("boombox6questionmark", StringComparison.Ordinal) || text.Contains("discoballmusic")) { return true; } string text2 = (((Object)(object)source != (Object)null && (Object)(object)((Component)source).gameObject != (Object)null) ? ((Object)((Component)source).gameObject).name : string.Empty); string text3 = (((Object)(object)source != (Object)null && (Object)(object)((Component)source).transform != (Object)null && (Object)(object)((Component)source).transform.root != (Object)null) ? ((Object)((Component)source).transform.root).name : string.Empty); string text4 = (((Object)(object)source != (Object)null) ? GetHierarchyPath(((Component)source).transform) : string.Empty); string text5 = (text2 + " " + text3 + " " + text4).ToLowerInvariant(); if (text5.Contains("discoball") || (text5.Contains("disco") && text5.Contains("ball"))) { return true; } if (SceneHasDiscoBall() && ((text5.Contains("ship") && text5.Contains("light")) || text5.Contains("shiplight") || text5.Contains("ship lights") || text5.Contains("light switch") || text5.Contains("lightswitch") || text5.Contains("lightswitchcontainer") || text5.Contains("breakerbox") || text5.Contains("breaker box"))) { return true; } return false; } internal string BuildDebugResolutionLine(AudioSource source, float multiplier) { if ((Object)(object)source == (Object)null) { return "[AudioResolution] null source"; } SoundCategory category; string groupKey; bool num = TryResolveGroup(source, null, out category, out groupKey); string hierarchyPath = GetHierarchyPath(((Component)source).transform); string text = (((Object)(object)((Component)source).transform != (Object)null && (Object)(object)((Component)source).transform.root != (Object)null) ? ((Object)((Component)source).transform.root).name : "(none)"); string text2 = (((Object)(object)source.clip != (Object)null) ? ((Object)source.clip).name : "(null)"); string text3 = (((Object)(object)source.outputAudioMixerGroup != (Object)null) ? ((Object)source.outputAudioMixerGroup).name : "(none)"); string text4 = (num ? GetCategoryTitle(category) : "Unresolved"); string text5 = (num ? groupKey : "(none)"); return $"[AudioResolution] id={((Object)source).GetInstanceID()} category={text4} key={text5} mult={multiplier:0.000} enabled(mod={ModEnabled.Value},item={ItemSoundsEnabled.Value},env={EnvironmentSoundsEnabled.Value},other={OtherSoundsEnabled.Value}) obj={((Object)((Component)source).gameObject).name} path={hierarchyPath} root={text} clip={text2} mixer={text3} playOnAwake={source.playOnAwake} loop={source.loop} mute={source.mute} spatialBlend={source.spatialBlend:0.00} volume={source.volume:0.000}"; } private ConfigEntry<int> GetOrCreateGroupEntry(SoundCategory category, string groupKey) { //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown Dictionary<string, ConfigEntry<int>> dictionaryByCategory = GetDictionaryByCategory(category); string categoryTitle = GetCategoryTitle(category); lock (_lock) { if (dictionaryByCategory.TryGetValue(groupKey, out var value)) { RememberLastNonZero(category, groupKey, value.Value); return value; } ConfigEntry<int> val2 = (dictionaryByCategory[groupKey] = ((BaseUnityPlugin)this).Config.Bind<int>(categoryTitle, groupKey, 100, new ConfigDescription("Volume percent for '" + groupKey + "'. 0 = muted, 1-100 by slider.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()))); RememberLastNonZero(category, groupKey, val2.Value); return val2; } } private bool TryResolveGroup(AudioSource source, AudioClip explicitClip, out SoundCategory category, out string groupKey) { category = SoundCategory.Item; groupKey = string.Empty; if ((Object)(object)source == (Object)null) { return false; } AudioClip val = (((Object)(object)explicitClip != (Object)null) ? explicitClip : source.clip); string text = NormalizePreserveDigits(((Object)(object)val != (Object)null) ? ((Object)val).name : string.Empty); if (text.StartsWith("boomboxmusic6", StringComparison.Ordinal) || text.StartsWith("boomboxmusic", StringComparison.Ordinal) || text.StartsWith("boombox6questionmark", StringComparison.Ordinal) || text.Contains("discoballmusic")) { category = SoundCategory.Item; groupKey = "discoball"; return true; } if (TryForceDiscoBallKey(source, val, out var forcedKey)) { category = SoundCategory.Item; groupKey = forcedKey; return true; } string text2 = string.Empty; NoisemakerProp componentInParent = ((Component)source).GetComponentInParent<NoisemakerProp>(); if ((Object)(object)componentInParent != (Object)null && (Object)(object)((GrabbableObject)componentInParent).itemProperties != (Object)null && !string.IsNullOrWhiteSpace(((GrabbableObject)componentInParent).itemProperties.itemName)) { text2 = ((GrabbableObject)componentInParent).itemProperties.itemName; category = SoundCategory.Item; } if (string.IsNullOrWhiteSpace(text2)) { GrabbableObject componentInParent2 = ((Component)source).GetComponentInParent<GrabbableObject>(); if ((Object)(object)componentInParent2 != (Object)null && (Object)(object)componentInParent2.itemProperties != (Object)null && !string.IsNullOrWhiteSpace(componentInParent2.itemProperties.itemName)) { text2 = componentInParent2.itemProperties.itemName; category = SoundCategory.Item; } } if (string.IsNullOrWhiteSpace(text2)) { PlaceableShipObject componentInParent3 = ((Component)source).GetComponentInParent<PlaceableShipObject>(); if ((Object)(object)componentInParent3 != (Object)null) { text2 = ((Object)((Component)componentInParent3).gameObject).name; category = SoundCategory.Item; } } if (string.IsNullOrWhiteSpace(text2)) { text2 = (((Object)(object)((Component)source).transform.root != (Object)null) ? ((Object)((Component)source).transform.root).name : ((Object)((Component)source).gameObject).name); category = DetermineNonItemCategory(text2, source); } string text3 = Normalize(text2); if (string.IsNullOrEmpty(text3)) { return false; } if (category == SoundCategory.Item && _aliases.TryGetValue(text3, out var value)) { text3 = value; } groupKey = text3; return true; } private bool TryForceDiscoBallKey(AudioSource source, AudioClip explicitClip, out string forcedKey) { forcedKey = string.Empty; string text = (((Object)(object)explicitClip != (Object)null) ? ((Object)explicitClip).name : (((Object)(object)source.clip != (Object)null) ? ((Object)source.clip).name : string.Empty)); string text2 = (((Object)(object)((Component)source).gameObject != (Object)null) ? ((Object)((Component)source).gameObject).name : string.Empty); string text3 = (((Object)(object)((Component)source).transform != (Object)null && (Object)(object)((Component)source).transform.root != (Object)null) ? ((Object)((Component)source).transform.root).name : string.Empty); string text4 = (text2 + " " + text3 + " " + text).ToLowerInvariant(); if ((!text4.Contains("ship") || !text4.Contains("light")) && !text4.Contains("shiplight") && !text4.Contains("ship lights") && !text4.Contains("light switch") && !text4.Contains("lightswitch") && !text4.Contains("set ship lights rpc") && !text4.Contains("toggling ship lights rpc") && !text4.Contains("breakerbox") && !text4.Contains("breaker box")) { return false; } if (!HasDiscoBallControlContext()) { return false; } forcedKey = "discoball"; return true; } private bool HasDiscoBallControlContext() { lock (_lock) { if (_itemEntries.ContainsKey("discoball")) { return true; } } return SceneHasDiscoBall(); } private bool SceneHasDiscoBall() { if (Time.unscaledTime < _nextDiscoProbeAt) { return _sceneHasDiscoBall; } _nextDiscoProbeAt = Time.unscaledTime + 2f; _sceneHasDiscoBall = false; PlaceableShipObject[] array = Object.FindObjectsOfType<PlaceableShipObject>(); foreach (PlaceableShipObject val in array) { if ((Object)(object)val == (Object)null) { continue; } string text = ((Object)((Component)val).gameObject).name.ToLowerInvariant(); if (text.Contains("discoball") || text.Contains("disco ball") || (text.Contains("disco") && text.Contains("ball"))) { _sceneHasDiscoBall = true; DumpDiscoBallAudioGraph(((Component)val).transform); if (DebugAudioDiscovery.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("[DiscoProbe] found placeable='" + ((Object)((Component)val).gameObject).name + "' path=" + GetHierarchyPath(((Component)val).transform))); } break; } } if (DebugAudioDiscovery.Value && !_sceneHasDiscoBall) { ((BaseUnityPlugin)this).Logger.LogInfo((object)$"[DiscoProbe] no disco ball found among {array.Length} PlaceableShipObject(s)"); } return _sceneHasDiscoBall; } private void DumpDiscoBallAudioGraph(Transform discoTransform) { if (_dumpedDiscoAudioGraph || (Object)(object)discoTransform == (Object)null) { return; } _dumpedDiscoAudioGraph = true; try { AudioSource[] componentsInChildren = ((Component)discoTransform).GetComponentsInChildren<AudioSource>(true); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"[DiscoDump] root={GetHierarchyPath(discoTransform)} audioSources={componentsInChildren.Length}"); foreach (AudioSource val in componentsInChildren) { if (!((Object)(object)val == (Object)null)) { string hierarchyPath = GetHierarchyPath(((Component)val).transform); string text = (((Object)(object)val.clip != (Object)null) ? ((Object)val.clip).name : "(null)"); string text2 = (((Object)(object)val.outputAudioMixerGroup != (Object)null) ? ((Object)val.outputAudioMixerGroup).name : "(none)"); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"[DiscoDump] source={((Object)((Component)val).gameObject).name} path={hierarchyPath} clip={text} mixer={text2} enabled={((Behaviour)val).enabled} active={((Component)val).gameObject.activeInHierarchy} playOnAwake={val.playOnAwake} loop={val.loop} mute={val.mute} spatialBlend={val.spatialBlend:0.00} volume={val.volume:0.000}"); } } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[DiscoDump] failed to dump disco audio graph: " + ex.Message)); } } private static SoundCategory DetermineNonItemCategory(string rawName, AudioSource source) { string text = (((Object)(object)source != (Object)null && (Object)(object)((Component)source).gameObject != (Object)null) ? ((Object)((Component)source).gameObject).name : string.Empty); string text2 = (((Object)(object)source != (Object)null && (Object)(object)((Component)source).transform != (Object)null && (Object)(object)((Component)source).transform.root != (Object)null) ? ((Object)((Component)source).transform.root).name : string.Empty); string text3 = (((Object)(object)source != (Object)null && (Object)(object)source.clip != (Object)null) ? ((Object)source.clip).name : string.Empty); string text4 = (rawName + " " + text + " " + text2 + " " + text3).ToLowerInvariant(); if (text4.Contains("discoball") || text4.Contains("disco ball") || (text4.Contains("disco") && text4.Contains("ball"))) { return SoundCategory.Item; } if (text2.Equals("Environment", StringComparison.OrdinalIgnoreCase) || text4.Contains("environment")) { return SoundCategory.Environment; } if (text2.Equals("Systems", StringComparison.OrdinalIgnoreCase) || text4.Contains("systems")) { return SoundCategory.Other; } if (ContainsAnyKeyword(text4, EnvironmentKeywords)) { return SoundCategory.Environment; } ContainsAnyKeyword(text4, OtherKeywords); return SoundCategory.Other; } private static bool ContainsAnyKeyword(string value, string[] keywords) { foreach (string value2 in keywords) { if (value.Contains(value2)) { return true; } } return false; } private static string Normalize(string value) { if (string.IsNullOrWhiteSpace(value)) { return string.Empty; } string text = value.Trim().ToLowerInvariant(); text = text.Replace("(clone)", string.Empty).Trim(); int num = text.Length - 1; while (num >= 0 && char.IsDigit(text[num])) { num--; } if (num < text.Length - 1) { text = text.Substring(0, num + 1).TrimEnd('_', '-', ' '); } while (text.Contains(" ")) { text = text.Replace(" ", " "); } return text; } private static string NormalizePreserveDigits(string value) { if (string.IsNullOrWhiteSpace(value)) { return string.Empty; } return value.Trim().ToLowerInvariant().Replace("(clone)", string.Empty) .Trim() .Replace(" ", string.Empty) .Replace("_", string.Empty) .Replace("-", string.Empty); } private void BuildDefaultAliases() { _aliases["air horn"] = "airhorn"; _aliases["loudhorn"] = "airhorn"; _aliases["disco ball"] = "discoball"; _aliases["disco_ball"] = "discoball"; _aliases["discoballcontainer"] = "discoball"; _aliases["disco ball container"] = "discoball"; _aliases["disco"] = "discoball"; _aliases["boomboxmusic6"] = "discoball"; _aliases["boombox6questionmark"] = "discoball"; _aliases["disco ball music"] = "discoball"; _aliases["discoballmusic"] = "discoball"; _aliases["clown horn"] = "clownhorn"; } } internal static class VolumeRuntime { private static readonly Dictionary<int, float> BaseVolumeBySource = new Dictionary<int, float>(); private static readonly Dictionary<int, float> LastAppliedMultiplierBySource = new Dictionary<int, float>(); private static readonly Dictionary<int, AudioSource> KnownSources = new Dictionary<int, AudioSource>(); private static readonly Dictionary<int, string> LastResolutionBySource = new Dictionary<int, string>(); private static readonly HashSet<int> LoggedScanSources = new HashSet<int>(); private static readonly Dictionary<int, bool> PreviousMuteBySource = new Dictionary<int, bool>(); private static readonly object Sync = new object(); internal static void ApplyForPlay(AudioSource source, string playbackMethod) { TrackSource(source); UniversalVolumeControllerPlugin instance = UniversalVolumeControllerPlugin.Instance; if ((Object)(object)instance == (Object)null || (Object)(object)source == (Object)null) { return; } instance.LogPlaybackEvent(playbackMethod, source, source.clip); if (instance.ShouldForceDiscoMute(source)) { int instanceID = ((Object)source).GetInstanceID(); lock (Sync) { if (!PreviousMuteBySource.ContainsKey(instanceID)) { PreviousMuteBySource[instanceID] = source.mute; } source.mute = true; LastAppliedMultiplierBySource[instanceID] = 0f; return; } } int instanceID2 = ((Object)source).GetInstanceID(); lock (Sync) { if (PreviousMuteBySource.TryGetValue(instanceID2, out var value)) { source.mute = value; PreviousMuteBySource.Remove(instanceID2); } } float multiplierForSource = instance.GetMultiplierForSource(source); bool flag = instance.IsDiscoSource(source, source.clip); int instanceID3 = ((Object)source).GetInstanceID(); lock (Sync) { if (!BaseVolumeBySource.TryGetValue(instanceID3, out var value2)) { value2 = source.volume; BaseVolumeBySource[instanceID3] = value2; LastAppliedMultiplierBySource[instanceID3] = 1f; } else { float value3; float num = (LastAppliedMultiplierBySource.TryGetValue(instanceID3, out value3) ? Mathf.Max(0.0001f, value3) : 1f); float num2 = value2 * num; if (!flag && Mathf.Abs(source.volume - num2) > 0.01f) { value2 = source.volume / num; BaseVolumeBySource[instanceID3] = value2; } } source.volume = Mathf.Clamp(value2 * multiplierForSource, 0f, 2f); LastAppliedMultiplierBySource[instanceID3] = multiplierForSource; } if (!instance.DebugAudioResolution.Value) { return; } string text = instance.BuildDebugResolutionLine(source, multiplierForSource); bool flag2 = false; lock (Sync) { if (!LastResolutionBySource.TryGetValue(instanceID3, out var value4) || !string.Equals(value4, text, StringComparison.Ordinal)) { LastResolutionBySource[instanceID3] = text; flag2 = true; } } if (flag2) { UniversalVolumeControllerPlugin.Log.LogInfo((object)text); } } internal static void ApplyForOneShot(ref float volumeScale, AudioSource source, AudioClip clip) { TrackSource(source); UniversalVolumeControllerPlugin instance = UniversalVolumeControllerPlugin.Instance; if (!((Object)(object)instance == (Object)null) && !((Object)(object)source == (Object)null)) { instance.LogPlaybackEvent("PlayOneShot", source, clip, volumeScale); if (instance.ShouldForceDiscoMute(source, clip)) { volumeScale = 0f; return; } float multiplierForSource = instance.GetMultiplierForSource(source, clip); volumeScale = Mathf.Clamp(volumeScale * multiplierForSource, 0f, 2f); } } internal static void ApplyForClipAtPoint(ref float volume, AudioClip clip, Vector3 position) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) UniversalVolumeControllerPlugin instance = UniversalVolumeControllerPlugin.Instance; if (!((Object)(object)instance == (Object)null)) { instance.LogPlaybackEvent("PlayClipAtPoint", null, clip, volume, position); if (instance.ShouldForceDiscoMute(null, clip)) { volume = 0f; } } } internal static void ScanActiveSources() { AudioSource[] array = Object.FindObjectsOfType<AudioSource>(); UniversalVolumeControllerPlugin instance = UniversalVolumeControllerPlugin.Instance; for (int i = 0; i < array.Length; i++) { try { AudioSource val = array[i]; TrackSource(val); if (!((Object)(object)instance != (Object)null) || !instance.DebugAudioDiscovery.Value || !((Object)(object)val != (Object)null)) { continue; } int instanceID = ((Object)val).GetInstanceID(); bool flag = false; lock (Sync) { if (LoggedScanSources.Add(instanceID)) { flag = true; } } if (flag) { string text = SafeGetRootName(val); string hierarchyPath = instance.GetHierarchyPath(((Object)(object)val != (Object)null) ? ((Component)val).transform : null); string text2 = (((Object)(object)val.outputAudioMixerGroup != (Object)null) ? ((Object)val.outputAudioMixerGroup).name : "(none)"); string text3 = (((Object)(object)val.clip != (Object)null) ? ((Object)val.clip).name : "(null)"); bool flag2 = (Object)(object)((Component)val).gameObject != (Object)null && ((Component)val).gameObject.activeInHierarchy; UniversalVolumeControllerPlugin.Log.LogInfo((object)$"[AudioScan] id={instanceID} name={SafeGetGameObjectName(val)} path={hierarchyPath} root={text} clip={text3} mixer={text2} playOnAwake={val.playOnAwake} loop={val.loop} mute={val.mute} enabled={((Behaviour)val).enabled} active={flag2} spatialBlend={val.spatialBlend:0.00} volume={val.volume:0.000}"); } } catch { } } if ((Object)(object)instance != (Object)null && instance.DebugAudioDiscovery.Value) { UniversalVolumeControllerPlugin.Log.LogInfo((object)$"[AudioScan] totalSources={array.Length}"); } } internal static void RefreshKnownSources() { AudioSource[] array; lock (Sync) { array = KnownSources.Values.ToArray(); } foreach (AudioSource val in array) { if (!((Object)(object)val == (Object)null)) { try { ApplyForPlay(val, "Refresh"); } catch { } } } List<int> list = null; lock (Sync) { foreach (KeyValuePair<int, AudioSource> knownSource in KnownSources) { if (!((Object)(object)knownSource.Value != (Object)null)) { if (list == null) { list = new List<int>(); } list.Add(knownSource.Key); } } if (list != null) { for (int j = 0; j < list.Count; j++) { int num = list[j]; KnownSources.Remove(num); BaseVolumeBySource.Remove(num); LastAppliedMultiplierBySource.Remove(num); LastResolutionBySource.Remove(num); LoggedScanSources.Remove(num); PreviousMuteBySource.Remove(num); } } } } internal static void RefreshDiscoSourcesLate() { UniversalVolumeControllerPlugin instance = UniversalVolumeControllerPlugin.Instance; if ((Object)(object)instance == (Object)null) { return; } AudioSource[] array; lock (Sync) { array = KnownSources.Values.ToArray(); } foreach (AudioSource val in array) { if ((Object)(object)val == (Object)null) { continue; } try { if (instance.IsDiscoSource(val, val.clip)) { ApplyForPlay(val, "LateRefresh"); } } catch { } } } private static void TrackSource(AudioSource source) { if ((Object)(object)source == (Object)null) { return; } int instanceID = ((Object)source).GetInstanceID(); bool flag = false; lock (Sync) { if (KnownSources.TryGetValue(instanceID, out var value) && (Object)(object)value == (Object)(object)source) { return; } KnownSources[instanceID] = source; flag = true; } UniversalVolumeControllerPlugin instance = UniversalVolumeControllerPlugin.Instance; if (!flag || !((Object)(object)instance != (Object)null) || !instance.DebugAudioDiscovery.Value) { return; } try { string text = SafeGetRootName(source); string text2 = (((Object)(object)UniversalVolumeControllerPlugin.Instance != (Object)null) ? UniversalVolumeControllerPlugin.Instance.GetHierarchyPath(((Object)(object)source != (Object)null) ? ((Component)source).transform : null) : "(none)"); string text3 = (((Object)(object)source.outputAudioMixerGroup != (Object)null) ? ((Object)source.outputAudioMixerGroup).name : "(none)"); UniversalVolumeControllerPlugin.Log.LogInfo((object)string.Format("[AudioDiscovery] id={0} name={1} path={2} root={3} clip={4} mixer={5} playOnAwake={6} loop={7} mute={8} spatialBlend={9:0.00} volume={10:0.000}", instanceID, SafeGetGameObjectName(source), text2, text, ((Object)(object)source.clip != (Object)null) ? ((Object)source.clip).name : "(null)", text3, source.playOnAwake, source.loop, source.mute, source.spatialBlend, source.volume)); } catch (Exception ex) { UniversalVolumeControllerPlugin.Log.LogWarning((object)$"[AudioDiscovery] failed to describe source {instanceID}: {ex.Message}"); } } private static string SafeGetGameObjectName(AudioSource source) { try { return ((Object)(object)source != (Object)null && (Object)(object)((Component)source).gameObject != (Object)null) ? ((Object)((Component)source).gameObject).name : "(none)"; } catch { return "(missing)"; } } private static string SafeGetRootName(AudioSource source) { try { Transform val = (((Object)(object)source != (Object)null) ? ((Component)source).transform : null); if ((Object)(object)val != (Object)null && (Object)(object)val.root != (Object)null) { return ((Object)val.root).name; } } catch { } return "(none)"; } } [HarmonyPatch(typeof(AudioSource))] internal static class AudioSourcePlayPatch { [HarmonyPatch("Play", new Type[] { })] [HarmonyPrefix] private static void PlayPrefix(AudioSource __instance) { VolumeRuntime.ApplyForPlay(__instance, "Play"); } [HarmonyPatch("PlayDelayed", new Type[] { typeof(float) })] [HarmonyPrefix] private static void PlayDelayedPrefix(AudioSource __instance) { VolumeRuntime.ApplyForPlay(__instance, "PlayDelayed"); } } [HarmonyPatch(typeof(AudioSource))] internal static class AudioSourceOneShotPatch { [HarmonyPatch("PlayClipAtPoint", new Type[] { typeof(AudioClip), typeof(Vector3), typeof(float) })] [HarmonyPrefix] private static void PlayClipAtPointPrefix(AudioClip clip, Vector3 position, ref float volume) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) VolumeRuntime.ApplyForClipAtPoint(ref volume, clip, position); } [HarmonyPatch("PlayOneShot", new Type[] { typeof(AudioClip) })] [HarmonyPrefix] private static bool PlayOneShotSimplePrefix(AudioSource __instance, AudioClip clip) { UniversalVolumeControllerPlugin instance = UniversalVolumeControllerPlugin.Instance; instance?.LogPlaybackEvent("PlayOneShot", __instance, clip, 1f); if ((Object)(object)instance != (Object)null && instance.ShouldForceDiscoMute(__instance, clip)) { return false; } return true; } [HarmonyPatch("PlayOneShot", new Type[] { typeof(AudioClip), typeof(float) })] [HarmonyPrefix] private static void PlayOneShotPrefix(AudioSource __instance, AudioClip clip, ref float volumeScale) { VolumeRuntime.ApplyForOneShot(ref volumeScale, __instance, clip); } [HarmonyPatch("PlayOneShotHelper", new Type[] { typeof(AudioSource), typeof(AudioClip), typeof(float) })] [HarmonyPrefix] private static void PlayOneShotHelperPrefix(AudioSource source, AudioClip clip, ref float volumeScale) { VolumeRuntime.ApplyForOneShot(ref volumeScale, source, clip); } }