using System.Collections; using System.Collections.Generic; using System.Linq; using BepInEx; using HarmonyLib; using UnityEngine; using UnityEngine.Networking; namespace MuzikaGromche { [BepInPlugin(PluginInfo.PLUGIN_GUID, PluginInfo.PLUGIN_NAME, PluginInfo.PLUGIN_VERSION)] public class Plugin : BaseUnityPlugin { public static Track[] Tracks = [ new Track { Name = "MuzikaGromche", WindUpTimer = 46.3f, Bpm = 130f, }, new Track { Name = "VseVZale", WindUpTimer = 39f, Bpm = 138f, }, new Track { Name = "DeployDestroy", WindUpTimer = 40.7f, Bpm = 130f, } ]; public static Coroutine JesterLightSwitching; public static Track CurrentTrack; private void Awake() { string text = Info.Location.TrimEnd((PluginInfo.PLUGIN_NAME + ".dll").ToCharArray()); UnityWebRequest[] requests = new UnityWebRequest[Tracks.Length * 2]; for (int i = 0; i < Tracks.Length; i++) { Track track = Tracks[i]; requests[i * 2] = UnityWebRequestMultimedia.GetAudioClip($"File://{text}{track.Name}Start.mp3", AudioType.MPEG); requests[i * 2 + 1] = UnityWebRequestMultimedia.GetAudioClip($"File://{text}{track.Name}Loop.mp3", AudioType.MPEG); requests[i * 2].SendWebRequest(); requests[i * 2 + 1].SendWebRequest(); } while (!requests.All(request => request.isDone)) { } if (requests.All(request => request.result == UnityWebRequest.Result.Success)) { for (int i = 0; i < Tracks.Length; i++) { Tracks[i].LoadedStart = DownloadHandlerAudioClip.GetContent(requests[i * 2]); Tracks[i].LoadedLoop = DownloadHandlerAudioClip.GetContent(requests[i * 2 + 1]); } new Harmony(PluginInfo.PLUGIN_NAME).PatchAll(typeof(JesterPatch)); } else { Logger.LogError("Could not load audio file"); } } } public class Track { public string Name; public float WindUpTimer; public float Bpm; public AudioClip LoadedStart; public AudioClip LoadedLoop; } [HarmonyPatch(typeof(JesterAI))] internal class JesterPatch { [HarmonyPatch("Update")] [HarmonyPrefix] public static void DoNotStopTheMusicPrefix(JesterAI __instance, out State __state) { __state = new State(); __state.prevStateindex = __instance.previousState; if (__instance.currentBehaviourStateIndex == 2 && __instance.previousBehaviourStateIndex != 2) { // if just popped out // then override farAudio so that vanilla logic does not stop the music __state.farAudio = __instance.farAudio; __instance.farAudio = __instance.creatureVoice; } } static List colors = [Color.magenta, Color.cyan, Color.green, Color.yellow]; public static IEnumerator rotateColors() { Debug.Log("Starting color rotation"); var i = 0; while (true) { var color = colors[i]; Debug.Log("Chose color " + color); foreach (var light in RoundManager.Instance.allPoweredLights) { light.color = color; } i += 1; if (i >= colors.Count) i = 0; yield return new WaitForSeconds(60f / Plugin.CurrentTrack.Bpm); } } [HarmonyPatch("Update")] [HarmonyPostfix] public static void DoNotStopTheMusic(JesterAI __instance, State __state) { if (__state.farAudio != null) { __instance.farAudio = __state.farAudio; } if (__instance.currentBehaviourStateIndex is 1 && __state.prevStateindex != 1) { // if just started winding up // then stop the default music... __instance.farAudio.Stop(); __instance.farAudio.Pause(); } if (__instance.currentBehaviourStateIndex is 1 && !__instance.farAudio.isPlaying) { // ...and start modded music var seed = RoundManager.Instance.dungeonGenerator.Generator.ChosenSeed; var trackId = seed % Plugin.Tracks.Length; Debug.Log($"Seed is {seed}, chosen track is {trackId} out of {Plugin.Tracks.Length} tracks"); Plugin.CurrentTrack = Plugin.Tracks[trackId]; __instance.popUpTimer = Plugin.CurrentTrack.WindUpTimer; Debug.Log($"Playing start music: maxDistance: {__instance.farAudio.maxDistance}, minDistance: {__instance.farAudio.minDistance}, volume: {__instance.farAudio.volume}, spread: {__instance.farAudio.spread}"); __instance.farAudio.maxDistance = 150; __instance.farAudio.PlayOneShot(Plugin.CurrentTrack.LoadedStart); } if (__instance.currentBehaviourStateIndex is 2 && __state.prevStateindex != 2) { __instance.creatureVoice.Stop(); if (Plugin.JesterLightSwitching != null) { __instance.StopCoroutine(Plugin.JesterLightSwitching); Plugin.JesterLightSwitching = null; } Plugin.JesterLightSwitching = __instance.StartCoroutine(rotateColors()); } if (__instance.currentBehaviourStateIndex != 2 && __state.prevStateindex == 2) { if (Plugin.JesterLightSwitching != null) { __instance.StopCoroutine(Plugin.JesterLightSwitching); Plugin.JesterLightSwitching = null; } foreach (var light in RoundManager.Instance.allPoweredLights) { light.color = Color.white; } } if (__instance.currentBehaviourStateIndex is 2 && !__instance.creatureVoice.isPlaying && !__instance.farAudio.isPlaying) { Debug.Log($"Playing loop music: maxDistance: {__instance.creatureVoice.maxDistance}, minDistance: {__instance.creatureVoice.minDistance}, volume: {__instance.creatureVoice.volume}, spread: {__instance.creatureVoice.spread}"); __instance.creatureVoice.maxDistance = 150; __instance.creatureVoice.clip = Plugin.CurrentTrack.LoadedLoop; __instance.creatureVoice.Play(); } } } internal class State { public AudioSource farAudio; public int prevStateindex; } }