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 MithrixChimeraMusic v1.0.2
MithrixChimeraMusic.dll
Decompiled 6 hours agousing System; using System.Collections; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using EntityStates.Missions.BrotherEncounter; using Microsoft.CodeAnalysis; using On.EntityStates.Missions.BrotherEncounter; using On.RoR2; using RoR2; using UnityEngine; using UnityEngine.Networking; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("MithrixChimeraMusic")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("MithrixChimeraMusic")] [assembly: AssemblyTitle("MithrixChimeraMusic")] [assembly: AssemblyVersion("1.0.0.0")] [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.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace MithrixChimeraMusic { [BepInPlugin("com.emerson.mithrixchimeramusic", "Mithrix Chimera Music", "1.0.2")] public class Plugin : BaseUnityPlugin { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static hook_OnEnter <>9__16_0; public static hook_OnEnter <>9__16_1; public static hook_OnEnter <>9__16_2; public static hook_OnEnter <>9__16_3; public static hook_BeginGameOver <>9__16_4; public static hook_Start <>9__16_5; public static Func<Type, bool> <>9__21_0; internal void <Awake>b__16_0(orig_OnEnter orig, Phase1 self) { orig.Invoke(self); OnPhaseEnter("Phase1"); } internal void <Awake>b__16_1(orig_OnEnter orig, Phase2 self) { orig.Invoke(self); OnPhaseEnter("Phase2"); } internal void <Awake>b__16_2(orig_OnEnter orig, Phase3 self) { orig.Invoke(self); OnPhaseEnter("Phase3"); } internal void <Awake>b__16_3(orig_OnEnter orig, Phase4 self) { orig.Invoke(self); OnPhaseEnter("Phase4"); } internal void <Awake>b__16_4(orig_BeginGameOver orig, Run self, GameEndingDef ending) { StopSong(); currentPhase = null; orig.Invoke(self, ending); } internal void <Awake>b__16_5(orig_Start orig, Stage self) { orig.Invoke(self); if (debugPlayOnStageStart.Value) { Log.LogInfo((object)"[Debug] Stage started — triggering song"); StartSong(); } } internal bool <PostWwiseEvent>b__21_0(Type t) { return t.Name == "AkSoundEngine"; } } public const string GUID = "com.emerson.mithrixchimeramusic"; public const string NAME = "Mithrix Chimera Music"; public const string VERSION = "1.0.2"; private const string ResourceName = "MithrixChimeraMusic.intermission.ogg"; internal static ManualLogSource Log; private static AudioClip clip; private static AudioSource source; private static ConfigEntry<string> phaseChoice; private static ConfigEntry<float> volume; private static ConfigEntry<bool> muteGameMusic; private static ConfigEntry<string> pauseEventName; private static ConfigEntry<string> resumeEventName; private static ConfigEntry<bool> debugPlayOnStageStart; private static MethodInfo akPostEvent; private static bool akLookupAttempted; private static string currentPhase; private void Awake() { //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Expected O, but got Unknown //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Expected O, but got Unknown //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Expected O, but got Unknown //IL_0168: 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_0173: Expected O, but got Unknown //IL_018c: 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_0197: Expected O, but got Unknown //IL_01b0: 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_01bb: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; phaseChoice = ((BaseUnityPlugin)this).Config.Bind<string>("General", "PhaseToPlayDuring", "Phase2", "Which Mithrix phase to play during. Valid: Phase1, Phase2, Phase3, Phase4. Watch the BepInEx console — every phase entry is logged so you can verify."); volume = ((BaseUnityPlugin)this).Config.Bind<float>("General", "Volume", 0.7f, "0.0 to 1.0"); muteGameMusic = ((BaseUnityPlugin)this).Config.Bind<bool>("Audio", "MuteGameMusic", true, "Try to pause Wwise music while the song plays. Best-effort — falls back to overlap if the Wwise call fails."); pauseEventName = ((BaseUnityPlugin)this).Config.Bind<string>("Audio", "PauseEventName", "Pause_Music_System", "Wwise event posted on phase enter."); resumeEventName = ((BaseUnityPlugin)this).Config.Bind<string>("Audio", "ResumeEventName", "Resume_Music_System", "Wwise event posted on phase exit."); debugPlayOnStageStart = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "PlayOnStageStart", false, "DEBUG: play the song at the start of every stage instead of waiting for the Mithrix fight. Useful for verifying audio works without grinding to phase 2."); ((MonoBehaviour)this).StartCoroutine(LoadClipCoroutine()); object obj = <>c.<>9__16_0; if (obj == null) { hook_OnEnter val = delegate(orig_OnEnter orig, Phase1 self) { orig.Invoke(self); OnPhaseEnter("Phase1"); }; <>c.<>9__16_0 = val; obj = (object)val; } Phase1.OnEnter += (hook_OnEnter)obj; object obj2 = <>c.<>9__16_1; if (obj2 == null) { hook_OnEnter val2 = delegate(orig_OnEnter orig, Phase2 self) { orig.Invoke(self); OnPhaseEnter("Phase2"); }; <>c.<>9__16_1 = val2; obj2 = (object)val2; } Phase2.OnEnter += (hook_OnEnter)obj2; object obj3 = <>c.<>9__16_2; if (obj3 == null) { hook_OnEnter val3 = delegate(orig_OnEnter orig, Phase3 self) { orig.Invoke(self); OnPhaseEnter("Phase3"); }; <>c.<>9__16_2 = val3; obj3 = (object)val3; } Phase3.OnEnter += (hook_OnEnter)obj3; object obj4 = <>c.<>9__16_3; if (obj4 == null) { hook_OnEnter val4 = delegate(orig_OnEnter orig, Phase4 self) { orig.Invoke(self); OnPhaseEnter("Phase4"); }; <>c.<>9__16_3 = val4; obj4 = (object)val4; } Phase4.OnEnter += (hook_OnEnter)obj4; object obj5 = <>c.<>9__16_4; if (obj5 == null) { hook_BeginGameOver val5 = delegate(orig_BeginGameOver orig, Run self, GameEndingDef ending) { StopSong(); currentPhase = null; orig.Invoke(self, ending); }; <>c.<>9__16_4 = val5; obj5 = (object)val5; } Run.BeginGameOver += (hook_BeginGameOver)obj5; object obj6 = <>c.<>9__16_5; if (obj6 == null) { hook_Start val6 = delegate(orig_Start orig, Stage self) { orig.Invoke(self); if (debugPlayOnStageStart.Value) { Log.LogInfo((object)"[Debug] Stage started — triggering song"); StartSong(); } }; <>c.<>9__16_5 = val6; obj6 = (object)val6; } Stage.Start += (hook_Start)obj6; } private static void OnPhaseEnter(string name) { Log.LogInfo((object)("[Mithrix] Entered phase: " + name)); if (currentPhase == phaseChoice.Value && name != phaseChoice.Value) { StopSong(); } currentPhase = name; if (name == phaseChoice.Value) { StartSong(); } } private IEnumerator LoadClipCoroutine() { Assembly executingAssembly = Assembly.GetExecutingAssembly(); Stream manifestResourceStream = executingAssembly.GetManifestResourceStream("MithrixChimeraMusic.intermission.ogg"); if (manifestResourceStream == null) { Log.LogError((object)("Embedded resource 'MithrixChimeraMusic.intermission.ogg' not found. Available: " + string.Join(", ", executingAssembly.GetManifestResourceNames()))); yield break; } string text = Path.Combine(Application.temporaryCachePath, "mithrix_chimera_song.ogg"); using (FileStream destination = File.Create(text)) { manifestResourceStream.CopyTo(destination); } manifestResourceStream.Dispose(); Log.LogInfo((object)$"Wrote OGG to {text} ({new FileInfo(text).Length} bytes)"); string absoluteUri = new Uri(text).AbsoluteUri; UnityWebRequest req = UnityWebRequestMultimedia.GetAudioClip(absoluteUri, (AudioType)14); try { ((DownloadHandlerAudioClip)req.downloadHandler).streamAudio = false; yield return req.SendWebRequest(); if ((int)req.result != 1) { Log.LogError((object)("Audio load failed: " + req.error)); yield break; } clip = DownloadHandlerAudioClip.GetContent(req); if ((Object)(object)clip == (Object)null || clip.length <= 0f) { ManualLogSource log = Log; object arg = (Object)(object)clip == (Object)null; AudioClip obj = clip; log.LogError((object)$"AudioClip invalid (null={arg}, length={((obj != null) ? new float?(obj.length) : null)})"); yield break; } ((Object)clip).name = "MithrixChimeraSong"; Log.LogInfo((object)$"Clip loaded: {clip.length:F1}s, {clip.channels}ch, {clip.frequency}Hz, samples={clip.samples}"); GameObject val = new GameObject("MithrixChimeraMusicSource"); Object.DontDestroyOnLoad((Object)val); source = val.AddComponent<AudioSource>(); source.clip = clip; source.loop = true; source.playOnAwake = false; source.spatialBlend = 0f; source.bypassEffects = true; source.bypassListenerEffects = true; source.bypassReverbZones = true; source.ignoreListenerPause = true; source.ignoreListenerVolume = false; source.volume = volume.Value; Log.LogInfo((object)"Mithrix Chimera Music loaded"); } finally { ((IDisposable)req)?.Dispose(); } } private static void StartSong() { if ((Object)(object)source == (Object)null) { Log.LogWarning((object)"Phase entered before AudioSource created"); } else if ((Object)(object)source.clip == (Object)null) { Log.LogError((object)"StartSong called but clip is null — load failed silently"); } else if (!source.isPlaying) { if (muteGameMusic.Value) { PostWwiseEvent(pauseEventName.Value); } source.volume = volume.Value; AudioListener.pause = false; source.Play(); Log.LogInfo((object)$"Custom song started (volume={source.volume}, listenerVol={AudioListener.volume}, listenerPaused={AudioListener.pause}, isPlaying={source.isPlaying})"); } } private static void StopSong() { if (!((Object)(object)source == (Object)null)) { source.Stop(); if (muteGameMusic.Value) { PostWwiseEvent(resumeEventName.Value); } Log.LogInfo((object)"Custom song stopped"); } } private static void PostWwiseEvent(string eventName) { try { if (!akLookupAttempted) { akLookupAttempted = true; Type type = null; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { try { type = assembly.GetTypes().FirstOrDefault((Type t) => t.Name == "AkSoundEngine"); } catch { continue; } if (type != null) { break; } } if (type != null) { akPostEvent = type.GetMethod("PostEvent", new Type[2] { typeof(string), typeof(GameObject) }); } else { Log.LogWarning((object)"AkSoundEngine type not found at runtime — game music won't be muted"); } } if (akPostEvent != null && (Object)(object)source != (Object)null) { akPostEvent.Invoke(null, new object[2] { eventName, ((Component)source).gameObject }); } } catch (Exception ex) { Log.LogWarning((object)("Wwise event post failed: " + ex.Message)); } } } }