Please disclose if any significant portion of your mod was created 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 IsMyFriendAlive v0.2.0
IsMyFriendAlive.dll
Decompiled a month agousing System; using System.Collections; 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 System.Threading; using BepInEx; using BepInEx.Configuration; using GameNetcodeStuff; using HarmonyLib; using UnityEngine; using UnityEngine.Networking; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("IsMyFriendAlive")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("IsMyFriendAlive")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("ab5d31f5-840a-470f-ad43-cd5fe63dcbe7")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("1.0.0.0")] namespace IsMyFriendAlive; [BepInPlugin("thunder.deathsounds", "Is My Friend Alive", "0.2.0")] public class DeathSoundPlugin : BaseUnityPlugin { [CompilerGenerated] private sealed class <RestoreVolumeAfterDelay>d__14 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public float delay; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <RestoreVolumeAfterDelay>d__14(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(delay); <>1__state = 1; return true; case 1: <>1__state = -1; AudioListener.volume = originalListenerVolume; isVolumeDucked = false; restoreCoroutine = null; return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private static ConfigEntry<float> SoundVolume; private static ConfigEntry<float> MainVolumeDecrease; private static List<AudioClip> deathSounds = new List<AudioClip>(); private static AudioSource audioSource; private static float originalListenerVolume = 1f; private static bool isVolumeDucked = false; private static Coroutine restoreCoroutine; private static MonoBehaviour coroutineRunner; public static Dictionary<PlayerControllerB, bool> lastDeathState = new Dictionary<PlayerControllerB, bool>(); 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_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Expected O, but got Unknown SoundVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Audio", "Volume", 1f, new ConfigDescription("Thunder Sound Volume", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); MainVolumeDecrease = ((BaseUnityPlugin)this).Config.Bind<float>("Audio", "Game Volume", 0.2f, new ConfigDescription("How loud will the game main volume be when playing Thunderstorm Sound(0.2 means 20% from current value)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); audioSource = ((Component)this).gameObject.GetComponent<AudioSource>() ?? ((Component)this).gameObject.AddComponent<AudioSource>(); audioSource.spatialBlend = 0f; audioSource.volume = SoundVolume.Value; audioSource.playOnAwake = false; audioSource.ignoreListenerVolume = true; if ((Object)(object)coroutineRunner == (Object)null) { coroutineRunner = (MonoBehaviour)(object)this; } LoadAllSounds(); Harmony val = new Harmony("thunder.deathsounds"); val.PatchAll(typeof(DeathPatch)); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"IsMyFriendAlive Loaded, Sounds: {deathSounds.Count}"); } private void LoadAllSounds() { string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); if (!Directory.Exists(directoryName)) { ((BaseUnityPlugin)this).Logger.LogError((object)("FolderIsMissing: " + directoryName)); return; } string[] files = Directory.GetFiles(directoryName, "*.wav"); string[] array = files; foreach (string text in array) { if (!text.EndsWith(".dll")) { string fileName = Path.GetFileName(text); AudioClip val = LoadWavSync(text); if ((Object)(object)val != (Object)null) { deathSounds.Add(val); } } } } private AudioClip LoadWavSync(string filePath) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Invalid comparison between Unknown and I4 try { UnityWebRequest audioClip = UnityWebRequestMultimedia.GetAudioClip("file:///" + filePath, (AudioType)20); try { UnityWebRequestAsyncOperation val = audioClip.SendWebRequest(); while (!((AsyncOperation)val).isDone) { Thread.Sleep(10); } if ((int)audioClip.result == 1) { AudioClip content = DownloadHandlerAudioClip.GetContent(audioClip); ((Object)content).name = Path.GetFileName(filePath); return content; } ((BaseUnityPlugin)this).Logger.LogError((object)("Error loading WAV: " + audioClip.error)); return null; } finally { ((IDisposable)audioClip)?.Dispose(); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Exception loading WAV: " + ex.Message)); return null; } } public static void PlayRandomSound() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown if ((Object)(object)audioSource == (Object)null) { GameObject val = new GameObject("DeathSoundSource"); Object.DontDestroyOnLoad((Object)(object)val); audioSource = val.AddComponent<AudioSource>(); audioSource.spatialBlend = 0f; audioSource.ignoreListenerVolume = true; } EnsureCoroutineRunner(); if (deathSounds == null || deathSounds.Count == 0) { Debug.LogError((object)$"[IsMyFriendAlive] No sounds! Count: {deathSounds?.Count ?? 0}"); return; } AudioClip val2 = deathSounds[Random.Range(0, deathSounds.Count)]; if ((Object)(object)val2 == (Object)null) { Debug.LogError((object)"[IsMyFriendAlive] Selected clip is null!"); return; } if (!isVolumeDucked) { originalListenerVolume = AudioListener.volume; AudioListener.volume = originalListenerVolume * MainVolumeDecrease.Value; isVolumeDucked = true; } if (audioSource.isPlaying) { audioSource.Stop(); } if (restoreCoroutine != null && (Object)(object)coroutineRunner != (Object)null) { coroutineRunner.StopCoroutine(restoreCoroutine); restoreCoroutine = null; } audioSource.clip = val2; audioSource.volume = SoundVolume.Value; audioSource.Play(); if ((Object)(object)coroutineRunner != (Object)null) { restoreCoroutine = coroutineRunner.StartCoroutine(RestoreVolumeAfterDelay(val2.length)); return; } AudioListener.volume = originalListenerVolume; isVolumeDucked = false; } private static void EnsureCoroutineRunner() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown if ((Object)(object)coroutineRunner == (Object)null) { GameObject val = new GameObject("DeathSoundCoroutineRunner"); Object.DontDestroyOnLoad((Object)(object)val); coroutineRunner = (MonoBehaviour)(object)val.AddComponent<EmptyMonoBehaviour>(); } } [IteratorStateMachine(typeof(<RestoreVolumeAfterDelay>d__14))] private static IEnumerator RestoreVolumeAfterDelay(float delay) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <RestoreVolumeAfterDelay>d__14(0) { delay = delay }; } } internal class EmptyMonoBehaviour : MonoBehaviour { } [HarmonyPatch(typeof(PlayerControllerB))] internal static class DeathPatch { [HarmonyPostfix] [HarmonyPatch("Update")] private static void OnUpdate(PlayerControllerB __instance) { if (!((Object)(object)__instance == (Object)null) && !((Object)(object)GameNetworkManager.Instance == (Object)null)) { bool isPlayerDead = __instance.isPlayerDead; if (!DeathSoundPlugin.lastDeathState.TryGetValue(__instance, out var value)) { value = false; } if (!value && isPlayerDead) { DeathSoundPlugin.PlayRandomSound(); } DeathSoundPlugin.lastDeathState[__instance] = isPlayerDead; } } }