Decompiled source of AmbienceSoundConfig v2.6.9

AmbienceSoundConfig.dll

Decompiled 2 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
using Valheim.SettingsGui;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("AmbienceSoundConfig")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Valheim_Ambience_Mute")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("f01ac134-75c0-45a2-be66-fe63019a4264")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace AmbienceSoundConfig;

[BepInPlugin("com.draconicvelum.ambiencesoundconfig", "Ambience Sound Config", "2.6.9")]
public class AmbienceSoundConfig : BaseUnityPlugin
{
	public static ConfigEntry<float> MasterVolume;

	public static ConfigEntry<float> WindVolume;

	public static ConfigEntry<float> OceanVolume;

	public static ConfigEntry<float> AmbientLoopVolume;

	public static ConfigEntry<float> ShieldHumVolume;

	public static ConfigEntry<string> ExtraSfxList;

	public static ConfigEntry<float> ExtraSfxVolume;

	public static ConfigEntry<string> ExtraClipList;

	public static ConfigEntry<float> ExtraClipVolume;

	public static ConfigEntry<bool> EnableSoundLogging;

	public static ConfigEntry<bool> LogOnlyUnique;

	private static readonly Harmony harmony = new Harmony("com.draconicvelum.ambiencesoundconfig");

	private void Awake()
	{
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Expected O, but got Unknown
		//IL_006c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0076: Expected O, but got Unknown
		//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: Expected O, but got Unknown
		//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f0: Expected O, but got Unknown
		//IL_0123: Unknown result type (might be due to invalid IL or missing references)
		//IL_012d: Expected O, but got Unknown
		//IL_0184: Unknown result type (might be due to invalid IL or missing references)
		//IL_018e: Expected O, but got Unknown
		//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ef: Expected O, but got Unknown
		MasterVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Ambience", "Master Volume", 0.25f, new ConfigDescription("Controls overall ambience loudness multiplier.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
		WindVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Ambience", "Wind Volume", 1f, new ConfigDescription("Volume for wind ambience (multiplied by Master Volume).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
		OceanVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Ambience", "Ocean Volume", 1f, new ConfigDescription("Volume for ocean ambience (multiplied by Master Volume).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
		AmbientLoopVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Ambience", "Ambient Loop Volume", 1f, new ConfigDescription("Volume for background ambient loop (multiplied by Master Volume).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
		ShieldHumVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Ambience", "Shield Hum Volume", 1f, new ConfigDescription("Volume for shield dome hum (multiplied by Master Volume).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
		ExtraSfxList = ((BaseUnityPlugin)this).Config.Bind<string>("Extra SFX", "Extra SFX Prefabs", "", "Comma separated list of ZSFX prefab names affected by Extra SFX Volume.");
		ExtraSfxVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Extra SFX", "Extra SFX Volume", 1f, new ConfigDescription("Independent volume multiplier for listed sound effects.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
		ExtraClipList = ((BaseUnityPlugin)this).Config.Bind<string>("Extra Clips", "Extra Clip Names", "", "Comma separated list of AudioClip names to mute or scale.");
		ExtraClipVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Extra Clips", "Extra Clip Volume", 1f, new ConfigDescription("Independent volume multiplier for listed clip names.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
		EnableSoundLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Logging", "Enable Sound Logging", false, "Logs all played SFX and AudioClips to console and a file next to this config.");
		LogOnlyUnique = ((BaseUnityPlugin)this).Config.Bind<bool>("Logging", "Log Only Unique", true, "If enabled, each sound name is logged only once per session.");
		ExtraSfxList.SettingChanged += delegate
		{
			AudioSourceFilter.Refresh();
		};
		ExtraSfxVolume.SettingChanged += delegate
		{
			AudioSource[] array = Object.FindObjectsOfType<AudioSource>();
			foreach (AudioSource src in array)
			{
				AudioSourceFilter.Apply(src);
			}
		};
		ExtraClipList.SettingChanged += delegate
		{
			AudioSourceFilter.Refresh();
		};
		ExtraClipVolume.SettingChanged += delegate
		{
		};
		AudioSourceFilter.Refresh();
		SoundPlayLogger.Init(((BaseUnityPlugin)this).Config);
		harmony.PatchAll(typeof(AudioSource_DoAll_Patch));
		harmony.PatchAll(typeof(AudioSource_PlayOneShotScale_Patch));
		harmony.PatchAll(typeof(ZSFX_VolumeScale_Patch));
		harmony.PatchAll(typeof(AudioMan_AmbienceVolume_Patch));
		harmony.PatchAll(typeof(SettingsInject));
		((BaseUnityPlugin)this).Config.ConfigReloaded += OnReloaded;
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Ambience Sound Config (v2.6.9) loaded.");
	}

	private void OnReloaded(object sender, EventArgs e)
	{
		AudioSourceFilter.Refresh();
		AudioSourceFilter.ApplyToRunningSources();
		ApplyAllVolumes();
		SettingsInject.SyncUI();
	}

	public static void ApplyAllVolumes()
	{
		AudioMan_AmbienceVolume_Patch.ApplyWindVolumeWrapper();
		AudioMan_AmbienceVolume_Patch.ApplyOceanVolumeWrapper();
		AudioMan_AmbienceVolume_Patch.ApplyAmbientLoopVolumeWrapper();
		AudioMan_AmbienceVolume_Patch.ApplyShieldHumVolumeWrapper();
	}
}
[HarmonyPatch(typeof(AudioMan))]
public static class AudioMan_AmbienceVolume_Patch
{
	private static readonly BindingFlags Flags = BindingFlags.Instance | BindingFlags.NonPublic;

	private static readonly Dictionary<string, FieldInfo> CachedFields = new Dictionary<string, FieldInfo>();

	private static AudioSource GetPrivateSource(string fieldName)
	{
		if ((Object)(object)AudioMan.instance == (Object)null)
		{
			return null;
		}
		if (!CachedFields.TryGetValue(fieldName, out var value))
		{
			value = typeof(AudioMan).GetField(fieldName, Flags);
			if (value != null)
			{
				CachedFields[fieldName] = value;
			}
		}
		object? obj = value?.GetValue(AudioMan.instance);
		return (AudioSource)((obj is AudioSource) ? obj : null);
	}

	public static void ApplyWindVolumeWrapper()
	{
		AudioSource privateSource = GetPrivateSource("m_windLoopSource");
		if ((Object)(object)privateSource != (Object)null)
		{
			privateSource.volume = AmbienceSoundConfig.WindVolume.Value * AmbienceSoundConfig.MasterVolume.Value;
		}
	}

	public static void ApplyOceanVolumeWrapper()
	{
		AudioSource privateSource = GetPrivateSource("m_oceanAmbientSource");
		if ((Object)(object)privateSource != (Object)null)
		{
			privateSource.volume = AmbienceSoundConfig.OceanVolume.Value * AmbienceSoundConfig.MasterVolume.Value;
		}
	}

	public static void ApplyAmbientLoopVolumeWrapper()
	{
		AudioSource privateSource = GetPrivateSource("m_ambientLoopSource");
		if ((Object)(object)privateSource != (Object)null)
		{
			privateSource.volume = AmbienceSoundConfig.AmbientLoopVolume.Value * AmbienceSoundConfig.MasterVolume.Value;
		}
	}

	public static void ApplyShieldHumVolumeWrapper()
	{
		AudioSource privateSource = GetPrivateSource("m_shieldHumSource");
		if ((Object)(object)privateSource != (Object)null)
		{
			privateSource.volume = AmbienceSoundConfig.ShieldHumVolume.Value * AmbienceSoundConfig.MasterVolume.Value;
		}
	}

	[HarmonyPostfix]
	[HarmonyPatch("UpdateWindAmbience")]
	public static void ApplyWindVolume(ref AudioSource ___m_windLoopSource)
	{
		ApplyWindVolumeWrapper();
	}

	[HarmonyPostfix]
	[HarmonyPatch("UpdateOceanAmbiance")]
	public static void ApplyOceanVolume(ref AudioSource ___m_oceanAmbientSource)
	{
		ApplyOceanVolumeWrapper();
	}

	[HarmonyPostfix]
	[HarmonyPatch("UpdateAmbientLoop")]
	public static void ApplyAmbientLoopVolume(ref AudioSource ___m_ambientLoopSource)
	{
		ApplyAmbientLoopVolumeWrapper();
	}

	[HarmonyPostfix]
	[HarmonyPatch("UpdateShieldHum")]
	public static void ApplyShieldHumVolume(ref AudioSource ___m_shieldHumSource)
	{
		ApplyShieldHumVolumeWrapper();
	}
}
internal static class AudioSourceFilter
{
	private static readonly HashSet<string> _nameTargets = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

	private static readonly HashSet<string> _clipTargets = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

	private static readonly Dictionary<AudioSource, float> _baseVolume = new Dictionary<AudioSource, float>();

	internal static float ClipMultiplier => AmbienceSoundConfig.ExtraClipVolume.Value;

	internal static bool HasClipTargets => _clipTargets.Count > 0;

	internal static void Refresh()
	{
		_nameTargets.Clear();
		_clipTargets.Clear();
		string value = AmbienceSoundConfig.ExtraSfxList.Value;
		if (!string.IsNullOrEmpty(value))
		{
			string[] array = value.Split(new char[1] { ',' });
			foreach (string name in array)
			{
				string text = Normalize(name);
				if (!string.IsNullOrEmpty(text))
				{
					_nameTargets.Add(text);
				}
			}
		}
		string value2 = AmbienceSoundConfig.ExtraClipList.Value;
		if (string.IsNullOrEmpty(value2))
		{
			return;
		}
		string[] array2 = value2.Split(new char[1] { ',' });
		foreach (string name2 in array2)
		{
			string text2 = Normalize(name2);
			if (!string.IsNullOrEmpty(text2))
			{
				_clipTargets.Add(text2);
			}
		}
	}

	internal static void Apply(AudioSource src)
	{
		if (!((Object)(object)src == (Object)null) && _nameTargets.Count != 0 && MatchName(((Object)((Component)src).gameObject).name))
		{
			ApplyVolume(src, AmbienceSoundConfig.ExtraSfxVolume.Value);
		}
	}

	internal static void Apply(AudioSource src, ref float volume)
	{
		if (!((Object)(object)src == (Object)null) && _nameTargets.Count != 0 && MatchName(((Object)((Component)src).gameObject).name))
		{
			volume = Scale(volume, AmbienceSoundConfig.ExtraSfxVolume.Value);
		}
	}

	internal static bool ShouldMuteClip(AudioClip clip)
	{
		if ((Object)(object)clip == (Object)null || _clipTargets.Count == 0)
		{
			return false;
		}
		return MatchClip(((Object)clip).name);
	}

	private static void ApplyVolume(AudioSource src, float mult)
	{
		if (mult <= 0f)
		{
			src.mute = true;
			return;
		}
		src.mute = false;
		src.volume = Mathf.Clamp01(src.volume * mult);
	}

	private static float Scale(float v, float mult)
	{
		if (mult <= 0f)
		{
			return 0f;
		}
		return v * mult;
	}

	private static bool MatchName(string goName)
	{
		if (_nameTargets.Count == 0)
		{
			return false;
		}
		string text = Normalize(goName);
		foreach (string nameTarget in _nameTargets)
		{
			if (text.Equals(nameTarget, StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			if (text.StartsWith(nameTarget, StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			if (text.IndexOf(nameTarget, StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return true;
			}
		}
		return false;
	}

	private static bool MatchClip(string clipName)
	{
		string text = Normalize(clipName);
		foreach (string clipTarget in _clipTargets)
		{
			if (text.Equals(clipTarget, StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			if (text.StartsWith(clipTarget, StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			if (text.IndexOf(clipTarget, StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return true;
			}
		}
		return false;
	}

	private static string Normalize(string name)
	{
		if (string.IsNullOrEmpty(name))
		{
			return string.Empty;
		}
		int num = name.IndexOf("(Clone)", StringComparison.OrdinalIgnoreCase);
		if (num >= 0)
		{
			name = name.Substring(0, num);
		}
		return name.Trim();
	}

	internal static void ApplyToRunningSources()
	{
		List<AudioSource> list = new List<AudioSource>();
		foreach (KeyValuePair<AudioSource, float> item in _baseVolume)
		{
			if ((Object)(object)item.Key == (Object)null)
			{
				list.Add(item.Key);
			}
		}
		foreach (AudioSource item2 in list)
		{
			_baseVolume.Remove(item2);
		}
		AudioSource[] array = Object.FindObjectsOfType<AudioSource>();
		foreach (AudioSource val in array)
		{
			if ((Object)(object)val == (Object)null || (Object)(object)val.clip == (Object)null)
			{
				continue;
			}
			if (!HasClipTargets || !ShouldMuteClip(val.clip))
			{
				if (_baseVolume.ContainsKey(val))
				{
					_baseVolume.Remove(val);
				}
				val.mute = false;
				continue;
			}
			if (!_baseVolume.ContainsKey(val))
			{
				_baseVolume[val] = val.volume;
			}
			float num = _baseVolume[val];
			float clipMultiplier = ClipMultiplier;
			if (clipMultiplier <= 0f)
			{
				val.mute = true;
				continue;
			}
			val.mute = false;
			val.volume = Mathf.Clamp01(num * clipMultiplier);
		}
	}
}
[HarmonyPatch(typeof(AudioSource))]
internal static class AudioSource_DoAll_Patch
{
	[HarmonyPostfix]
	[HarmonyPatch("Play", new Type[] { })]
	private static void Postfix_Play(AudioSource __instance)
	{
		SoundPlayLogger.Log("SFX", ((Object)((Component)__instance).gameObject).name, ((Component)__instance).gameObject);
		AudioSourceFilter.Apply(__instance);
	}

	[HarmonyPostfix]
	[HarmonyPatch("Play", new Type[] { typeof(ulong) })]
	private static void Postfix_PlayDelayed(AudioSource __instance)
	{
		AudioSourceFilter.Apply(__instance);
	}

	[HarmonyPostfix]
	[HarmonyPatch("PlayOneShot", new Type[] { typeof(AudioClip) })]
	private static void Postfix_PlayOneShot(AudioSource __instance)
	{
		AudioSourceFilter.Apply(__instance);
	}

	[HarmonyPrefix]
	[HarmonyPatch("set_volume")]
	private static void Prefix_SetVolume(AudioSource __instance, ref float value)
	{
		AudioSourceFilter.Apply(__instance, ref value);
	}
}
[HarmonyPatch(typeof(AudioSource))]
internal static class AudioSource_PlayOneShotScale_Patch
{
	[HarmonyPrefix]
	[HarmonyPatch("PlayOneShot", new Type[]
	{
		typeof(AudioClip),
		typeof(float)
	})]
	private static void Prefix(AudioSource __instance, AudioClip clip, ref float volumeScale)
	{
		SoundPlayLogger.Log("CLIP", (clip != null) ? ((Object)clip).name : null, Object.op_Implicit((Object)(object)__instance) ? ((Component)__instance).gameObject : null);
		if (!((Object)(object)clip == (Object)null) && AudioSourceFilter.HasClipTargets && AudioSourceFilter.ShouldMuteClip(clip))
		{
			float clipMultiplier = AudioSourceFilter.ClipMultiplier;
			volumeScale = ((clipMultiplier <= 0f) ? 0f : (volumeScale * clipMultiplier));
		}
	}

	[HarmonyPrefix]
	[HarmonyPatch("PlayOneShot", new Type[] { typeof(AudioClip) })]
	private static void Prefix_NoScale(AudioSource __instance, AudioClip clip)
	{
		SoundPlayLogger.Log("CLIP", (clip != null) ? ((Object)clip).name : null, Object.op_Implicit((Object)(object)__instance) ? ((Component)__instance).gameObject : null);
	}
}
[HarmonyPatch]
public static class SettingsInject
{
	private static Transform _gridContainer;

	private static bool _built;

	private const string ContainerName = "AmbienceGridContainer";

	internal static Slider _sMaster;

	internal static Slider _sWind;

	internal static Slider _sOcean;

	internal static Slider _sAmbientLoop;

	internal static Slider _sShieldHum;

	internal static Slider _sExtraSfx;

	internal static Slider _sExtraClip;

	internal static TextMeshProUGUI _vMaster;

	internal static TextMeshProUGUI _vWind;

	internal static TextMeshProUGUI _vOcean;

	internal static TextMeshProUGUI _vAmbientLoop;

	internal static TextMeshProUGUI _vShieldHum;

	internal static TextMeshProUGUI _vExtraSfx;

	internal static TextMeshProUGUI _vExtraClip;

	private static MethodBase TargetMethod()
	{
		Type type = typeof(AudioSettings);
		MethodBase methodBase = Find("Initialize") ?? Find("Awake") ?? Find("Start");
		if (methodBase != null)
		{
			Debug.Log((object)("[AmbienceSoundConfig] UI inject patching → " + methodBase.Name));
			return methodBase;
		}
		methodBase = Find("LoadSettings");
		if (methodBase != null)
		{
			Debug.Log((object)"[AmbienceSoundConfig] UI inject patching → LoadSettings (legacy fallback for Valheim 0.221.4)");
			return methodBase;
		}
		throw new Exception("[AmbienceSoundConfig] No compatible AudioSettings method found to patch.");
		MethodBase Find(string name)
		{
			return type.GetMethod(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		}
	}

	[HarmonyPostfix]
	private static void Postfix_LoadSettings(AudioSettings __instance)
	{
		//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fe: Expected O, but got Unknown
		//IL_0156: Unknown result type (might be due to invalid IL or missing references)
		//IL_016d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0184: Unknown result type (might be due to invalid IL or missing references)
		//IL_0191: 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_01b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f0: Expected O, but got Unknown
		//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0214: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if (_built && (Object)(object)_gridContainer != (Object)null)
			{
				SyncUI();
				return;
			}
			Slider value = Traverse.Create((object)__instance).Field("m_musicVolumeSlider").GetValue<Slider>();
			GameObject val = ((value != null) ? ((Component)value).gameObject : null);
			if ((Object)(object)val == (Object)null)
			{
				Debug.LogWarning((object)"[AmbienceSoundConfig] Could not get m_musicVolumeSlider.");
				return;
			}
			Toggle value2 = Traverse.Create((object)__instance).Field("m_continousMusic").GetValue<Toggle>();
			Transform val2 = ((value2 != null) ? ((Component)value2).transform.parent : null) ?? val.transform.parent;
			Transform val3 = val2.Find("AmbienceGridContainer");
			if ((Object)(object)val3 != (Object)null)
			{
				Object.DestroyImmediate((Object)(object)((Component)val3).gameObject);
			}
			GameObject val4 = new GameObject("AmbienceGridContainer", new Type[3]
			{
				typeof(RectTransform),
				typeof(GridLayoutGroup),
				typeof(ContentSizeFitter)
			});
			val4.transform.SetParent(val2, false);
			int siblingIndex = (((Object)(object)value2 != (Object)null) ? ((Component)value2).transform.GetSiblingIndex() : val.transform.GetSiblingIndex()) + 1;
			val4.transform.SetSiblingIndex(siblingIndex);
			RectTransform component = val4.GetComponent<RectTransform>();
			component.anchorMin = new Vector2(0f, 1f);
			component.anchorMax = new Vector2(1f, 1f);
			component.pivot = new Vector2(0.5f, 1f);
			component.offsetMin = Vector2.zero;
			component.offsetMax = Vector2.zero;
			component.anchoredPosition = new Vector2(0f, 0f);
			component.sizeDelta = new Vector2(0f, 0f);
			GridLayoutGroup component2 = val4.GetComponent<GridLayoutGroup>();
			((LayoutGroup)component2).padding = new RectOffset(0, 0, 0, 0);
			component2.cellSize = new Vector2(300f, 20f);
			component2.spacing = new Vector2(0f, 8f);
			component2.constraint = (Constraint)1;
			component2.constraintCount = 1;
			((LayoutGroup)component2).childAlignment = (TextAnchor)0;
			ContentSizeFitter component3 = val4.GetComponent<ContentSizeFitter>();
			component3.verticalFit = (FitMode)2;
			component3.horizontalFit = (FitMode)0;
			_gridContainer = val4.transform;
			BindOrCreateSliders(_gridContainer, val);
			SyncUI();
			_built = true;
			LayoutRebuilder.ForceRebuildLayoutImmediate(((Component)val2).GetComponent<RectTransform>());
			Debug.Log((object)"[AmbienceSoundConfig] AmbienceGridContainer built and anchored to top (no drift).");
		}
		catch (Exception ex)
		{
			Debug.LogError((object)("[AmbienceSoundConfig] LoadSettings patch failed: " + ex));
		}
	}

	private static void BindOrCreateSliders(Transform container, GameObject baseSlider)
	{
		CreateOrBind(container, baseSlider, "Ambience Master Volume", ref _sMaster, ref _vMaster, AmbienceSoundConfig.MasterVolume, delegate
		{
			AmbienceSoundConfig.ApplyAllVolumes();
		});
		CreateOrBind(container, baseSlider, "Wind Volume", ref _sWind, ref _vWind, AmbienceSoundConfig.WindVolume, delegate
		{
			AudioMan_AmbienceVolume_Patch.ApplyWindVolumeWrapper();
		});
		CreateOrBind(container, baseSlider, "Ocean Volume", ref _sOcean, ref _vOcean, AmbienceSoundConfig.OceanVolume, delegate
		{
			AudioMan_AmbienceVolume_Patch.ApplyOceanVolumeWrapper();
		});
		CreateOrBind(container, baseSlider, "Ambient Loop Volume", ref _sAmbientLoop, ref _vAmbientLoop, AmbienceSoundConfig.AmbientLoopVolume, delegate
		{
			AudioMan_AmbienceVolume_Patch.ApplyAmbientLoopVolumeWrapper();
		});
		CreateOrBind(container, baseSlider, "Shield Hum Volume", ref _sShieldHum, ref _vShieldHum, AmbienceSoundConfig.ShieldHumVolume, delegate
		{
			AudioMan_AmbienceVolume_Patch.ApplyShieldHumVolumeWrapper();
		});
		CreateOrBind(container, baseSlider, "Extra SFX Volume", ref _sExtraSfx, ref _vExtraSfx, AmbienceSoundConfig.ExtraSfxVolume, delegate
		{
			AudioSourceFilter.Refresh();
		});
		CreateOrBind(container, baseSlider, "Extra Clip Volume", ref _sExtraClip, ref _vExtraClip, AmbienceSoundConfig.ExtraClipVolume, delegate
		{
			AudioSourceFilter.Refresh();
		});
	}

	internal static void CreateOrBind(Transform parent, GameObject baseSlider, string labelText, ref Slider sliderRef, ref TextMeshProUGUI valueTextRef, ConfigEntry<float> config, Action<float> onChanged)
	{
		//IL_0061: 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_008b: Unknown result type (might be due to invalid IL or missing references)
		string text = "Ambience_" + labelText.Replace(" ", "");
		Transform val2 = parent.Find(text);
		GameObject val3;
		if ((Object)(object)val2 == (Object)null)
		{
			val3 = Object.Instantiate<GameObject>(baseSlider, parent);
			((Object)val3).name = text;
			val3.transform.localScale = Vector3.one;
			val3.SetActive(true);
			RectTransform component = val3.GetComponent<RectTransform>();
			((Transform)component).localPosition = Vector3.zero;
			((Transform)component).localRotation = Quaternion.identity;
			TextMeshProUGUI[] componentsInChildren = val3.GetComponentsInChildren<TextMeshProUGUI>(true);
			foreach (TextMeshProUGUI val4 in componentsInChildren)
			{
				if (!((Object)(object)((TMP_Text)val4).font == (Object)null))
				{
					continue;
				}
				TextMeshProUGUI componentInChildren = baseSlider.GetComponentInChildren<TextMeshProUGUI>(true);
				if ((Object)(object)componentInChildren != (Object)null && (Object)(object)((TMP_Text)componentInChildren).font != (Object)null)
				{
					((TMP_Text)val4).font = ((TMP_Text)componentInChildren).font;
					((TMP_Text)val4).fontSharedMaterial = ((TMP_Text)componentInChildren).fontSharedMaterial;
					continue;
				}
				TMP_FontAsset[] array = Resources.FindObjectsOfTypeAll<TMP_FontAsset>();
				if (array.Length != 0)
				{
					((TMP_Text)val4).font = array[0];
				}
			}
		}
		else
		{
			val3 = ((Component)val2).gameObject;
		}
		Slider componentInChildren2 = val3.GetComponentInChildren<Slider>(true);
		if ((Object)(object)componentInChildren2 == (Object)null)
		{
			Debug.LogError((object)("[AmbienceSoundConfig] Slider missing for " + labelText));
			return;
		}
		TextMeshProUGUI val5 = null;
		TextMeshProUGUI valueText = null;
		TextMeshProUGUI[] componentsInChildren2 = val3.GetComponentsInChildren<TextMeshProUGUI>(true);
		foreach (TextMeshProUGUI val6 in componentsInChildren2)
		{
			string text2 = ((Object)val6).name.ToLowerInvariant();
			if (text2.Contains("value"))
			{
				valueText = val6;
			}
			else if (text2.Contains("text") || text2.Contains("label"))
			{
				val5 = val6;
			}
		}
		if ((Object)(object)val5 != (Object)null)
		{
			((TMP_Text)val5).text = labelText;
			((TMP_Text)val5).enableAutoSizing = true;
			((TMP_Text)val5).fontSizeMin = 10f;
			((TMP_Text)val5).fontSizeMax = 14f;
			((Graphic)val5).raycastTarget = false;
		}
		if ((Object)(object)valueText != (Object)null)
		{
			((Graphic)valueText).raycastTarget = false;
			((TMP_Text)valueText).text = $"{Mathf.RoundToInt(config.Value * 100f)}%";
		}
		componentInChildren2.minValue = 0f;
		componentInChildren2.maxValue = 1f;
		((UnityEventBase)componentInChildren2.onValueChanged).RemoveAllListeners();
		((UnityEvent<float>)(object)componentInChildren2.onValueChanged).AddListener((UnityAction<float>)delegate(float val)
		{
			config.Value = val;
			((ConfigEntryBase)config).ConfigFile.Save();
			if ((Object)(object)valueText != (Object)null)
			{
				((TMP_Text)valueText).text = $"{Mathf.RoundToInt(val * 100f)}%";
			}
			onChanged?.Invoke(val);
		});
		sliderRef = componentInChildren2;
		valueTextRef = valueText;
		componentInChildren2.value = config.Value;
	}

	public static void SyncUI()
	{
		try
		{
			if ((Object)(object)_gridContainer == (Object)null || (Object)(object)((Component)_gridContainer).gameObject == (Object)null)
			{
				return;
			}
			if ((Object)(object)_sMaster != (Object)null)
			{
				_sMaster.SetValueWithoutNotify(AmbienceSoundConfig.MasterVolume.Value);
				if ((Object)(object)_vMaster != (Object)null)
				{
					((TMP_Text)_vMaster).text = $"{Mathf.RoundToInt(_sMaster.value * 100f)}%";
				}
			}
			if ((Object)(object)_sWind != (Object)null)
			{
				_sWind.SetValueWithoutNotify(AmbienceSoundConfig.WindVolume.Value);
				if ((Object)(object)_vWind != (Object)null)
				{
					((TMP_Text)_vWind).text = $"{Mathf.RoundToInt(_sWind.value * 100f)}%";
				}
			}
			if ((Object)(object)_sOcean != (Object)null)
			{
				_sOcean.SetValueWithoutNotify(AmbienceSoundConfig.OceanVolume.Value);
				if ((Object)(object)_vOcean != (Object)null)
				{
					((TMP_Text)_vOcean).text = $"{Mathf.RoundToInt(_sOcean.value * 100f)}%";
				}
			}
			if ((Object)(object)_sAmbientLoop != (Object)null)
			{
				_sAmbientLoop.SetValueWithoutNotify(AmbienceSoundConfig.AmbientLoopVolume.Value);
				if ((Object)(object)_vAmbientLoop != (Object)null)
				{
					((TMP_Text)_vAmbientLoop).text = $"{Mathf.RoundToInt(_sAmbientLoop.value * 100f)}%";
				}
			}
			if ((Object)(object)_sShieldHum != (Object)null)
			{
				_sShieldHum.SetValueWithoutNotify(AmbienceSoundConfig.ShieldHumVolume.Value);
				if ((Object)(object)_vShieldHum != (Object)null)
				{
					((TMP_Text)_vShieldHum).text = $"{Mathf.RoundToInt(_sShieldHum.value * 100f)}%";
				}
			}
			if ((Object)(object)_sExtraSfx != (Object)null)
			{
				_sExtraSfx.SetValueWithoutNotify(AmbienceSoundConfig.ExtraSfxVolume.Value);
				if ((Object)(object)_vExtraSfx != (Object)null)
				{
					((TMP_Text)_vExtraSfx).text = $"{Mathf.RoundToInt(_sExtraSfx.value * 100f)}%";
				}
			}
			if ((Object)(object)_sExtraClip != (Object)null)
			{
				_sExtraClip.SetValueWithoutNotify(AmbienceSoundConfig.ExtraClipVolume.Value);
				if ((Object)(object)_vExtraClip != (Object)null)
				{
					((TMP_Text)_vExtraClip).text = $"{Mathf.RoundToInt(_sExtraClip.value * 100f)}%";
				}
			}
		}
		catch (Exception ex)
		{
			Debug.LogError((object)("[AmbienceSoundConfig] SyncUI failed: " + ex));
		}
	}

	private static GameObject FindDeepChild(Transform parent, string name)
	{
		Transform val = FindDeepChildTransform(parent, name);
		return Object.op_Implicit((Object)(object)val) ? ((Component)val).gameObject : null;
	}

	private static Transform FindDeepChildTransform(Transform parent, string name)
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Expected O, but got Unknown
		foreach (Transform item in parent)
		{
			Transform val = item;
			if (((Object)val).name == name)
			{
				return val;
			}
			Transform val2 = FindDeepChildTransform(val, name);
			if ((Object)(object)val2 != (Object)null)
			{
				return val2;
			}
		}
		return null;
	}
}
internal static class SoundPlayLogger
{
	private static readonly HashSet<string> _seen = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

	private static string _logPath;

	internal static void Init(ConfigFile config)
	{
		try
		{
			string directoryName = Path.GetDirectoryName(config.ConfigFilePath);
			_logPath = Path.Combine(directoryName, "AmbienceSoundConfig_SoundLog.txt");
		}
		catch
		{
			_logPath = Path.Combine(Paths.ConfigPath, "AmbienceSoundConfig_SoundLog.txt");
		}
	}

	internal static void Log(string type, string name, GameObject go = null)
	{
		if (!AmbienceSoundConfig.EnableSoundLogging.Value || string.IsNullOrEmpty(name) || (AmbienceSoundConfig.LogOnlyUnique.Value && !_seen.Add(type + "|" + name)))
		{
			return;
		}
		string text = DateTime.Now.ToString("HH:mm:ss.fff");
		string text2 = (((Object)(object)go != (Object)null) ? ("[" + text + "] " + type + ": " + name + " @ " + ((Object)go).name) : ("[" + text + "] " + type + ": " + name));
		Debug.Log((object)("[ASC-LOG] " + text2));
		try
		{
			File.AppendAllText(_logPath, text2 + Environment.NewLine);
		}
		catch
		{
		}
	}
}
[HarmonyPatch(typeof(ZSFX))]
internal static class ZSFX_VolumeScale_Patch
{
	[HarmonyPostfix]
	[HarmonyPatch("CustomUpdate")]
	private static void Postfix(ZSFX __instance)
	{
		if (!AudioSourceFilter.HasClipTargets)
		{
			return;
		}
		AudioSource component = ((Component)__instance).GetComponent<AudioSource>();
		if (!((Object)(object)component == (Object)null) && !((Object)(object)component.clip == (Object)null))
		{
			if (component.isPlaying)
			{
				SoundPlayLogger.Log("ZSFX", ((Object)component.clip).name, ((Component)__instance).gameObject);
			}
			float num = 1f;
			if (AudioSourceFilter.ShouldMuteClip(component.clip))
			{
				num = AudioSourceFilter.ClipMultiplier;
			}
			__instance.SetVolumeModifier((num <= 0f) ? 0f : num);
		}
	}
}