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 FortunateSonEndGameSong v1.0.0
Plugins/FortunateSonPeak/com.github.aleasdev.fortunatesonpeak.dll
Decompiled 3 weeks 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.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.Audio; using UnityEngine.Networking; using Zorro.Core; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("com.github.aleasdev.fortunatesonpeak")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("0.1.0.0")] [assembly: AssemblyInformationalVersion("0.1.0+d6929056e576ac0c1006a0e5fb2ffda587a72f14")] [assembly: AssemblyProduct("com.github.aleasdev.fortunatesonpeak")] [assembly: AssemblyTitle("fortunatesonpeak")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.1.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace BepInEx { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] [Conditional("CodeGeneration")] internal sealed class BepInAutoPluginAttribute : Attribute { public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null) { } } } namespace BepInEx.Preloader.Core.Patching { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] [Conditional("CodeGeneration")] internal sealed class PatcherAutoPluginAttribute : Attribute { public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null) { } } } namespace fortunatesonpeak { public static class AudioHandler { [CompilerGenerated] private sealed class <LoadWavFile>d__9 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public string path; private UnityWebRequest <www>5__1; object? IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object? IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <LoadWavFile>d__9(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(); } } <www>5__1 = null; <>1__state = -2; } private bool MoveNext() { //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Invalid comparison between Unknown and I4 //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Invalid comparison between Unknown and I4 try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <www>5__1 = UnityWebRequestMultimedia.GetAudioClip("file://" + path, (AudioType)20); <>1__state = -3; <>2__current = <www>5__1.SendWebRequest(); <>1__state = 1; return true; case 1: <>1__state = -3; if ((int)<www>5__1.result == 2 || (int)<www>5__1.result == 3) { FortunateSonPeakPlugin.Log.LogError((object)("Error al cargar audio: " + <www>5__1.error)); } else { FortunateSonClip = DownloadHandlerAudioClip.GetContent(<www>5__1); if ((Object)(object)FortunateSonClip != (Object)null) { FortunateSonPeakPlugin.Log.LogInfo((object)"Audio 'fortunateson.wav' cargado correctamente."); } else { FortunateSonPeakPlugin.Log.LogError((object)"No se pudo obtener el contenido del AudioClip desde el archivo WAV."); } } <>m__Finally1(); <www>5__1 = null; 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; if (<www>5__1 != null) { ((IDisposable)<www>5__1).Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <StopAudioWithFade>d__11 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public AudioSource audioSource; public float fadeDuration; private float <startVolume>5__1; private float <elapsedTime>5__2; object? IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object? IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <StopAudioWithFade>d__11(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; <startVolume>5__1 = audioSource.volume; <elapsedTime>5__2 = 0f; break; case 1: <>1__state = -1; break; } if (<elapsedTime>5__2 < fadeDuration) { <elapsedTime>5__2 += Time.unscaledDeltaTime; audioSource.volume = Mathf.Lerp(<startVolume>5__1, 0f, <elapsedTime>5__2 / fadeDuration); <>2__current = null; <>1__state = 1; return true; } audioSource.Stop(); audioSource.volume = <startVolume>5__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(); } } public static AudioClip? FortunateSonClip { get; private set; } public static GameObject? CurrentAudioPlayer { get; set; } public static void LoadFortunateSonClip(MonoBehaviour coroutineRunner) { try { string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); string text = Path.Combine(directoryName, "FortunateSon.wav"); if (File.Exists(text)) { coroutineRunner.StartCoroutine(LoadWavFile(text)); } else { FortunateSonPeakPlugin.Log.LogError((object)("¡Error! No se encontró el archivo de audio: " + text)); } } catch (Exception arg) { FortunateSonPeakPlugin.Log.LogError((object)$"Error al cargar el archivo de audio: {arg}"); } } [IteratorStateMachine(typeof(<LoadWavFile>d__9))] private static IEnumerator LoadWavFile(string path) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <LoadWavFile>d__9(0) { path = path }; } public static void PlayFortunateSon() { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected O, but got Unknown if ((Object)(object)FortunateSonClip != (Object)null) { if ((Object)(object)CurrentAudioPlayer != (Object)null) { Object.Destroy((Object)(object)CurrentAudioPlayer); } CurrentAudioPlayer = new GameObject("FortunateSonAudioPlayer"); Object.DontDestroyOnLoad((Object)(object)CurrentAudioPlayer); AudioSource val = CurrentAudioPlayer.AddComponent<AudioSource>(); val.clip = FortunateSonClip; val.loop = true; AudioMixerGroup val2 = ((IEnumerable<AudioMixerGroup>)Resources.FindObjectsOfTypeAll<AudioMixerGroup>()).FirstOrDefault((Func<AudioMixerGroup, bool>)((AudioMixerGroup g) => ((Object)g).name == "Music_Setting")); if ((Object)(object)val2 != (Object)null) { val.outputAudioMixerGroup = val2; val.volume = 0.7f; FortunateSonPeakPlugin.Log.LogInfo((object)"[✔] Asignado a MusicVolumeSetting."); } else if ((Object)(object)SingletonAsset<StaticReferences>.Instance?.masterMixerGroup != (Object)null) { val.outputAudioMixerGroup = SingletonAsset<StaticReferences>.Instance.masterMixerGroup; val.volume = 0.7f; FortunateSonPeakPlugin.Log.LogWarning((object)"[⚠] Usando masterMixerGroup como fallback."); } else { val.volume = 0.7f; FortunateSonPeakPlugin.Log.LogError((object)"[✖] No se encontró ningún AudioMixerGroup."); } val.Play(); FortunateSonPeakPlugin.Log.LogInfo((object)"¡'Fortunate Son' debería estar sonando ahora!"); } else { FortunateSonPeakPlugin.Log.LogWarning((object)"El AudioClip de 'Fortunate Son' no se ha cargado. No se puede reproducir la canción."); } } [IteratorStateMachine(typeof(<StopAudioWithFade>d__11))] public static IEnumerator StopAudioWithFade(AudioSource audioSource, float fadeDuration) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <StopAudioWithFade>d__11(0) { audioSource = audioSource, fadeDuration = fadeDuration }; } } [HarmonyPatch(typeof(GameOverHandler), "LoadAirport")] public static class EndScreenPatch { [HarmonyPostfix] public static void Prefix() { FortunateSonPeakPlugin.Log.LogInfo((object)"¡Parche activado! Deteniendo la música de 'Fortunate Son'..."); if ((Object)(object)AudioHandler.CurrentAudioPlayer != (Object)null) { AudioSource component = AudioHandler.CurrentAudioPlayer.GetComponent<AudioSource>(); if ((Object)(object)component != (Object)null) { if ((Object)(object)FortunateSonPeakPlugin.Instance != (Object)null) { ((MonoBehaviour)FortunateSonPeakPlugin.Instance).StartCoroutine(AudioHandler.StopAudioWithFade(component, 2f)); FortunateSonPeakPlugin.Log.LogInfo((object)"¡Iniciando fade out de la música de 'Fortunate Son'!"); return; } FortunateSonPeakPlugin.Log.LogError((object)"La instancia de FortunateSonPeakPlugin no está disponible para iniciar el fade out. Deteniendo el audio inmediatamente."); component.Stop(); Object.Destroy((Object)(object)AudioHandler.CurrentAudioPlayer); AudioHandler.CurrentAudioPlayer = null; } else { FortunateSonPeakPlugin.Log.LogWarning((object)"No se encontró AudioSource en currentAudioPlayer. Destruyendo inmediatamente."); Object.Destroy((Object)(object)AudioHandler.CurrentAudioPlayer); AudioHandler.CurrentAudioPlayer = null; } } else { FortunateSonPeakPlugin.Log.LogWarning((object)"No hay un reproductor de audio activo para detener la música."); } } } [BepInPlugin("com.aleasdev.fortunatesonpeak", "fortunatesonpeak", "1.0.0")] public class FortunateSonPeakPlugin : BaseUnityPlugin { public static ManualLogSource Log { get; private set; } public static FortunateSonPeakPlugin Instance { get; private set; } private void Awake() { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; Log.LogInfo((object)"fortunatesonpeak plugin is loaded!"); Log.LogInfo((object)"El mod está cargando..."); AudioHandler.LoadFortunateSonClip((MonoBehaviour)(object)this); Harmony val = new Harmony("com.aleasdev.fortunatesonpeak"); val.PatchAll(); Log.LogInfo((object)"¡El mod se ha cargado correctamente!"); } } [HarmonyPatch(typeof(PeakHandler), "SummonHelicopter")] public static class HelicopterSpawnPatch { [HarmonyPrefix] public static void Postfix() { FortunateSonPeakPlugin.Log.LogInfo((object)"¡Parche activado! Intentando reproducir 'Fortunate Son'..."); AudioHandler.PlayFortunateSon(); } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }