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);
}
}
}