The BepInEx console will not appear when launching like it does for other games on Thunderstore (you can turn it back on in your BepInEx.cfg file). If your PEAK crashes on startup, add -dx12 to your launch parameters.
Decompiled source of Stamina Panic v1.0.4
tony4twentys-Stamina Panic.dll
Decompiled 3 days agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using UnityEngine; using UnityEngine.Audio; using UnityEngine.Networking; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("Stamina Panic")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("Stamina Panic")] [assembly: AssemblyCopyright("Copyright © 2025")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("f3d2d2cf-e3bd-4b0f-a0ba-2082998aceb8")] [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 StaminaPanic; [BepInPlugin("tony4twentys.Stamina_Panic", "Stamina Panic", "1.0.3")] [HarmonyPatch(typeof(RunManager), "Awake")] public class StaminaPanic : BaseUnityPlugin { [CompilerGenerated] private sealed class <CheckStaminaLoop>d__21 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public StaminaPanic <>4__this; private CharacterData <playerData>5__1; private bool <isDown>5__2; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <CheckStaminaLoop>d__21(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <playerData>5__1 = null; <>1__state = -2; } private bool MoveNext() { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Expected O, but got Unknown //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Expected O, but got Unknown //IL_0374: Unknown result type (might be due to invalid IL or missing references) //IL_037e: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; break; case 1: <>1__state = -1; break; case 2: <>1__state = -1; break; case 3: <>1__state = -1; break; case 4: <>1__state = -1; <playerData>5__1 = null; break; } if (!<>4__this.inGameScene) { <>2__current = (object)new WaitForSeconds(1f); <>1__state = 1; return true; } <playerData>5__1 = ((IEnumerable<CharacterData>)Object.FindObjectsByType<CharacterData>((FindObjectsSortMode)0)).FirstOrDefault((Func<CharacterData, bool>)delegate(CharacterData cd) { Character component = ((Component)cd).GetComponent<Character>(); return component != null && component.IsLocal; }); if ((Object)(object)<playerData>5__1 == (Object)null) { <>2__current = (object)new WaitForSeconds(1f); <>1__state = 2; return true; } <isDown>5__2 = !<playerData>5__1.fullyConscious; if (<isDown>5__2) { if (<>4__this.audioSource.isPlaying && !<>4__this.isFadingOut) { if (<>4__this.fadeOutCoroutine != null) { ((MonoBehaviour)<>4__this).StopCoroutine(<>4__this.fadeOutCoroutine); } <>4__this.fadeOutCoroutine = ((MonoBehaviour)<>4__this).StartCoroutine(<>4__this.FadeOutAndStop()); } <>4__this.suppressedUntilConscious = true; <>4__this.isBelowThreshold = false; <>2__current = (object)new WaitForSeconds(1f); <>1__state = 3; return true; } if (<>4__this.suppressedUntilConscious && <playerData>5__1.fullyConscious) { <>4__this.suppressedUntilConscious = false; } <>4__this.audioSource.volume = Mathf.Clamp(<>4__this.volumeConfig.Value, 0f, 100f) / 100f; if (!<>4__this.suppressedUntilConscious && <playerData>5__1.TotalStamina <= <>4__this.thresholdConfig.Value) { if (!<>4__this.isBelowThreshold && !<>4__this.isFadingOut) { if (<>4__this.fadeOutCoroutine != null) { ((MonoBehaviour)<>4__this).StopCoroutine(<>4__this.fadeOutCoroutine); } <>4__this.audioSource.volume = Mathf.Clamp(<>4__this.volumeConfig.Value, 0f, 100f) / 100f; <>4__this.audioSource.Play(); <>4__this.isBelowThreshold = true; } } else if (<>4__this.isBelowThreshold) { if (<>4__this.fadeOutCoroutine != null) { ((MonoBehaviour)<>4__this).StopCoroutine(<>4__this.fadeOutCoroutine); } <>4__this.fadeOutCoroutine = ((MonoBehaviour)<>4__this).StartCoroutine(<>4__this.FadeOutAndStop()); <>4__this.isBelowThreshold = false; } <>2__current = (object)new WaitForSeconds(1f); <>1__state = 4; 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 <DelayedStartup>d__17 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public StaminaPanic <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <DelayedStartup>d__17(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(30f); <>1__state = 1; return true; case 1: <>1__state = -1; <>2__current = <>4__this.LoadAudioFromPluginDirectory(); <>1__state = 2; return true; case 2: <>1__state = -1; 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(); } } [CompilerGenerated] private sealed class <FadeOutAndStop>d__20 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public StaminaPanic <>4__this; private float <startVolume>5__1; private float <time>5__2; private float <duration>5__3; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <FadeOutAndStop>d__20(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>4__this.isFadingOut = true; <startVolume>5__1 = <>4__this.audioSource.volume; <time>5__2 = 0f; <duration>5__3 = <>4__this.fadeOutTimeConfig.Value; break; case 1: <>1__state = -1; break; } if (<time>5__2 < <duration>5__3) { <time>5__2 += Time.deltaTime; <>4__this.audioSource.volume = Mathf.Lerp(<startVolume>5__1, 0f, <time>5__2 / <duration>5__3); <>2__current = null; <>1__state = 1; return true; } <>4__this.audioSource.Stop(); <>4__this.audioSource.volume = Mathf.Clamp(<>4__this.volumeConfig.Value, 0f, 100f) / 100f; <>4__this.isFadingOut = false; 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(); } } [CompilerGenerated] private sealed class <LoadAudioFromPluginDirectory>d__19 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public StaminaPanic <>4__this; private string <pluginLocation>5__1; private string <pluginDirectory>5__2; private string[] <audioFiles>5__3; private string <soundFile>5__4; private string <url>5__5; private AudioType <audioType>5__6; private UnityWebRequest <www>5__7; private AudioMixerGroup <gameMixerGroup>5__8; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <LoadAudioFromPluginDirectory>d__19(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } <pluginLocation>5__1 = null; <pluginDirectory>5__2 = null; <audioFiles>5__3 = null; <soundFile>5__4 = null; <url>5__5 = null; <www>5__7 = null; <gameMixerGroup>5__8 = null; <>1__state = -2; } private bool MoveNext() { //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Invalid comparison between Unknown and I4 //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_025a: Unknown result type (might be due to invalid IL or missing references) //IL_0264: Expected O, but got Unknown bool result; try { switch (<>1__state) { default: result = false; break; case 0: <>1__state = -1; <pluginLocation>5__1 = ((BaseUnityPlugin)<>4__this).Info.Location; <pluginDirectory>5__2 = Path.GetDirectoryName(<pluginLocation>5__1); ((BaseUnityPlugin)<>4__this).Logger.LogInfo((object)("=== STAMINA PANIC: Looking for audio files in: " + <pluginDirectory>5__2 + " ===")); <audioFiles>5__3 = Directory.GetFiles(<pluginDirectory>5__2, "*.ogg", SearchOption.AllDirectories).Concat(Directory.GetFiles(<pluginDirectory>5__2, "*.wav", SearchOption.AllDirectories)).ToArray(); if (<audioFiles>5__3.Length == 0) { ((BaseUnityPlugin)<>4__this).Logger.LogWarning((object)("=== STAMINA PANIC: No .wav or .ogg files found in " + <pluginDirectory>5__2 + " ===")); ((BaseUnityPlugin)<>4__this).Logger.LogInfo((object)"=== STAMINA PANIC: Audio will be disabled - plugin will work without sound ==="); result = false; break; } <soundFile>5__4 = <audioFiles>5__3[0]; ((BaseUnityPlugin)<>4__this).Logger.LogInfo((object)("=== STAMINA PANIC: Loading audio from " + <soundFile>5__4 + " ===")); <url>5__5 = "file://" + Path.GetFullPath(<soundFile>5__4).Replace("\\", "/"); <audioType>5__6 = (AudioType)(<soundFile>5__4.EndsWith(".ogg") ? 14 : 20); <www>5__7 = UnityWebRequestMultimedia.GetAudioClip(<url>5__5, <audioType>5__6); <>1__state = -3; <>2__current = <www>5__7.SendWebRequest(); <>1__state = 1; result = true; break; case 1: <>1__state = -3; if ((int)<www>5__7.result != 1) { ((BaseUnityPlugin)<>4__this).Logger.LogError((object)("=== STAMINA PANIC: Failed to load audio: " + <www>5__7.error + " ===")); result = false; } else { <>4__this.cueClip = DownloadHandlerAudioClip.GetContent(<www>5__7); if (!((Object)(object)<>4__this.cueClip == (Object)null)) { <>4__this.audioHost = new GameObject("StaminaPanicAudioHost"); <>4__this.audioSource = <>4__this.audioHost.AddComponent<AudioSource>(); <>4__this.audioSource.clip = <>4__this.cueClip; <>4__this.audioSource.loop = true; <>4__this.audioSource.playOnAwake = false; <>4__this.audioSource.spatialBlend = 0f; <>4__this.audioSource.dopplerLevel = 0f; <>4__this.audioSource.rolloffMode = (AudioRolloffMode)1; <>4__this.audioSource.minDistance = 1f; <>4__this.audioSource.maxDistance = 500f; <>4__this.audioSource.ignoreListenerPause = true; <>4__this.audioSource.bypassEffects = false; <>4__this.audioSource.bypassListenerEffects = false; <>4__this.audioSource.bypassReverbZones = true; <gameMixerGroup>5__8 = TryGetGameMixerGroup(); if ((Object)(object)<gameMixerGroup>5__8 != (Object)null) { <>4__this.audioSource.outputAudioMixerGroup = <gameMixerGroup>5__8; } Object.DontDestroyOnLoad((Object)(object)<>4__this.audioHost); ((BaseUnityPlugin)<>4__this).Logger.LogInfo((object)"=== STAMINA PANIC: Audio loaded successfully ==="); if (<>4__this.staminaCoroutine != null) { ((MonoBehaviour)<>4__this).StopCoroutine(<>4__this.staminaCoroutine); } <>4__this.staminaCoroutine = ((MonoBehaviour)<>4__this).StartCoroutine(<>4__this.CheckStaminaLoop()); <gameMixerGroup>5__8 = null; <>m__Finally1(); <www>5__7 = null; result = false; break; } ((BaseUnityPlugin)<>4__this).Logger.LogError((object)"=== STAMINA PANIC: Failed to create audio clip ==="); result = false; } <>m__Finally1(); break; } } catch { //try-fault ((IDisposable)this).Dispose(); throw; } return result; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<www>5__7 != null) { ((IDisposable)<www>5__7).Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private static StaminaPanic instance; private GameObject audioHost; private AudioSource audioSource; private AudioClip cueClip; private ConfigEntry<float> thresholdConfig; private ConfigEntry<float> volumeConfig; private ConfigEntry<float> fadeOutTimeConfig; private bool isBelowThreshold = false; private bool inGameScene = false; private Coroutine staminaCoroutine; private Coroutine startCoroutine; private Coroutine fadeOutCoroutine; private bool isFadingOut; private bool suppressedUntilConscious; private void Awake() { //IL_008d: Unknown result type (might be due to invalid IL or missing references) instance = this; thresholdConfig = ((BaseUnityPlugin)this).Config.Bind<float>("General", "StaminaThreshold", 0.2f, "Value of TotalStamina that triggers the sound (0.0 to 1.0)"); volumeConfig = ((BaseUnityPlugin)this).Config.Bind<float>("General", "CueVolume", 100f, "Volume level for the audio cue (0 to 100)"); fadeOutTimeConfig = ((BaseUnityPlugin)this).Config.Bind<float>("General", "FadeOutTime", 1.5f, "Time in seconds to fade out the audio when stamina recovers"); SceneManager.activeSceneChanged += OnSceneChanged; new Harmony("tony4twentys.Stamina_Panic").PatchAll(); } private void OnSceneChanged(Scene oldScene, Scene newScene) { inGameScene = ((Scene)(ref newScene)).name.StartsWith("Level_"); if (!inGameScene) { ((MonoBehaviour)this).StopAllCoroutines(); if ((Object)(object)audioSource != (Object)null && audioSource.isPlaying) { audioSource.Stop(); } isBelowThreshold = false; isFadingOut = false; suppressedUntilConscious = false; } } [HarmonyPostfix] private static void RunManager_Awake_Postfix() { if (instance.startCoroutine != null) { ((MonoBehaviour)instance).StopCoroutine(instance.startCoroutine); } instance.startCoroutine = ((MonoBehaviour)instance).StartCoroutine(instance.DelayedStartup()); } [IteratorStateMachine(typeof(<DelayedStartup>d__17))] private IEnumerator DelayedStartup() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <DelayedStartup>d__17(0) { <>4__this = this }; } private static AudioMixerGroup TryGetGameMixerGroup() { AudioSource val = ((IEnumerable<AudioSource>)Object.FindObjectsByType<AudioSource>((FindObjectsSortMode)0)).FirstOrDefault((Func<AudioSource, bool>)((AudioSource a) => (Object)(object)a != (Object)null && ((Behaviour)a).isActiveAndEnabled && (Object)(object)a.outputAudioMixerGroup != (Object)null)); return ((Object)(object)val != (Object)null) ? val.outputAudioMixerGroup : null; } [IteratorStateMachine(typeof(<LoadAudioFromPluginDirectory>d__19))] private IEnumerator LoadAudioFromPluginDirectory() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <LoadAudioFromPluginDirectory>d__19(0) { <>4__this = this }; } [IteratorStateMachine(typeof(<FadeOutAndStop>d__20))] private IEnumerator FadeOutAndStop() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <FadeOutAndStop>d__20(0) { <>4__this = this }; } [IteratorStateMachine(typeof(<CheckStaminaLoop>d__21))] private IEnumerator CheckStaminaLoop() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <CheckStaminaLoop>d__21(0) { <>4__this = this }; } }