Decompiled source of MuzikaGromche v1337.9001.1
Ratijas.MuzikaGromche.dll
Decompiled 2 weeks ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Net.NetworkInformation; using System.Net.Sockets; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Cryptography; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using DunGen; using GameNetcodeStuff; using HarmonyLib; using LethalConfig; using LethalConfig.ConfigItems; using LethalConfig.ConfigItems.Options; using LobbyCompatibility.Enums; using LobbyCompatibility.Features; using Microsoft.CodeAnalysis; using Ratijas.MuzikaGromche.NetcodePatcher; using TMPro; using Unity.Netcode; 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: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: IgnoresAccessChecksTo("Unity.Netcode.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.TextMeshPro")] [assembly: IgnoresAccessChecksTo("UnityEngine.UI")] [assembly: AssemblyCompany("Ratijas.MuzikaGromche")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Add some content to your inverse teleporter experience on Titan!")] [assembly: AssemblyFileVersion("1337.9001.1.0")] [assembly: AssemblyInformationalVersion("1337.9001.1+f790decc4d8f38bb852d2523ddca8bb4c5b17467")] [assembly: AssemblyProduct("Muzika Gromche")] [assembly: AssemblyTitle("Ratijas.MuzikaGromche")] [assembly: AssemblyMetadata("RepositoryUrl", "https://git.vilunov.me/ratijas/muzika-gromche")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1337.9001.1.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] [module: NetcodePatchedAssembly] 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 MuzikaGromche { internal static class Compatibility { [MethodImpl(MethodImplOptions.NoInlining)] public static void Register(BaseUnityPlugin plugin) { if (Chainloader.PluginInfos.ContainsKey("BMX.LobbyCompatibility")) { RegisterLobbyCompatibility(plugin.Info.Metadata); } } [MethodImpl(MethodImplOptions.NoInlining)] private static void RegisterLobbyCompatibility(BepInPlugin plugin) { PluginHelper.RegisterPlugin(plugin.GUID, plugin.Version, (CompatibilityLevel)2, (VersionStrictness)3); } } internal static class DeathScreenGameOverTextManager { [CompilerGenerated] private sealed class <SetTextAndClear>d__4 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public string text; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <SetTextAndClear>d__4(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; SetText(text); <>2__current = (object)new WaitForSeconds(5f); <>1__state = 1; return true; case 1: <>1__state = -1; Clear(); 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 const string GameOverTextVanilla = "[LIFE SUPPORT: OFFLINE]"; public const string GameOverTextModdedDefault = "[ MUZIKA: GROMCHE ]"; public static void Clear() { SetTextImpl("[LIFE SUPPORT: OFFLINE]"); } public static void SetText(string? text) { SetTextImpl(text ?? "[ MUZIKA: GROMCHE ]"); } [IteratorStateMachine(typeof(<SetTextAndClear>d__4))] public static IEnumerator SetTextAndClear(string? text) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <SetTextAndClear>d__4(0) { text = text }; } private static void SetTextImpl(string text) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) GameObject val = GameObject.Find("Systems/UI/Canvas/DeathScreen/GameOverText"); if ((Object)(object)val == (Object)null) { return; } TextMeshProUGUI component = val.GetComponent<TextMeshProUGUI>(); if ((Object)(object)component == (Object)null) { return; } RectTransform component2 = val.GetComponent<RectTransform>(); if (!((Object)(object)component2 == (Object)null)) { Vector2 sizeDelta = component2.sizeDelta; if (Mathf.Approximately(sizeDelta.x, 645.8f)) { sizeDelta.x += 100f; component2.sizeDelta = sizeDelta; } ((TMP_Text)component).text = text; } } } [HarmonyPatch(typeof(RoundManager))] internal static class DeathScreenGameOverTextResetPatch { [HarmonyPatch("DespawnPropsAtEndOfRound")] [HarmonyPatch("OnDestroy")] [HarmonyPrefix] private static void OnDestroy(RoundManager __instance) { DeathScreenGameOverTextManager.Clear(); } } public static class DiscoBallManager { private readonly record struct TilePatch(string TileName, GameObject DiscoBallContainer) { public readonly string TileCloneName = TileName + "(Clone)"; } [CompilerGenerated] private sealed class <FindDiscoBallAnimators>d__8 : IEnumerable<Animator>, IEnumerable, IEnumerator<Animator>, IEnumerator, IDisposable { private int <>1__state; private Animator <>2__current; private int <>l__initialThreadId; private GameObject discoBall; public GameObject <>3__discoBall; private string[] <>7__wrap1; private int <>7__wrap2; Animator IEnumerator<Animator>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <FindDiscoBallAnimators>d__8(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <>7__wrap1 = null; <>1__state = -2; } private bool MoveNext() { int num = <>1__state; if (num != 0) { if (num != 1) { return false; } <>1__state = -1; goto IL_0087; } <>1__state = -1; <>7__wrap1 = AnimatorContainersNames; <>7__wrap2 = 0; goto IL_0095; IL_0087: <>7__wrap2++; goto IL_0095; IL_0095: if (<>7__wrap2 < <>7__wrap1.Length) { string text = <>7__wrap1[<>7__wrap2]; Transform val = discoBall.transform.Find(text); if (!((Object)(object)val == (Object)null)) { GameObject gameObject = ((Component)val).gameObject; Animator val2 = ((gameObject != null) ? gameObject.GetComponent<Animator>() : null); if (!((Object)(object)val2 == (Object)null)) { <>2__current = val2; <>1__state = 1; return true; } } goto IL_0087; } <>7__wrap1 = 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(); } [DebuggerHidden] IEnumerator<Animator> IEnumerable<Animator>.GetEnumerator() { <FindDiscoBallAnimators>d__8 <FindDiscoBallAnimators>d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; <FindDiscoBallAnimators>d__ = this; } else { <FindDiscoBallAnimators>d__ = new <FindDiscoBallAnimators>d__8(0); } <FindDiscoBallAnimators>d__.discoBall = <>3__discoBall; return <FindDiscoBallAnimators>d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<Animator>)this).GetEnumerator(); } } private static TilePatch[] Patches = Array.Empty<TilePatch>(); private static readonly List<GameObject> CachedDiscoBalls = new List<GameObject>(); private static readonly List<Animator> CachedDiscoBallAnimators = new List<Animator>(); private static readonly string[] AnimatorContainersNames = new string[6] { "DiscoBallProp/AnimContainer", "DiscoBallProp1/AnimContainer", "DiscoBallProp2/AnimContainer", "DiscoBallProp3/AnimContainer", "DiscoBallProp4/AnimContainer", "DiscoBallProp5/AnimContainer" }; public static void Load() { string text = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "muzikagromche_discoball"); AssetBundle assetBundle = AssetBundle.LoadFromFile(text) ?? throw new NullReferenceException("Failed to load bundle"); Patches = new(string, string)[6] { ("Assets/LethalCompany/Mods/MuzikaGromche/DiscoBallContainerManor.prefab", "ManorStartRoomSmall"), ("Assets/LethalCompany/Mods/MuzikaGromche/DiscoBallContainerManorOLD.prefab", "ManorStartRoom"), ("Assets/LethalCompany/Mods/MuzikaGromche/DiscoBallContainerFactory.prefab", "StartRoom"), ("Assets/LethalCompany/Mods/MuzikaGromche/DiscoBallContainerMineShaft.prefab", "MineshaftStartTile"), ("Assets/LethalCompany/Mods/MuzikaGromche/DiscoBallContainerLargeForkTileB.prefab", "LargeForkTileB"), ("Assets/LethalCompany/Mods/MuzikaGromche/DiscoBallContainerBirthdayRoomTile.prefab", "BirthdayRoomTile") }.Select(((string PrefabPath, string TileName) d) => new TilePatch(d.TileName, assetBundle.LoadAsset<GameObject>(d.PrefabPath))).ToArray(); } internal static void Patch(Tile tile) { Tile tile2 = tile; foreach (TilePatch item in Patches.Where((TilePatch patch) => ((Object)((Component)tile2).gameObject).name == patch.TileCloneName)) { Patch(tile2, item); } } private static void Patch(Tile tile, TilePatch patch) { GameObject val = Object.Instantiate<GameObject>(patch.DiscoBallContainer, ((Component)tile).transform); if ((Object)(object)val == (Object)null) { return; } foreach (Animator item in FindDiscoBallAnimators(val)) { CachedDiscoBallAnimators.Add(item); } CachedDiscoBalls.Add(val); val.SetActive(false); Debug.Log((object)("MuzikaGromche DiscoBallManager Patched tile '" + ((Object)((Component)tile).gameObject).name + "'")); } [IteratorStateMachine(typeof(<FindDiscoBallAnimators>d__8))] private static IEnumerable<Animator> FindDiscoBallAnimators(GameObject discoBall) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <FindDiscoBallAnimators>d__8(-2) { <>3__discoBall = discoBall }; } public static void Toggle(bool on) { Debug.Log((object)string.Format("{0} {1} Toggle {2} {3} animators", "MuzikaGromche", "DiscoBallManager", on ? "ON" : "OFF", CachedDiscoBallAnimators.Count)); foreach (GameObject cachedDiscoBall in CachedDiscoBalls) { cachedDiscoBall.SetActive(on); } foreach (Animator cachedDiscoBallAnimator in CachedDiscoBallAnimators) { if (cachedDiscoBallAnimator != null) { cachedDiscoBallAnimator.SetBool("on", on); } } } public static void Enable() { Toggle(on: true); } public static void Disable() { Toggle(on: false); } internal static void Clear() { Debug.Log((object)string.Format("{0} {1} Clearing {2} disco balls & {3} animators", "MuzikaGromche", "DiscoBallManager", CachedDiscoBalls.Count, CachedDiscoBallAnimators.Count)); CachedDiscoBallAnimators.Clear(); CachedDiscoBalls.Clear(); } } [HarmonyPatch(typeof(Tile))] internal static class DiscoBallTilePatch { [HarmonyPatch("AddTriggerVolume")] [HarmonyPostfix] private static void OnAddTriggerVolume(Tile __instance) { DiscoBallManager.Patch(__instance); } } [HarmonyPatch(typeof(RoundManager))] internal static class DiscoBallDespawnPatch { [HarmonyPatch("DespawnPropsAtEndOfRound")] [HarmonyPatch("OnDestroy")] [HarmonyPrefix] private static void OnDestroy(RoundManager __instance) { DiscoBallManager.Clear(); } } [BepInPlugin("Ratijas.MuzikaGromche", "Muzika Gromche", "1337.9001.1")] [BepInDependency("ainavt.lc.lethalconfig", "1.4.6")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { internal static Dictionary<Light, Color> InitialLightsColors = new Dictionary<Light, Color>(); private static readonly string[] PwnLyricsVariants; private static readonly TimeSeries<float> DrunknessLoopOffsetTimeSeriesBeefLiver; public static readonly ISelectableTrack[] Tracks; public const float AudioMaxDistance = 150f; internal static Config Config { get; private set; } = null; public static ISelectableTrack ChooseTrack() { int chosenSeed = RoundManager.Instance.dungeonGenerator.Generator.ChosenSeed; ISelectableTrack[] array = (MuzikaGromche.Config.SkipExplicitTracks.Value ? Tracks.Where((ISelectableTrack track) => !track.IsExplicit).ToArray() : Tracks); int[] weights = array.Select((ISelectableTrack track) => track.Weight.Value).ToArray(); RandomWeightedIndex randomWeightedIndex = new RandomWeightedIndex(weights); int randomWeightedIndex2 = randomWeightedIndex.GetRandomWeightedIndex(chosenSeed); ISelectableTrack selectableTrack = array[randomWeightedIndex2]; Debug.Log((object)string.Format("{0} Seed is {1}, chosen track is \"{2}\", #{3} of {4}", "MuzikaGromche", chosenSeed, selectableTrack.Name, randomWeightedIndex2, randomWeightedIndex)); return array[randomWeightedIndex2]; } public static IAudioTrack? FindTrackNamed(string name) { string name2 = name; return Tracks.SelectMany((ISelectableTrack track) => track.GetTracks()).FirstOrDefault((IAudioTrack track) => track.Name == name2); } public static bool LocalPlayerCanHearMusic(EnemyAI jester) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController; AudioListener audioListener = StartOfRound.Instance.audioListener; if ((Object)(object)localPlayerController == (Object)null || (Object)(object)audioListener == (Object)null || !localPlayerController.isInsideFactory) { return false; } return Vector3.Distance(((Component)audioListener).transform.position, ((Component)jester).transform.position) <= 150f; } public static void DisplayLyrics(string text) { HUDManager.Instance.DisplayTip("[Lyrics]", text, false, false, "LC_Tip1"); HUDManager.Instance.UIAudio.Stop(); } private void Awake() { //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_02be: Unknown result type (might be due to invalid IL or missing references) //IL_02c3: Unknown result type (might be due to invalid IL or missing references) //IL_02d3: Unknown result type (might be due to invalid IL or missing references) //IL_02e3: Unknown result type (might be due to invalid IL or missing references) //IL_02f3: Unknown result type (might be due to invalid IL or missing references) //IL_0303: Unknown result type (might be due to invalid IL or missing references) //IL_0313: Unknown result type (might be due to invalid IL or missing references) //IL_0323: Unknown result type (might be due to invalid IL or missing references) //IL_0333: Unknown result type (might be due to invalid IL or missing references) //IL_0343: Unknown result type (might be due to invalid IL or missing references) Array.Sort(Tracks.Select((ISelectableTrack track) => track.Name).ToArray(), Tracks); string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); Dictionary<string, (UnityWebRequest, List<Action<AudioClip>>)> dictionary = new Dictionary<string, (UnityWebRequest, List<Action<AudioClip>>)>(); dictionary.EnsureCapacity(Tracks.Length * 2); foreach (IAudioTrack track2 in Tracks.SelectMany((ISelectableTrack track) => track.GetTracks())) { (string, Action<AudioClip>)[] array = new(string, Action<AudioClip>)[2] { (track2.FileNameIntro, delegate(AudioClip clip) { track2.LoadedIntro = clip; }), (track2.FileNameLoop, delegate(AudioClip clip) { track2.LoadedLoop = clip; }) }; for (int i = 0; i < array.Length; i++) { var (text, item) = array[i]; if (dictionary.TryGetValue(text, out var value)) { value.Item2.Add(item); continue; } UnityWebRequest audioClip = UnityWebRequestMultimedia.GetAudioClip("file://" + directoryName + "/" + text, track2.AudioType); audioClip.SendWebRequest(); dictionary[text] = (audioClip, new List<Action<AudioClip>>(1) { item }); } } while (!dictionary.Values.All<(UnityWebRequest, List<Action<AudioClip>>)>(((UnityWebRequest Request, List<Action<AudioClip>> Setters) tuple) => tuple.Request.isDone)) { } if (dictionary.Values.All<(UnityWebRequest, List<Action<AudioClip>>)>(((UnityWebRequest Request, List<Action<AudioClip>> Setters) tuple) => (int)tuple.Request.result == 1)) { foreach (KeyValuePair<string, (UnityWebRequest, List<Action<AudioClip>>)> item2 in dictionary) { item2.Deconstruct(out var _, out var value2); (UnityWebRequest, List<Action<AudioClip>>) tuple3 = value2; AudioClip content = DownloadHandlerAudioClip.GetContent(tuple3.Item1); foreach (Action<AudioClip> item3 in tuple3.Item2) { item3(content); } } Config = new Config(((BaseUnityPlugin)this).Config); DiscoBallManager.Load(); PoweredLightsAnimators.Load(); Harmony val = new Harmony("Muzika Gromche"); val.PatchAll(typeof(GameNetworkManagerPatch)); val.PatchAll(typeof(JesterPatch)); val.PatchAll(typeof(EnemyAIPatch)); val.PatchAll(typeof(PoweredLightsAnimatorsPatch)); val.PatchAll(typeof(AllPoweredLightsPatch)); val.PatchAll(typeof(DiscoBallTilePatch)); val.PatchAll(typeof(DiscoBallDespawnPatch)); val.PatchAll(typeof(SpawnRatePatch)); val.PatchAll(typeof(DeathScreenGameOverTextResetPatch)); val.PatchAll(typeof(ScreenFiltersManager.HUDManagerScreenFiltersPatch)); NetcodePatcher(); Compatibility.Register((BaseUnityPlugin)(object)this); } else { IEnumerable<string> values = from tuple in dictionary.Values where (int)tuple.Request.result != 1 select tuple.Request.GetUrl(); ((BaseUnityPlugin)this).Logger.LogError((object)("Could not load audio file " + string.Join(", ", values))); } } private static void NetcodePatcher() { Type[] types = Assembly.GetExecutingAssembly().GetTypes(); for (int i = 0; i < types.Length; i++) { MethodInfo[] methods = types[i].GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (methodInfo.GetCustomAttributes(typeof(RuntimeInitializeOnLoadMethodAttribute), inherit: false).Length != 0) { methodInfo.Invoke(null, null); } } } } static Plugin() { List<string> list = new List<string>(); list.Add(""); list.Add(""); list.Add(""); list.AddRange(from a in (from n in NetworkInterface.GetAllNetworkInterfaces() where n.OperationalStatus == OperationalStatus.Up select n).SelectMany((NetworkInterface n) => n.GetIPProperties().UnicastAddresses) where a.Address.AddressFamily == AddressFamily.InterNetwork select a.Address.ToString() into a select " Trying... " + a); PwnLyricsVariants = list.ToArray(); DrunknessLoopOffsetTimeSeriesBeefLiver = new TimeSeries<float>(new float[13] { -0.5f, 0.5f, 8f, 15f, 16f, 24f, 29f, 30f, 36f, 37f, 38f, 44f, 47.5f }, new float[13] { 0f, 0.6f, 0f, 0f, 0.4f, 0f, 0f, 0.3f, 0f, 0f, 0.3f, 0f, 0f }); Tracks = new ISelectableTrack[22] { new SelectableAudioTrack { Name = "MuzikaGromche", AudioType = (AudioType)14, Language = Language.RUSSIAN, WindUpTimer = 46.3f, Bars = 16, BeatsOffset = 0f, FadeOutBeat = -3f, FadeOutDuration = 3f, ColorTransitionIn = 0.25f, ColorTransitionOut = 0.25f, ColorTransitionEasing = Easing.OutExpo, FlickerLightsTimeSeries = new float[3] { -5f, 29f, 61f }, DrunknessLoopOffsetTimeSeries = new TimeSeries<float>(new float[9] { -2f, 0f, 1f, 3f, 30f, 32f, 33f, 35f, 62f }, new float[9] { 0f, 0.4f, 0.6f, 0f, 0f, 0.5f, 0.7f, 0f, 0f }), Palette = Palette.Parse(new string[6] { "#B300FF", "#FFF100", "#00FF51", "#474747", "#FF00B3", "#0070FF" }), Lyrics = new(float, string)[22] { (-68f, "Devchata pljashut pod spidami"), (-60f, "A ty stoish', kak vkopannyj"), (-52f, "Krossovkami lomajut pol"), (-44f, "A ty stoish', kak vkopannyj"), (-36f, "Ja-ja-ja znaju, chto ty hochesh',"), (-32f, "Ja-ja-ja znaju, chto ty hochesh',\nTy hochesh' tancevat'"), (-28f, "Nu-nu zhe, nu davaj zhe,"), (-24f, "Nu-nu zhe, nu davaj zhe,\nNu-nu zhe, nu davaj zhe"), (-20f, "Ja znaju, chto ty znaesh'\nJetot trek, gotov'sja podpevat'"), (-12f, "1) RAZ"), (-10f, "raz, DVA"), (-8f, "raz, 2wo,\nTRI"), (-6f, "ras, dva,\n7ri, 4ETYRE"), (-1f, "Muzyka Gromche\nGlaza zakryty >_<"), (6f, "This is NON-STOP,\nNoch'ju otkrytij"), (12f, "Delaj chto hochesh', ja zabyvajus'"), (22f, "This is NON-STOP,\nne prekrashhajas'"), (31f, "Muzyka Gromche\nGlaza zakryty -.-"), (38f, "This is NON-STOP,\nNoch'ju otkrytij"), (46f, "Budu s toboju,\nsamoj primernoju"), (54f, "Utro v okne\nyi my budem pervye"), (63f, "Muzyka Gromche\nGlaza zakryty >_<") } }, new SelectableAudioTrack { Name = "VseVZale", AudioType = (AudioType)14, Language = Language.RUSSIAN, WindUpTimer = 38.28f, Bars = 16, LoopOffset = 0, BeatsOffset = 0.25f, FadeOutBeat = -3f, FadeOutDuration = 2.5f, ColorTransitionIn = 0.25f, ColorTransitionOut = 0.25f, ColorTransitionEasing = Easing.OutExpo, FlickerLightsTimeSeries = new float[3] { -5f, 29f, 59f }, Palette = Palette.Parse(new string[6] { "#FF7F00", "#FFB600", "#FFED00", "#00D1FF", "#6696FB", "#704DF8" }).Use((Palette palette) => palette * 5 + new Palette(palette.Colors[0..2]) + (new Palette(palette.Colors[2..]) + palette * 2).Stretch(2)), Lyrics = new(float, string)[12] { (-30f, "VSE V ZALE\nDvigajtes' s nami"), (-24f, "Chtob sotrjasalis'\nSami my, steny i pol!"), (-14f, "Vse znaem - jeto examen na dom nam zadan"), (-4f, "HIP-HOP, HOUSE & ROCK-N-ROLL"), (2f, "VSE V ZALE\nDvigajtes' s nami"), (8f, "Chtob sotrjasalis'\nSami my, steny i pol!"), (18f, "Vse znaem - jeto examen na dom nam zadan"), (28f, "HIP-HOP, HOUSE & ROCK-N-ROLL"), (32f, "O-o-o-o! Zdes' startuet hip-hop party"), (44f, "Tolstyj paren', nam igraj!"), (48f, "O-o-o-o! Pesen i devchonok hvatit!"), (60f, "Everybody shake your body") } }, new SelectableAudioTrack { Name = "DeployDestroy", AudioType = (AudioType)14, Language = Language.RUSSIAN, WindUpTimer = 40.68f, Bars = 8, LoopOffset = 32, BeatsOffset = 0.2f, FadeOutBeat = -38f, FadeOutDuration = 4f, ColorTransitionIn = 0.25f, ColorTransitionOut = 0.25f, ColorTransitionEasing = Easing.OutExpo, FlickerLightsTimeSeries = new float[7] { -101f, -93f, -77f, -61f, -37f, -5f, 27f }, DrunknessLoopOffsetTimeSeries = new TimeSeries<float>(new float[6] { -48f, -46f, -42f, 16f, 19f, 23f }, new float[6] { 0f, 0.7f, 0f, 0f, 0.3f, 0f }), Palette = Palette.Parse(new string[5] { "#217F87", "#BAFF00", "#73BE25", "#78AB4E", "#FFFF00" }), Lyrics = new(float, string)[24] { (-111f, "Deploy Destroy, porjadok eto otstoj"), (-103f, "Krushi, lomaj, trjasi bashkoju pustoj"), (-95f, "Dopej, razbej i novuju otkryvaj"), (-87f, "Davaj-davaj!"), (-79f, "Chestnoe slovo ja nevinoven"), (-75f, "Ja ne pomnju, otkuda stol'ko krovi"), (-71f, "Na moih ladonjah\nyi moej odezhde"), (-67f, "Ja nikogda nikogo\nne bil prezhde"), (-63f, "Ja nikogda nichego\nne pil prezhde"), (-59f, "Byl tih, spokoen,\nso vsemi vezhliv"), (-55f, "Vsegda tol'ko v urnu\nbrosal musor"), (-51f, "Obhodil storonoj shumnye tusy"), (-47f, "Zapreshhjonnyh veshhestv nikakih ne juzal"), (-43f, "Byl polozhitel'nej samogo pljusa"), (-39f, "A potom kak-to raz\njetu pesnju uslyshal"), (-35f, "I vsjo proshhaj, moja krysha"), (-31f, "Deploy Destroy, porjadok eto otstoj"), (-23f, "Krushi, lomaj, trjasi bashkoju pustoj"), (-15f, "Dopej, razbej i novuju otkryvaj"), (-7f, "Davaj-davaj!"), (1f, "Deploy Destroy, porjadok eto otstoj"), (9f, "Krushi, lomaj, trjasi bashkoju pustoj"), (17f, "Dopej, razbej i novuju otkryvaj"), (25f, "Davaj-davaj!") } }, new SelectableAudioTrack { Name = "MoyaZhittya", AudioType = (AudioType)14, Language = Language.ENGLISH, WindUpTimer = 34.53f, Bars = 8, LoopOffset = 32, BeatsOffset = 0f, FadeOutBeat = -35f, FadeOutDuration = 3.3f, ColorTransitionIn = 0.25f, ColorTransitionOut = 0.5f, ColorTransitionEasing = Easing.OutExpo, Palette = Palette.Parse(new string[6] { "#A8C480", "#3ABBBE", "#6E9855", "#4c6846", "#748084", "#058099" }), FlickerLightsTimeSeries = new float[14] { -100.5f, -99.5f, -92.5f, -91.5f, -76.5f, -75.5f, -60.5f, -59.5f, -37f, -36f, -4.5f, -3.5f, 27.5f, 28.5f }, Lyrics = new(float, string)[28] { (-84f, "This ain't a song for the broken-hearted"), (-68f, "No silent prayer for the faith-departed"), (-52f, "I ain't gonna be"), (-48f, "I ain't gonna be\njust a face in the crowd"), (-45f, "YOU'RE"), (-44f, "you're GONNA"), (-43.5f, "you're gonna HEAR"), (-43f, "you're gonna hear\nMY"), (-42f, "you're gonna hear\nmy VOICE"), (-41f, "WHEN I"), (-40f, "When I SHOUT IT"), (-39f, "When I shout it\nOUT LOUD"), (-34f, "IT'S MY"), (-32f, "IT'S MY\nLIIIIIFE"), (-28f, "And it's now or never"), (-22f, "I ain't gonna"), (-20f, "I ain't gonna\nlive forever"), (-14f, "I just want to live"), (-10f, "I just want to live\nwhile I'm alive"), (-2f, "IT'S MY"), (0f, "IT'S MY\nLIIIIIFE"), (2f, "My heart is like"), (4f, "My heart is like\nan open highway"), (10f, "Like Frankie said,"), (12f, "Like Frankie said,\n\"I did it my way\""), (18f, "I just want to live"), (22f, "I just want to live\nwhile I'm alive"), (30f, "IT'S MY") }, DrunknessLoopOffsetTimeSeries = new TimeSeries<float>(new float[7] { -33f, -31f, 24f, -1f, 1f, 8f, 31f }, new float[7] { 0f, 0.7f, 0f, 0f, 0.7f, 0f, 0f }), GameOverText = "[LIFE IS: NOW OR NEVER]" }, new SelectableAudioTrack { Name = "Gorgorod", AudioType = (AudioType)14, Language = Language.RUSSIAN, WindUpTimer = 43.2f, Bars = 6, BeatsOffset = 0f, ColorTransitionIn = 0.25f, ColorTransitionOut = 0.25f, ColorTransitionEasing = Easing.InExpo, Palette = Palette.Parse(new string[8] { "#42367E", "#FF9400", "#932A04", "#FF9400", "#932A04", "#42367E", "#FF9400", "#932A04" }), LoopOffset = 0, FadeOutBeat = -2f, FadeOutDuration = 2f, FlickerLightsTimeSeries = new float[1] { 20f }, Lyrics = Array.Empty<(float, string)>() }, new SelectableAudioTrack { Name = "Durochka", AudioType = (AudioType)14, Language = Language.RUSSIAN, WindUpTimer = 37f, Bars = 10, BeatsOffset = 0f, ColorTransitionIn = 0.25f, ColorTransitionOut = 0.3f, ColorTransitionEasing = Easing.OutExpo, Palette = Palette.Parse(new string[8] { "#5986FE", "#FEFEDC", "#FF4FDF", "#FEFEDC", "#FFAA23", "#FEFEDC", "#F95A5A", "#FEFEDC" }), LoopOffset = 0, FadeOutBeat = -7f, FadeOutDuration = 7f, FlickerLightsTimeSeries = new float[1] { -9f }, Lyrics = Array.Empty<(float, string)>() }, new SelectableAudioTrack { Name = "ZmeiGorynich", AudioType = (AudioType)14, Language = Language.KOREAN, WindUpTimer = 46.13f, Bars = 8, BeatsOffset = 0.1f, ColorTransitionIn = 0.4f, ColorTransitionOut = 0.4f, ColorTransitionEasing = Easing.OutExpo, Palette = Palette.Parse(new string[6] { "#4C8AC5", "#AF326A", "#0B1666", "#AFD2FC", "#C55297", "#540070" }), LoopOffset = 0, FadeOutBeat = -4f, FadeOutDuration = 4f, FlickerLightsTimeSeries = new float[2] { -5f, 31f }, Lyrics = Array.Empty<(float, string)>(), GameOverText = "[MUZIKA: K-POP GROMCHE]" }, new SelectableAudioTrack { Name = "GodMode", AudioType = (AudioType)14, Language = Language.ENGLISH, WindUpTimer = 40.38f, Bars = 16, BeatsOffset = 0.1f, ColorTransitionIn = 0.5f, ColorTransitionOut = 0.5f, ColorTransitionEasing = Easing.OutCubic, Palette = Palette.Parse(new string[8] { "#FBDBDB", "#4B81FF", "#564242", "#C90AE2", "#FBDBDB", "#61CBE3", "#564242", "#ED3131" }), LoopOffset = 0, FadeOutBeat = -4f, FadeOutDuration = 4f, FlickerLightsTimeSeries = new float[1] { -5f }, Lyrics = Array.Empty<(float, string)>(), DrunknessLoopOffsetTimeSeries = new TimeSeries<float>(new float[4] { -0.5f, 0f, 8f, 63.5f }, new float[4] { 0f, 0.7f, 0f, 0f }), GameOverText = "[COULD'VE BEEN: IMMORTAL]" }, new SelectableAudioTrack { Name = "RiseAndShine", AudioType = (AudioType)14, Language = Language.ENGLISH, WindUpTimer = 59.87f, Bars = 16, BeatsOffset = 0.1f, ColorTransitionIn = 0.5f, ColorTransitionOut = 0.5f, ColorTransitionEasing = Easing.OutCubic, Palette = Palette.Parse(new string[8] { "#FC6F3C", "#3CB0FC", "#FCD489", "#564242", "#FC6F3C", "#3CB0FC", "#63E98C", "#866868" }), LoopOffset = 0, FadeOutBeat = -4.5f, FadeOutDuration = 4f, FlickerLightsTimeSeries = new float[3] { -5.5f, 31f, 63.9f }, Lyrics = Array.Empty<(float, string)>(), DrunknessLoopOffsetTimeSeries = new TimeSeries<float>(new float[4] { -0.5f, 0f, 8f, 63.5f }, new float[4] { 0f, 0.7f, 0f, 0f }), GameOverText = "[ HEY, YOUNG BLOOD ]" }, new SelectableAudioTrack { Name = "Song2", AudioType = (AudioType)14, Language = Language.RUSSIAN, WindUpTimer = 38.63f, Beats = 34, BeatsOffset = 0.1f, ColorTransitionIn = 0.3f, ColorTransitionOut = 0.3f, ColorTransitionEasing = Easing.InCubic, Palette = Palette.Parse(new string[8] { "#FFD3E3", "#78A0FF", "#FFD3E3", "#74A392", "#FFD3E3", "#E4B082", "#FFD3E3", "#E277AA" }), LoopOffset = 0, FadeOutBeat = -2f, FadeOutDuration = 2f, FlickerLightsTimeSeries = new float[1] { 2.5f }, Lyrics = Array.Empty<(float, string)>() }, new SelectableAudioTrack { Name = "Peretasovka", AudioType = (AudioType)14, Language = Language.ENGLISH, WindUpTimer = 39.68f, Bars = 8, BeatsOffset = 0.3f, ColorTransitionIn = 0.4f, ColorTransitionOut = 0.4f, ColorTransitionEasing = Easing.OutExpo, Palette = Palette.Parse(new string[8] { "#65C7FA", "#FCEB3C", "#89FC8F", "#FEE9E9", "#FC3C9D", "#FCEB3C", "#89FC8F", "#FC3C9D" }), LoopOffset = 0, FadeOutBeat = -6f, FadeOutDuration = 4f, FlickerLightsTimeSeries = new float[2] { -8f, 31f }, Lyrics = Array.Empty<(float, string)>() }, new SelectableAudioTrack { Name = "Yalgaar", AudioType = (AudioType)14, Language = Language.HINDI, WindUpTimer = 52.17f, Bars = 8, BeatsOffset = 0f, ColorTransitionIn = 0.1f, ColorTransitionOut = 0.35f, ColorTransitionEasing = Easing.OutExpo, Palette = Palette.Parse(new string[8] { "#C0402D", "#906F0B", "#DC8044", "#70190A", "#929FAF", "#4248A2", "#AE2727", "#2D2D42" }), LoopOffset = 0, FadeOutBeat = -4f, FadeOutDuration = 4f, FlickerLightsTimeSeries = new float[1] { -5f }, Lyrics = Array.Empty<(float, string)>() }, new SelectableAudioTrack { Name = "Chereshnya", AudioType = (AudioType)14, Language = Language.RUSSIAN, WindUpTimer = 45.48f, Bars = 16, BeatsOffset = 0f, ColorTransitionIn = 0.3f, ColorTransitionOut = 0.35f, ColorTransitionEasing = Easing.InOutCubic, Palette = Palette.Parse(new string[16] { "#A01471", "#CB2243", "#4CAF50", "#F01D7A", "#AF005A", "#EF355F", "#FFD85D", "#FF66B2", "#A01471", "#4CAF50", "#CB2243", "#F01D7A", "#AF005A", "#FFD85D", "#EF355F", "#FF66B2" }), LoopOffset = 0, FadeOutBeat = -4f, FadeOutDuration = 4f, FlickerLightsTimeSeries = new float[5] { -5f, 27f, 29f, 59f, 61f }, Lyrics = Array.Empty<(float, string)>() }, new SelectableAudioTrack { Name = "PWNED", AudioType = (AudioType)14, Language = Language.ENGLISH, IsExplicit = true, WindUpTimer = 39.73f, Bars = 32, BeatsOffset = -0.2f, ColorTransitionIn = 0.5f, ColorTransitionOut = 0.3f, ColorTransitionEasing = Easing.InExpo, Palette = Palette.Parse(new string[8] { "#9E9E9E", "#383838", "#5E5E5E", "#2E2E2E", "#666666", "#4B4B4B", "#8E8E8E", "#1D1D1D" }).Use(delegate(Palette gray8) { Palette palette2 = Palette.Parse(new string[4] { "#FFFFFF", "#0032A0", "#DA291C", "#000000" }); Palette palette3 = new Palette(gray8.Colors[0..6]); Palette palette4 = palette2 + (gray8 + palette3).Stretch(2); Palette palette5 = gray8.Stretch(4); return palette4 * 2 + palette5 * 2; }), LoopOffset = 0, FadeOutBeat = -8f, FadeOutDuration = 6f, FlickerLightsTimeSeries = new float[4] { -136f, -72f, -12f, 88f }, Lyrics = new(float, string)[44] { (-190f, "These Russian hackers have been"), (-184f, "in these US governments\nsince March"), (-172f, "and it is an extraordinary invasion of our cyberspace"), (-152f, "Russian hackers got access to sensitive"), (-142f, "parts of the White House email system..."), (-134f, "[They began to recognize...]"), (-126f, "<Russian hackers/>"), (-118f, "<Russian hackers/>\n X__X"), (-110f, "Gonna crack your"), (-102f, "Gonna crack your\nStrongest pa$$words%123"), (-94f, "You popped online"), (-86f, "You popped online\nTo look for sneakers"), (-78f, "My hand just popped"), (-70f, "My hand just popped\nRight in your knickers >_< "), (-62f, "Keystrokes like Uzi"), (-54f, "Keystrokes like Uzi\nWill make you go all goosey"), (-46f, "Kicking down your backdoor"), (-38f, "Kicking down your backdoor\nCount down before you lose it"), (-30f, "Keystrokes like Uzi"), (-22f, "Keystrokes like Uzi\nWill make you go all goosey"), (-14f, "Kicking down your backdoor"), (-6f, "Kicking down your backdoor\nCount down before you lose it"), (0f, "C:\\> $Ru55ian hack3rs"), (4f, "C:\\> $Ru55ian hack3rs\n O__o"), (8f, "Infamous White House attackers"), (16f, "Stealing your cookies\nto this beat"), (24f, "Counting crypto to\nembarrass Wall Street"), (32f, "Russi?n ^hackers\tЯushan h@ckers###"), (34f, "\tЯushan h@ckers###\n X_X"), (36f, "Russi?n ^hackers\n--.--\tЯushan h@ckers###\n X___X"), (38f, "\tЯushan h@ckers###\n X_____X"), (40f, "Infamous White House attackers"), (48f, "Stealing your cookies\nto this beat"), (56f, "Counting crypto to\nembarrass Wall Street"), (80f, "Instling min3r.exe\t\t\tresolving ur private IP\n/"), (82f, "Instling min3r.exe\n00% [8=D ]\tHenllo ${username = \"" + Environment.UserName + "\"}\t\tresolving ur private IP\n-" + PwnLyricsVariants[^3]), (84f, "Instling min3r.exe\n33% [8====D ]\t\t\tresolving ur private IP\n\\" + PwnLyricsVariants[^3]), (86f, "Instling min3r.exe\n66% [8=========D ]\t\t\tresolving ur private IP\n|" + PwnLyricsVariants[^2]), (88f, "Instling min3r.exe\n95% [8============D ]\t\tWhere did you download\nthis < mod / dll > from?\tresolving ur private IP\n" + PwnLyricsVariants[^2] + "/"), (90f, "Instling min3r.exe\n99% [8=============D]\t\t\tresolving ur private IP\n-" + PwnLyricsVariants[^2]), (92f, "Encrpt1ng f!les.. \n99% [8=============D]\t\t\tresolving ur private IP\n\\" + PwnLyricsVariants[^1]), (94f, "Encrpt1ng f!les...\n100% enj0y \\o/\t\t\tresolving ur private IP\n|" + PwnLyricsVariants[^1]), (96f, "\t\t\tresolving ur private IP\n/" + PwnLyricsVariants[^1]), (98f, "\t\t\tresolving ur private IP\nP_WNED") }, DrunknessLoopOffsetTimeSeries = new TimeSeries<float>(new float[7] { -128f, -127f, -116f, 68f, 72f, 88f, 98f }, new float[7] { 0f, 0.7f, 0f, 0f, 0.3f, 0.5f, 0f }), GameOverText = "[HACK3D BY: RUSSI4NS]" }, new SelectableAudioTrack { Name = "Kach", AudioType = (AudioType)14, Language = Language.ENGLISH, WindUpTimer = 47.3f, Bars = 12, BeatsOffset = 0.4f, ColorTransitionIn = 0.8f, ColorTransitionOut = 0.4f, ColorTransitionEasing = Easing.OutExpo, Palette = Palette.Parse(new string[12] { "#7774DE", "#1EA59A", "#3BC457", "#3BC457", "#CA6935", "#A82615", "#A7AA43", "#A7AA43", "#4C2B81", "#2E802B", "#C952E7", "#C952E7" }), LoopOffset = 0, FadeOutBeat = -6f, FadeOutDuration = 6f, FlickerLightsTimeSeries = new float[6] { -120.5f, -105f, -89f, -8f, 44f, 45f }, Lyrics = Array.Empty<(float, string)>(), GameOverText = "[DIDN'T PUMP IT: LOUDER]" }, new SelectableTracksGroup { Name = "BeefLiver", Language = Language.ENGLISH, Tracks = new IAudioTrack[3] { new CoreAudioTrack { Name = "BeefLiver1", FileNameLoop = "BeefLiverLoop.ogg", AudioType = (AudioType)14, WindUpTimer = 39.35f, Bars = 12, BeatsOffset = 0.2f, ColorTransitionIn = 0.4f, ColorTransitionOut = 0.4f, ColorTransitionEasing = Easing.OutExpo, Palette = Palette.Parse(new string[8] { "#FFEBEB", "#FFEBEB", "#445782", "#EBA602", "#5EEBB9", "#8EE3DC", "#A23045", "#262222" }), LoopOffset = 0, FadeOutBeat = -3f, FadeOutDuration = 3f, FlickerLightsTimeSeries = new float[4] { -48f, -40f, -4.5f, 44f }, DrunknessLoopOffsetTimeSeries = DrunknessLoopOffsetTimeSeriesBeefLiver, Lyrics = new(float, string)[13] { (-66f, "First things first"), (-62f, "First things first,\nI'ma say all the words\ninside my head"), (-57f, "I'm fired up and tired of"), (-52f, "the way that things have been,\noh-ooh"), (-44f, "(x2)\nThe way that things have been,\noh-ooooh"), (-34f, "I was broken from a young age, taking my sulkin' to the masses"), (-27f, "Writing my poems for the few"), (-23f, "that look at me, took to me,\nshook at me, feelin' me"), (-19f, "Singing from heartache from the pain"), (-15f, "Singing from heartache from the pain,\ntaking my message from the veins"), (-11f, "Speaking my lesson from the brain"), (-8f, "Speaking my lesson from the brain,\nseeing the beauty through the"), (-0.1f, "PAIN!") } }, new CoreAudioTrack { Name = "BeefLiver3", FileNameLoop = "BeefLiverLoop.ogg", AudioType = (AudioType)14, WindUpTimer = 39.35f, Bars = 12, BeatsOffset = 0.2f, ColorTransitionIn = 0.4f, ColorTransitionOut = 0.4f, ColorTransitionEasing = Easing.OutExpo, Palette = Palette.Parse(new string[8] { "#FFEBEB", "#FFEBEB", "#445782", "#EBA602", "#5EEBB9", "#8EE3DC", "#A23045", "#262222" }), LoopOffset = 0, FadeOutBeat = -3f, FadeOutDuration = 3f, FlickerLightsTimeSeries = new float[4] { -48f, -40f, -4.5f, 44f }, DrunknessLoopOffsetTimeSeries = DrunknessLoopOffsetTimeSeriesBeefLiver, Lyrics = new(float, string)[13] { (-66f, "Third things third"), (-62f, "Third things third,\nsend a prayer to the ones up above"), (-57f, "All the hate that you've heard has turned"), (-52f, "your spirit to a dove,\noh-ooh"), (-44f, "(x2)\nYour spirit up above,\noh-ooooh"), (-34f, "I was chokin' in the crowd, building my rain up in the cloud"), (-27f, "Falling like ashes to the ground"), (-23f, "hoping my feelings, they would drown"), (-19f, "But they never did, ever lived, ebbin' and flowin'"), (-15f, "Inhibited, limited 'til it broke open"), (-11f, "Inhibited, limited 'til it broke open and rained down"), (-8f, "It rained down like"), (-0.1f, "PAIN!") } }, new CoreAudioTrack { Name = "BeefLiver4", AudioType = (AudioType)14, WindUpTimer = 31.68f, Bars = 12, BeatsOffset = 0.2f, ColorTransitionIn = 0.4f, ColorTransitionOut = 0.4f, ColorTransitionEasing = Easing.OutExpo, Palette = Palette.Parse(new string[8] { "#FFEBEB", "#FFEBEB", "#445782", "#EBA602", "#5EEBB9", "#8EE3DC", "#A23045", "#262222" }), LoopOffset = 0, FadeOutBeat = -3f, FadeOutDuration = 3f, FlickerLightsTimeSeries = new float[4] { -32f, -24f, -4.5f, 44f }, DrunknessLoopOffsetTimeSeries = DrunknessLoopOffsetTimeSeriesBeefLiver, Lyrics = new(float, string)[10] { (-50f, "Last things last"), (-46f, "Last things last,\nby the grace\nof the fire and the flames"), (-41f, "You're the face of the future"), (-36f, "the blood in my veins, oh-ooh"), (-28f, "(x2)\nThe blood in my veins, oh-ooooh"), (-19f, "But they never did, ever lived, ebbin' and flowin'"), (-15f, "Inhibited, limited 'til it broke open"), (-11f, "Inhibited, limited 'til it broke open and rained down"), (-8f, "It rained down like"), (-0.1f, "PAIN!") } } } }, new SelectableTracksGroup { Name = "Beha", Language = Language.RUSSIAN, IsExplicit = true, Tracks = new IAudioTrack[3] { new CoreAudioTrack { Name = "Beha1", FileNameLoop = "BehaLoop.ogg", AudioType = (AudioType)14, WindUpTimer = 35.23f, Beats = 34, BeatsOffset = 0f, ColorTransitionIn = 0.1f, ColorTransitionOut = 0.6f, ColorTransitionEasing = Easing.OutExpo, Palette = Palette.Parse(new string[6] { "#9554F9", "#3769FD", "#E43B65", "#59CFEA", "#7F3FEE", "#C831FE" }), LoopOffset = 0, FadeOutBeat = -4f, FadeOutDuration = 3.9f, FlickerLightsTimeSeries = new float[2] { -6f, 16.5f }, Lyrics = Array.Empty<(float, string)>() }, new CoreAudioTrack { Name = "Beha2", FileNameLoop = "BehaLoop.ogg", AudioType = (AudioType)14, WindUpTimer = 38.16f, Beats = 34, BeatsOffset = 0f, ColorTransitionIn = 0.1f, ColorTransitionOut = 0.6f, ColorTransitionEasing = Easing.OutExpo, Palette = Palette.Parse(new string[6] { "#9554F9", "#3769FD", "#E43B65", "#59CFEA", "#7F3FEE", "#C831FE" }), LoopOffset = 0, FadeOutBeat = -4f, FadeOutDuration = 3.9f, FlickerLightsTimeSeries = new float[2] { -6f, 16.5f }, Lyrics = Array.Empty<(float, string)>() }, new CoreAudioTrack { Name = "Beha3", FileNameLoop = "BehaLoop.ogg", AudioType = (AudioType)14, WindUpTimer = 35.21f, Beats = 34, BeatsOffset = 0f, ColorTransitionIn = 0.1f, ColorTransitionOut = 0.6f, ColorTransitionEasing = Easing.OutExpo, Palette = Palette.Parse(new string[6] { "#9554F9", "#3769FD", "#E43B65", "#59CFEA", "#7F3FEE", "#C831FE" }), LoopOffset = 0, FadeOutBeat = -4f, FadeOutDuration = 3.9f, FlickerLightsTimeSeries = new float[2] { -6f, 16.5f }, Lyrics = Array.Empty<(float, string)>() } } }, new SelectableAudioTrack { Name = "OnePartiyaUdar", AudioType = (AudioType)14, Language = Language.JAPANESE, WindUpTimer = 41.27f, Bars = 12, BeatsOffset = 0.3f, ColorTransitionIn = 0.6f, ColorTransitionOut = 0.15f, ColorTransitionEasing = Easing.InOutExpo, Palette = Palette.Parse(new string[6] { "#9C3C37", "#E9BF5C", "#B5E3EA", "#662422", "#EBC3A8", "#AA8238" }), LoopOffset = 0, FadeOutBeat = -8f, FadeOutDuration = 6f, FlickerLightsTimeSeries = new float[3] { -68.5f, -16.5f, 30.5f }, Lyrics = Array.Empty<(float, string)>() }, new SelectableTracksGroup { Name = "AttentionPls", Language = Language.RUSSIAN, IsExplicit = true, Tracks = new IAudioTrack[2] { new CoreAudioTrack { Name = "AttentionPls1", FileNameLoop = "AttentionPlsLoop.ogg", AudioType = (AudioType)14, WindUpTimer = 39.19f, Bars = 8, BeatsOffset = 0.3f, ColorTransitionIn = 0.4f, ColorTransitionOut = 0.4f, ColorTransitionEasing = Easing.OutExpo, Palette = Palette.Parse(new string[8] { "#FCEB3C", "#FC3C9D", "#65C7FA", "#89FC8F", "#FEE9E9", "#FCEB3C", "#89FC8F", "#FC3C9D" }), LoopOffset = 0, FadeOutBeat = -6f, FadeOutDuration = 5f, FlickerLightsTimeSeries = new float[2] { -8f, 31f }, Lyrics = Array.Empty<(float, string)>(), DrunknessLoopOffsetTimeSeries = new TimeSeries<float>(new float[3] { 7f, 12f, 15f }, new float[3] { 0f, 0.9f, 0f }), CondensationLoopOffsetTimeSeries = new TimeSeries<float>(new float[3] { 23f, 28f, 31f }, new float[3] { 0f, 0.4f, 0f }) }, new CoreAudioTrack { Name = "AttentionPls2", FileNameLoop = "AttentionPlsLoop.ogg", AudioType = (AudioType)14, WindUpTimer = 39.19f, Bars = 8, BeatsOffset = 0.3f, ColorTransitionIn = 0.4f, ColorTransitionOut = 0.4f, ColorTransitionEasing = Easing.OutExpo, Palette = Palette.Parse(new string[8] { "#FCEB3C", "#FC3C9D", "#65C7FA", "#89FC8F", "#FEE9E9", "#FCEB3C", "#89FC8F", "#FC3C9D" }), LoopOffset = 0, FadeOutBeat = -6f, FadeOutDuration = 5f, FlickerLightsTimeSeries = new float[2] { -8f, 31f }, Lyrics = Array.Empty<(float, string)>(), DrunknessLoopOffsetTimeSeries = new TimeSeries<float>(new float[3] { 7f, 12f, 15f }, new float[3] { 0f, 0.9f, 0f }), CondensationLoopOffsetTimeSeries = new TimeSeries<float>(new float[3] { 23f, 28f, 31f }, new float[3] { 0f, 0.4f, 0f }) } } }, new SelectableAudioTrack { Name = "BbIXODaHET", AudioType = (AudioType)14, Language = Language.RUSSIAN, WindUpTimer = 40.85f, Bars = 8, BeatsOffset = 0.3f, ColorTransitionIn = 0.7f, ColorTransitionOut = 0.3f, ColorTransitionEasing = Easing.InOutCubic, Palette = Palette.Parse(new string[6] { "#E6D58F", "#612F7E", "#D9783F", "#C3411C", "#D3B742", "#549BDE" }), LoopOffset = 0, FadeOutBeat = -6f, FadeOutDuration = 6f, FlickerLightsTimeSeries = new float[3] { -32.5f, -16.5f, 30.5f }, Lyrics = Array.Empty<(float, string)>(), DrunknessLoopOffsetTimeSeries = new TimeSeries<float>(new float[4] { -1f, 2f, 7f, 31f }, new float[4] { 0f, 0.4f, 0f, 0f }) }, new SelectableAudioTrack { Name = "Whistle", AudioType = (AudioType)14, Language = Language.ENGLISH, WindUpTimer = 41.27f, Bars = 12, BeatsOffset = 0f, ColorTransitionIn = 0.5f, ColorTransitionOut = 0.2f, ColorTransitionEasing = Easing.OutExpo, Palette = Palette.Parse(new string[6] { "#8DDEDD", "#98DE28", "#E8DB4B", "#F060A8", "#EEC263", "#725DEB" }), LoopOffset = 16, FadeOutBeat = -22f, FadeOutDuration = 6f, FlickerLightsTimeSeries = new float[2] { -20f, 12f }, Lyrics = new(float, string)[20] { (-40f, "Can you blow my whistle, baby, whistle, baby?"), (-36f, "Can you blow my whistle, baby, whistle, baby? Let me know"), (-33.5f, "Girl, I'm gonna show you how to\ndo it"), (-30.5f, "Girl, I'm gonna show you how to\ndo it and we start real slow"), (-27f, "You just put your lips together"), (-24f, "You just put your lips together and you come real close"), (-21f, "Can you blow my whistle, baby, whistle, baby?"), (-17f, "HERE WE GO"), (10f, "Yeah, baby, make that whistle"), (12f, "Yeah, baby, make that whistle\nblow oh oh oh"), (15f, "Can you blow my whistle, baby, whistle, baby?"), (20f, "Can you blow my whistle, baby, whistle, baby? Let me know"), (23f, "Girl, I'm gonna show you how to\ndo it"), (28f, "Girl, I'm gonna show you how to\ndo it and we start real slow"), (32f, "You just put your lips together"), (36f, "You just put your lips together and you come real close"), (39f, "Can you blow my whistle, baby, whistle, baby?"), (46f, "HERE"), (47f, "Here WE"), (48f, "Here we GO") }, DrunknessLoopOffsetTimeSeries = new TimeSeries<float>(new float[8] { -16f, -15.25f, -12f, 9f, 15f, 16f, 18f, 21f }, new float[8] { 0f, 0.7f, 0f, 0f, 0.4f, 0.7f, 0.4f, 0f }) }, new SelectableAudioTrack { Name = "ReelGoon", AudioType = (AudioType)14, Language = Language.ENGLISH, WindUpTimer = 45.15f, Bars = 16, BeatsOffset = -0.35f, ColorTransitionIn = 0.1f, ColorTransitionOut = 0.35f, ColorTransitionEasing = Easing.OutExpo, Palette = Palette.Parse(new string[8] { "#DE1C31", "#F7E26B", "#3D3D3D", "#FBB040", "#ED4E4A", "#F0BD37", "#E41E2E", "#2E2D2B" }), LoopOffset = 0, FadeOutBeat = -2f, FadeOutDuration = 2f, FlickerLightsTimeSeries = new float[2] { -41f, 61f }, Lyrics = Array.Empty<(float, string)>(), DrunknessLoopOffsetTimeSeries = new TimeSeries<float>(new float[5] { -0.5f, -0.05f, 6f, 60f, 61f }, new float[5] { 0f, 0.5f, 0f, 0f, 0.5f }), GameOverText = "[LIFE SUPPORT: REAL GONE]" } }; } } public readonly record struct Language(string Short, string Full) { public static readonly Language ENGLISH = new Language("EN", "English"); public static readonly Language RUSSIAN = new Language("RU", "Russian"); public static readonly Language KOREAN = new Language("KO", "Korean"); public static readonly Language JAPANESE = new Language("JP", "Japanese"); public static readonly Language HINDI = new Language("HI", "Hindi"); } public readonly record struct Easing(string Name, Func<float, float> Eval) { public static Easing Linear = new Easing("Linear", (float x) => x); public static Easing OutCubic = new Easing("OutCubic", (float x) => 1f - Mathf.Pow(1f - x, 3f)); public static Easing InCubic = new Easing("InCubic", (float x) => x * x * x); public static Easing InOutCubic = new Easing("InOutCubic", (float x) => (!(x < 0.5f)) ? (1f - Mathf.Pow(-2f * x + 2f, 3f) / 2f) : (4f * x * x * x)); public static Easing InExpo = new Easing("InExpo", (float x) => (x != 0f) ? Mathf.Pow(2f, 10f * x - 10f) : 0f); public static Easing OutExpo = new Easing("OutExpo", (float x) => (x != 1f) ? (1f - Mathf.Pow(2f, -10f * x)) : 1f); public static Easing InOutExpo = new Easing("InOutExpo", (float x) => (x != 0f) ? ((x != 1f) ? ((!(x < 0.5f)) ? ((2f - Mathf.Pow(2f, -20f * x + 10f)) / 2f) : (Mathf.Pow(2f, 20f * x - 10f) / 2f)) : 1f) : 0f); public static readonly Easing[] All = new Easing[7] { Linear, InCubic, OutCubic, InOutCubic, InExpo, OutExpo, InOutExpo }; public static readonly string[] AllNames = All.Select((Easing easing) => easing.Name).ToArray(); public static Easing FindByName(string Name) { string Name2 = Name; return All.Where((Easing easing) => easing.Name == Name2).DefaultIfEmpty(Linear).First(); } public override string ToString() { return Name; } } public readonly record struct Palette(Color[] Colors) { public static readonly Palette DEFAULT = new Palette((Color[])(object)new Color[4] { Color.magenta, Color.cyan, Color.green, Color.yellow }); public static Palette Parse(string[] hexColors) { Color[] array = (Color[])(object)new Color[hexColors.Length]; for (int i = 0; i < hexColors.Length; i++) { if (!ColorUtility.TryParseHtmlString(hexColors[i], ref array[i])) { throw new ArgumentException($"Unable to parse color #{i}: {hexColors}"); } } return new Palette(array); } public static Palette operator +(Palette before, Palette after) { Color[] colors = before.Colors; Color[] colors2 = after.Colors; int num = 0; Color[] array = (Color[])(object)new Color[colors.Length + colors2.Length]; ReadOnlySpan<Color> readOnlySpan = new ReadOnlySpan<Color>(colors); readOnlySpan.CopyTo(new Span<Color>(array).Slice(num, readOnlySpan.Length)); num += readOnlySpan.Length; ReadOnlySpan<Color> readOnlySpan2 = new ReadOnlySpan<Color>(colors2); readOnlySpan2.CopyTo(new Span<Color>(array).Slice(num, readOnlySpan2.Length)); num += readOnlySpan2.Length; return new Palette(array); } public static Palette operator *(Palette palette, int repeat) { return new Palette(Enumerable.Repeat(palette.Colors, repeat).SelectMany((Color[] x) => x).ToArray()); } public Palette Stretch(int times) { return new Palette(Colors.SelectMany((Color color) => Enumerable.Repeat<Color>(color, times)).ToArray()); } public Palette Use(Func<Palette, Palette> op) { return op(this); } } public readonly struct TimeSeries<T> { public int Length => Beats.Length; public float[] Beats { get; } public T[] Values { get; } public TimeSeries() : this(Array.Empty<float>(), Array.Empty<T>()) { } public TimeSeries(float[] beats, T[] values) { Beats = Array.Empty<float>(); Values = Array.Empty<T>(); if (beats.Length != values.Length) { throw new ArgumentOutOfRangeException($"Time series length mismatch: {beats.Length} != {values.Length}"); } SortedDictionary<float, T> sortedDictionary = new SortedDictionary<float, T>(); for (int i = 0; i < values.Length; i++) { sortedDictionary.Add(beats[i], values[i]); } Beats = sortedDictionary.Keys.ToArray(); Values = sortedDictionary.Values.ToArray(); } public override string ToString() { return "TimeSeries([" + string.Join(", ", Beats) + "], [" + string.Join(", ", Values) + "])"; } } public interface ISelectableTrack { string Name { get; init; } Language Language { get; init; } bool IsExplicit { get; init; } internal ConfigEntry<int> Weight { get; set; } internal IAudioTrack[] GetTracks(); internal IAudioTrack SelectTrack(int index); internal void Debug(); } public interface IAudioTrack { string Name { get; } float WindUpTimer { get; } float Bpm => 60f / (LoadedLoop.length / (float)Beats); int Beats { get; } int LoopOffset { get; } float LoopOffsetInSeconds => (float)LoopOffset / (float)Beats * LoadedLoop.length; AudioType AudioType { get; } AudioClip LoadedIntro { get; internal set; } AudioClip LoadedLoop { get; internal set; } string FileNameIntro { get; } string FileNameLoop { get; } string Ext { get { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Invalid comparison between Unknown and I4 //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Invalid comparison between Unknown and I4 //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Invalid comparison between Unknown and I4 AudioType audioType = AudioType; if ((int)audioType != 13) { if ((int)audioType != 14) { if ((int)audioType == 20) { return "wav"; } return ""; } return "ogg"; } return "mp3"; } } float BeatsOffset { get; } float BeatsOffsetInSeconds => BeatsOffset / (float)Beats * LoadedLoop.length; float FadeOutBeat { get; } float FadeOutDuration { get; } float ColorTransitionIn { get; } float ColorTransitionOut { get; } Easing ColorTransitionEasing { get; } float[] FlickerLightsTimeSeries { get; } float[] LyricsTimeSeries { get; } string[] LyricsLines { get; } TimeSeries<float> DrunknessLoopOffsetTimeSeries { get; } TimeSeries<float> CondensationLoopOffsetTimeSeries { get; } Palette Palette { get; } string? GameOverText => null; } public abstract class ProxyAudioTrack : IAudioTrack { internal IAudioTrack Track; string IAudioTrack.Name => Track.Name; float IAudioTrack.WindUpTimer => Track.WindUpTimer; int IAudioTrack.Beats => Track.Beats; int IAudioTrack.LoopOffset => Track.LoopOffset; AudioType IAudioTrack.AudioType => Track.AudioType; AudioClip IAudioTrack.LoadedIntro { get { return Track.LoadedIntro; } set { Track.LoadedIntro = value; } } AudioClip IAudioTrack.LoadedLoop { get { return Track.LoadedLoop; } set { Track.LoadedLoop = value; } } string IAudioTrack.FileNameIntro => Track.FileNameIntro; string IAudioTrack.FileNameLoop => Track.FileNameLoop; float IAudioTrack.BeatsOffset => Track.BeatsOffset; float IAudioTrack.FadeOutBeat => Track.FadeOutBeat; float IAudioTrack.FadeOutDuration => Track.FadeOutDuration; float IAudioTrack.ColorTransitionIn => Track.ColorTransitionIn; float IAudioTrack.ColorTransitionOut => Track.ColorTransitionOut; Easing IAudioTrack.ColorTransitionEasing => Track.ColorTransitionEasing; float[] IAudioTrack.FlickerLightsTimeSeries => Track.FlickerLightsTimeSeries; float[] IAudioTrack.LyricsTimeSeries => Track.LyricsTimeSeries; string[] IAudioTrack.LyricsLines => Track.LyricsLines; TimeSeries<float> IAudioTrack.DrunknessLoopOffsetTimeSeries => Track.DrunknessLoopOffsetTimeSeries; TimeSeries<float> IAudioTrack.CondensationLoopOffsetTimeSeries => Track.CondensationLoopOffsetTimeSeries; Palette IAudioTrack.Palette => Track.Palette; string? IAudioTrack.GameOverText => Track.GameOverText; protected ProxyAudioTrack(IAudioTrack track) { Track = track; base..ctor(); } } public class CoreAudioTrack : IAudioTrack { private string? FileNameIntroOverride; private string? FileNameLoopOverride; public float[] _FlickerLightsTimeSeries = Array.Empty<float>(); public string Name { get; init; } = ""; public float WindUpTimer { get; init; } public int Beats { get; init; } public int Bars { init { Beats = value * 4; } } public int LoopOffset { get; init; } public AudioType AudioType { get; init; } = (AudioType)13; public AudioClip LoadedIntro { get; set; } public AudioClip LoadedLoop { get; set; } public string FileNameIntro { get { return FileNameIntroOverride ?? (Name + "Intro." + ((IAudioTrack)this).Ext); } init { FileNameIntroOverride = value; } } public string FileNameLoop { get { return FileNameLoopOverride ?? (Name + "Loop." + ((IAudioTrack)this).Ext); } init { FileNameLoopOverride = value; } } public float BeatsOffset { get; init; } public float FadeOutBeat { get; init; } = float.NaN; public float FadeOutDuration { get; init; } = 2f; public float ColorTransitionIn { get; init; } = 0.25f; public float ColorTransitionOut { get; init; } = 0.25f; public Easing ColorTransitionEasing { get; init; } = Easing.OutExpo; public float[] FlickerLightsTimeSeries { get { return _FlickerLightsTimeSeries; } init { Array.Sort(value); _FlickerLightsTimeSeries = value; } } public float[] LyricsTimeSeries { get; private set; } = Array.Empty<float>(); public string[] LyricsLines { get; private set; } = Array.Empty<string>(); public (float, string)[] Lyrics { set { SortedDictionary<float, string> sortedDictionary = new SortedDictionary<float, string>(); for (int i = 0; i < value.Length; i++) { var (key, value2) = value[i]; sortedDictionary.Add(key, value2); } LyricsTimeSeries = sortedDictionary.Keys.ToArray(); LyricsLines = sortedDictionary.Values.ToArray(); } } public TimeSeries<float> DrunknessLoopOffsetTimeSeries { get; init; } = new TimeSeries<float>(); public TimeSeries<float> CondensationLoopOffsetTimeSeries { get; init; } = new TimeSeries<float>(); public Palette Palette { get; set; } = Palette.DEFAULT; public string? GameOverText { get; init; } } public class SelectableAudioTrack : CoreAudioTrack, ISelectableTrack { public Language Language { get; init; } public bool IsExplicit { get; init; } ConfigEntry<int> ISelectableTrack.Weight { get; set; } IAudioTrack[] ISelectableTrack.GetTracks() { return new IAudioTrack[1] { this }; } IAudioTrack ISelectableTrack.SelectTrack(int index) { return this; } void ISelectableTrack.Debug() { Debug.Log((object)string.Format("{0} Track \"{1}\", Intro={2:N4}, Loop={3:N4}", "MuzikaGromche", base.Name, base.LoadedIntro.length, base.LoadedLoop.length)); } } public class SelectableTracksGroup : ISelectableTrack { public IAudioTrack[] Tracks = Array.Empty<IAudioTrack>(); public string Name { get; init; } = ""; public Language Language { get; init; } public bool IsExplicit { get; init; } ConfigEntry<int> ISelectableTrack.Weight { get; set; } IAudioTrack[] ISelectableTrack.GetTracks() { return Tracks; } IAudioTrack ISelectableTrack.SelectTrack(int index) { if (Tracks.Length == 0) { throw new IndexOutOfRangeException("Tracks list is empty"); } return Mod.Index(Tracks, index); } void ISelectableTrack.Debug() { Debug.Log((object)string.Format("{0} Track Group \"{1}\", Count={2}", "MuzikaGromche", Name, Tracks.Length)); foreach (var (audioTrack, num) in Tracks.Select((IAudioTrack x, int i) => (x, i))) { Debug.Log((object)string.Format("{0} Track {1} \"{2}\", Intro={3:N4}, Loop={4:N4}", "MuzikaGromche", num, audioTrack.Name, audioTrack.LoadedIntro.length, audioTrack.LoadedLoop.length)); } } } internal readonly record struct BeatTimestamp { public float HalfLoopBeats => (float)LoopBeats / 2f; public readonly int LoopBeats; public readonly bool IsLooping; public readonly float Beat; public readonly bool IsExtrapolated; public BeatTimestamp(int loopBeats, bool isLooping, float beat, bool isExtrapolated) { IsLooping = false; Beat = 0f; IsExtrapolated = false; LoopBeats = loopBeats; IsLooping = isLooping || beat >= HalfLoopBeats; Beat = ((isLooping || beat >= (float)LoopBeats) ? Mod.Positive(beat, LoopBeats) : beat); IsExtrapolated = isExtrapolated; } public static BeatTimestamp operator +(BeatTimestamp self, float delta) { if (delta < 0f - self.HalfLoopBeats && self.Beat > self.HalfLoopBeats) { _ = self.IsLooping; } return new BeatTimestamp(self.LoopBeats, self.IsLooping, self.Beat + delta, self.IsExtrapolated); } public static BeatTimestamp operator -(BeatTimestamp self, float delta) { return self + (0f - delta); } public BeatTimestamp Floor() { float beat = Mathf.Floor(Beat); return new BeatTimestamp(LoopBeats, IsLooping, beat, IsExtrapolated); } public override string ToString() { return string.Format("{0}({1}{2} {3:N4}/{4})", "BeatTimestamp", IsLooping ? 'Y' : 'n', IsExtrapolated ? 'E' : '_', Beat, LoopBeats); } [CompilerGenerated] private bool PrintMembers(StringBuilder builder) { builder.Append("LoopBeats = "); builder.Append(LoopBeats.ToString()); builder.Append(", HalfLoopBeats = "); builder.Append(HalfLoopBeats.ToString()); builder.Append(", IsLooping = "); builder.Append(IsLooping.ToString()); builder.Append(", Beat = "); builder.Append(Beat.ToString()); builder.Append(", IsExtrapolated = "); builder.Append(IsExtrapolated.ToString()); return true; } } internal readonly record struct BeatTimeSpan { public float HalfLoopBeats => (float)LoopBeats / 2f; public readonly int LoopBeats; public readonly bool IsLooping; public readonly float BeatFromExclusive; public readonly float BeatToInclusive; public readonly bool IsExtrapolated; public static BeatTimeSpan Empty; public BeatTimeSpan(int loopBeats, bool isLooping, float beatFromExclusive, float beatToInclusive, bool isExtrapolated) { IsLooping = false; BeatFromExclusive = 0f; BeatToInclusive = 0f; IsExtrapolated = false; LoopBeats = loopBeats; IsLooping = isLooping || beatToInclusive >= HalfLoopBeats; BeatFromExclusive = wrap(beatFromExclusive); BeatToInclusive = wrap(beatToInclusive); IsExtrapolated = isExtrapolated; float wrap(float beat) { if (!isLooping && !(beat >= (float)loopBeats)) { return beat; } return Mod.Positive(beat, loopBeats); } } public static BeatTimeSpan Between(BeatTimestamp timestampFromExclusive, BeatTimestamp timestampToInclusive) { bool isExtrapolated = timestampFromExclusive.IsExtrapolated || timestampToInclusive.IsExtrapolated; return new BeatTimeSpan(timestampToInclusive.LoopBeats, timestampToInclusive.IsLooping, timestampFromExclusive.Beat, timestampToInclusive.Beat, isExtrapolated); } public static BeatTimeSpan Between(float beatFromExclusive, BeatTimestamp timestampToInclusive) { return new BeatTimeSpan(timestampToInclusive.LoopBeats, timestampToInclusive.IsLooping, beatFromExclusive, timestampToInclusive.Beat, timestampToInclusive.IsExtrapolated); } public BeatTimestamp ToTimestamp() { return new BeatTimestamp(LoopBeats, IsLooping, BeatToInclusive, IsExtrapolated); } public bool ContainsExact(float beat) { if (BeatFromExclusive < beat) { return beat <= BeatToInclusive; } return false; } public int? GetLastIndex(float[] timeSeries) { if (IsEmpty() || timeSeries == null || timeSeries.Length == 0) { return null; } if (IsWrapped()) { int? lastIndex = new BeatTimeSpan(LoopBeats, isLooping: false, -0.001f, BeatToInclusive, IsExtrapolated).GetLastIndex(timeSeries); if (lastIndex.HasValue) { return lastIndex; } int num = timeSeries.Length - 1; if (timeSeries[num] > BeatFromExclusive) { return num; } } else { int num2 = Array.BinarySearch(timeSeries, BeatToInclusive); if (num2 > 0 && num2 < timeSeries.Length && timeSeries[num2] > BeatFromExclusive) { return num2; } num2 = ~num2; num2--; if (num2 >= 0 && timeSeries[num2] > BeatFromExclusive && timeSeries[num2] <= BeatToInclusive) { return num2; } } return null; } public float Duration(bool longest = false) { if (longest) { float num = BeatToInclusive; if (BeatFromExclusive >= 0f && BeatToInclusive >= 0f && num < BeatFromExclusive) { num += (float)LoopBeats; } return Mathf.Max(0f, num - BeatFromExclusive); } if (IsEmpty()) { return 0f; } if (IsWrapped()) { float num2 = (float)LoopBeats - BeatFromExclusive; float num3 = BeatToInclusive - 0f; return num2 + num3; } return BeatToInclusive - BeatFromExclusive; } public bool IsEmpty() { if (IsLooping) { float num = BeatToInclusive; if (BeatToInclusive < BeatFromExclusive) { num = BeatToInclusive + (float)LoopBeats; } return num - BeatFromExclusive > HalfLoopBeats; } return BeatFromExclusive > BeatToInclusive; } public bool IsWrapped() { if (IsLooping && !IsEmpty()) { return BeatToInclusive < BeatFromExclusive; } return false; } public override string ToString() { return string.Format("{0}({1}{2}, {3:N4}..{4:N4}/{5}{6})", "BeatTimeSpan", IsLooping ? 'Y' : 'n', IsExtrapolated ? 'E' : '_', BeatFromExclusive, BeatToInclusive, LoopBeats, IsEmpty() ? " Empty!" : ""); } [CompilerGenerated] private bool PrintMembers(StringBuilder builder) { builder.Append("LoopBeats = "); builder.Append(LoopBeats.ToString()); builder.Append(", HalfLoopBeats = "); builder.Append(HalfLoopBeats.ToString()); builder.Append(", IsLooping = "); builder.Append(IsLooping.ToString()); builder.Append(", BeatFromExclusive = "); builder.Append(BeatFromExclusive.ToString()); builder.Append(", BeatToInclusive = "); builder.Append(BeatToInclusive.ToString()); builder.Append(", IsExtrapolated = "); builder.Append(IsExtrapolated.ToString()); return true; } } internal class ExtrapolatedAudioSourceState { private float ExtrapolatedTime; private float LastKnownNonExtrapolatedTime; private float LastKnownRealtime; private const float MaxExtrapolationInterval = 0.5f; public bool IsPlaying { get; private set; } public float Time => ExtrapolatedTime; public bool HasStarted { get; private set; } public bool IsExtrapolated => LastKnownNonExtrapolatedTime != ExtrapolatedTime; public void Update(AudioSource audioSource, float realtime) { IsPlaying = audioSource.isPlaying; HasStarted |= audioSource.time != 0f; if (LastKnownNonExtrapolatedTime != audioSource.time) { LastKnownRealtime = realtime; LastKnownNonExtrapolatedTime = (ExtrapolatedTime = audioSource.time); } else if (IsPlaying && HasStarted && Config.ExtrapolateTime) { float num = realtime - LastKnownRealtime; if (0f < num && num < 0.5f) { ExtrapolatedTime = LastKnownNonExtrapolatedTime + num; } } } public override string ToString() { return string.Format("{0}({1}{2} ", "ExtrapolatedAudioSourceState", IsPlaying ? 'P' : '_', HasStarted ? 'S' : '0') + (IsExtrapolated ? $"{LastKnownRealtime:N4}, {LastKnownNonExtrapolatedTime:N4} => {ExtrapolatedTime:N4}" : $"{LastKnownRealtime:N4}, {LastKnownNonExtrapolatedTime:N4}") + ")"; } } internal class JesterAudioSourcesState { private readonly float IntroClipLength; private readonly ExtrapolatedAudioSourceState Intro = new ExtrapolatedAudioSourceState(); private readonly ExtrapolatedAudioSourceState Loop = new ExtrapolatedAudioSourceState(); private bool ReferenceIsIntro = true; public bool HasStarted => Intro.HasStarted; public bool IsExtrapolated { get { if (!ReferenceIsIntro) { return Loop.IsExtrapolated; } return Intro.IsExtrapolated; } } public float Time { get { if (!ReferenceIsIntro) { return IntroClipLength + Loop.Time; } return Intro.Time; } } public JesterAudioSourcesState(float introClipLength) { IntroClipLength = introClipLength; } public void Update(AudioSource intro, AudioSource loop, float realtime) { Loop.Update(loop, realtime); if (!Loop.HasStarted) { Intro.Update(intro, realtime); } else { ReferenceIsIntro = false; } } } internal class AudioLoopingState { private readonly float StartOfLoop; private readonly float LoopLength; private readonly int Beats; public bool IsLooping { get; private set; } public AudioLoopingState(float startOfLoop, float loopLength, int beats) { StartOfLoop = startOfLoop; LoopLength = loopLength; Beats = beats; } public BeatTimestamp Update(float time, bool isExtrapolated, float additionalOffset) { float num = StartOfLoop + additionalOffset; float beat = (time - num) / LoopLength * (float)Beats; BeatTimestamp result = new BeatTimestamp(Beats, IsLooping, beat, isExtrapolated); IsLooping |= result.IsLooping; return result; } } internal class BeatTimeState { private readonly IAudioTrack track; private readonly JesterAudioSourcesState AudioState; private readonly AudioLoopingState WindUpLoopingState; private readonly AudioLoopingState LoopLoopingState; private float LastKnownLoopOffsetBeat = float.NegativeInfinity; private static Random LyricsRandom; private int LyricsRandomPerLoop; private bool WindUpZeroBeatEventTriggered; public BeatTimeState(IAudioTrack track) { if (LyricsRandom == null) { LyricsRandom = new Random(RoundManager.Instance.playersManager.randomMapSeed + 1337); LyricsRandomPerLoop = LyricsRandom.Next(); } this.track = track; AudioState = new JesterAudioSourcesState(track.LoadedIntro.length); WindUpLoopingState = new AudioLoopingState(track.WindUpTimer, track.LoadedLoop.length, track.Beats); LoopLoopingState = new AudioLoopingState(track.WindUpTimer + track.LoopOffsetInSeconds, track.LoadedLoop.length, track.Beats); } public List<BaseEvent> Update(AudioSource intro, AudioSource loop) { float realtimeSinceStartup = Time.realtimeSinceStartup; AudioState.Update(intro, loop, realtimeSinceStartup); if (AudioState.HasStarted) { BeatTimestamp beatTimestamp = Update(LoopLoopingState); BeatTimeSpan loopOffsetSpan = BeatTimeSpan.Between(LastKnownLoopOffsetBeat, beatTimestamp); if (!loopOffsetSpan.IsEmpty()) { if (loopOffsetSpan.BeatFromExclusive > loopOffsetSpan.BeatToInclusive) { LyricsRandomPerLoop = LyricsRandom.Next(); } BeatTimestamp windUpOffsetTimestamp = Update(WindUpLoopingState); LastKnownLoopOffsetBeat = beatTimestamp.Beat; return GetEvents(beatTimestamp, loopOffsetSpan, windUpOffsetTimestamp); } } return new List<BaseEvent>(); } private BeatTimestamp Update(AudioLoopingState loopingState) { return loopingState.Update(AudioState.Time, AudioState.IsExtrapolated, AdditionalOffset()); } private float AdditionalOffset() { return Config.AudioOffset.Value + track.BeatsOffsetInSeconds; } private List<BaseEvent> GetEvents(BeatTimestamp loopOffsetTimestamp, BeatTimeSpan loopOffsetSpan, BeatTimestamp windUpOffsetTimestamp) { List<BaseEvent> list = new List<BaseEvent>(); if (windUpOffsetTimestamp.Beat >= 0f && !WindUpZeroBeatEventTriggered) { list.Add(new WindUpZeroBeatEvent()); WindUpZeroBeatEventTriggered = true; } SetLightsColorEvent colorEvent = GetColorEvent(loopOffsetSpan, windUpOffsetTimestamp); if (colorEvent != null) { list.Add(colorEvent); } if (loopOffsetSpan.GetLastIndex(track.FlickerLightsTimeSeries).HasValue) { list.Add(new FlickerLightsEvent()); } if (Config.DisplayLyrics.Value) { int? lastIndex = loopOffsetSpan.GetLastIndex(track.LyricsTimeSeries); if (lastIndex.HasValue) { int valueOrDefault = lastIndex.GetValueOrDefault(); if (valueOrDefault < track.LyricsLines.Length) { string[] array = track.LyricsLines[valueOrDefault].Split('\t'); int num = LyricsRandomPerLoop % array.Length; string text = array[num]; if (text != "") { list.Add(new LyricsEvent(text)); } } } } float? interpolation = GetInterpolation(loopOffsetTimestamp, track.DrunknessLoopOffsetTimeSeries, Easing.Linear); if (interpolation.HasValue) { float valueOrDefault2 = interpolation.GetValueOrDefault(); list.Add(new DrunkEvent(valueOrDefault2)); } interpolation = GetInterpolation(loopOffsetTimestamp, track.CondensationLoopOffsetTimeSeries, Easing.Linear); if (interpolation.HasValue) { float valueOrDefault3 = interpolation.GetValueOrDefault(); list.Add(new CondensationEvent(valueOrDefault3)); } return list; } private SetLightsColorEvent? GetColorEvent(BeatTimeSpan loopOffsetSpan, BeatTimestamp windUpOffsetTimestamp) { SetLightsColorTransitionEvent setLightsColorTransitionEvent = FadeOut(loopOffsetSpan, windUpOffsetTimestamp); if (setLightsColorTransitionEvent != null) { return setLightsColorTransitionEvent; } SetLightsColorEvent setLightsColorEvent = ColorFromPaletteAtTimestamp(windUpOffsetTimestamp); if (setLightsColorEvent != null) { return setLightsColorEvent; } return null; } private SetLightsColorTransitionEvent? FadeOut(BeatTimeSpan loopOffsetSpan, BeatTimestamp windUpOffsetTimestamp) { //IL_0069: Unknown result type (might be due to invalid IL or missing references) float num = track.FadeOutBeat + track.FadeOutDuration; if (windUpOffsetTimestamp.Beat < 0f && track.FadeOutBeat < loopOffsetSpan.BeatToInclusive && loopOffsetSpan.BeatFromExclusive <= num) { float t = (loopOffsetSpan.BeatToInclusive - track.FadeOutBeat) / track.FadeOutDuration; return new SetLightsColorTransitionEvent(null, Color.black, Easing.Linear, t); } return null; } public SetLightsColorEvent? ColorFromPaletteAtTimestamp(BeatTimestamp timestamp) { if (timestamp.Beat <= 0f - track.ColorTransitionIn) { return null; } BeatTimestamp beatTimestamp = timestamp.Floor(); BeatTimestamp beatTimestamp2 = beatTimestamp + 1f; float transitionLength = track.ColorTransitionIn + track.ColorTransitionOut; if ((double)transitionLength > 0.01) { if (BeatTimeSpan.Between(beatTimestamp, timestamp).Duration() < track.ColorTransitionOut) { return ColorTransition(beatTimestamp); } if (BeatTimeSpan.Between(timestamp, beatTimestamp2).Duration() < track.ColorTransitionIn) { return ColorTransition(beatTimestamp2); } } return new SetLightsColorStaticEvent(ColorAtWholeBeat(timestamp)); Color? ColorAtWholeBeat(BeatTimestamp timestamp) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) if (timestamp.Beat >= 0f) { int index = Mathf.FloorToInt(timestamp.Beat); return Mod.Index(track.Palette.Colors, index); } if (!float.IsNaN(track.FadeOutBeat)) { return Color.black; } return null; } SetLightsColorTransitionEvent ColorTransition(BeatTimestamp clipsBoundary) { BeatTimestamp beatTimestamp3 = clipsBoundary - track.ColorTransitionIn; BeatTimestamp timestamp2 = clipsBoundary + track.ColorTransitionOut; float t = BeatTimeSpan.Between(beatTimestamp3, timestamp).Duration() / transitionLength; if (track.ColorTransitionIn == 0f) { beatTimestamp3 -= 0.01f; } return new SetLightsColorTransitionEvent(ColorAtWholeBeat(beatTimestamp3), ColorAtWholeBeat(timestamp2), track.ColorTransitionEasing, t); } } private float? GetInterpolation(BeatTimestamp timestamp, TimeSeries<float> timeSeries, Easing easing) { if (timeSeries.Length == 0) { return null; } if (timeSeries.Length == 1) { return timeSeries.Values[0]; } int? num = null; for (int num2 = timeSeries.Length - 1; num2 >= 0; num2--) { if (timeSeries.Beats[num2] <= timestamp.Beat) { num = num2; break; } } if (!num.HasValue && timestamp.IsLooping) { num = timeSeries.Length - 1; } int? num3 = null; for (int i = 0; i < timeSeries.Length; i++) { if (timeSeries.Beats[i] >= timestamp.Beat) { num3 = i; break; } } if (!num3.HasValue && timestamp.IsLooping) { for (int j = 0; j < timeSeries.Length; j++) { if (timeSeries.Beats[j] >= 0f) { num3 = j; break; } } } int? num4 = num; int? num5 = num3; if (!num4.HasValue) { if (num5.HasValue) { int valueOrDefault = num5.GetValueOrDefault(); return timeSeries.Values[valueOrDefault]; } return null; } int valueOrDefault2 = num4.GetValueOrDefault(); if (num5.HasValue) { int valueOrDefault = num5.GetValueOrDefault(); int num6 = valueOrDefault2; int num7 = valueOrDefault; if (num6 == num7 || timeSeries.Beats[num6] == timeSeries.Beats[num7]) { return timeSeries.Values[num6]; } int num8 = valueOrDefault2; int num9 = valueOrDefault; float beat = timeSeries.Beats[num8]; float beat2 = timeSeries.Beats[num9]; BeatTimestamp timestampFromExclusive = new BeatTimestamp(timestamp.LoopBeats, isLooping: false, beat, isExtrapolated: false); BeatTimestamp timestampToInclusive = new BeatTimestamp(timestamp.LoopBeats, isLooping: false, beat2, isExtrapolated: false); float arg = BeatTimeSpan.Between(timestampFromExclusive, timestamp).Duration(longest: true) / BeatTimeSpan.Between(timestampFromExclusive, timestampToInclusive).Duration(longest: true); float num10 = timeSeries.Values[num8]; float num11 = timeSeries.Values[num9]; return Mathf.Lerp(num10, num11, easing.Eval(arg)); } return timeSeries.Values[valueOrDefault2]; } } internal abstract class BaseEvent { } internal abstract class SetLightsColorEvent : BaseEvent { public abstract Color GetColor(Color initialColor); protected string NullableColorToString(Color? color) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) if (color.HasValue) { Color valueOrDefault = color.GetValueOrDefault(); return ColorUtility.ToHtmlStringRGB(valueOrDefault); } return "??????"; } } internal class SetLightsColorStaticEvent : SetLightsColorEvent { public readonly Color? Color; public SetLightsColorStaticEvent(Color? color) { Color = color; base..ctor(); } public override Color GetColor(Color initialColor) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) Color? color = Color; return color.GetValueOrDefault(initialColor); } public override string ToString() { return "Color(#" + NullableColorToString(Color) + ")"; } } internal class SetLightsColorTransitionEvent : SetLightsColorEvent { public readonly Color? From; public readonly Color? To; public readonly Easing Easing; public readonly float T; public SetLightsColorTransitionEvent(Color? from, Color? to, Easing easing, float t) { From = from; To = to; Easing = easing; T = t; base..ctor(); } public override Color GetColor(Color initialColor) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) Color? from = From; Color valueOrDefault = from.GetValueOrDefault(initialColor); from = To; Color valueOrDefault2 = from.GetValueOrDefault(initialColor); return Color.Lerp(valueOrDefault, valueOrDefault2, Mathf.Clamp(Easing.Eval(T), 0f, 1f)); } private Color? GetNullableColor() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) Color? from = From; if (from.HasValue) { Color valueOrDefault = from.GetValueOrDefault(); from = To; if (from.HasValue) { Color valueOrDefault2 = from.GetValueOrDefault(); return Color.Lerp(valueOrDefault, valueOrDefault2, Mathf.Clamp(Easing.Eval(T), 0f, 1f)); } } return null; } public override string ToString() { return $"Color(#{NullableColorToString(GetNullableColor())} = #{NullableColorToString(From)}..#{NullableColorToString(To)} {Easing} {T:N4})"; } } internal class FlickerLightsEvent : BaseEvent { public override string ToString() { return "Flicker"; } } internal class LyricsEvent : BaseEvent { public readonly string Text; public LyricsEvent(string text) { Text = text; base..ctor(); } public override string ToString() { return "Lyrics(" + Text.Replace("\n", "\\n") + ")"; } } internal class WindUpZeroBeatEvent : BaseEvent { public override string ToString() { return "WindUp"; } } internal abstract class HUDEvent : BaseEvent { } internal class DrunkEvent : HUDEvent { public readonly float Drunkness; public DrunkEvent(float drunkness) { Drunkness = drunkness; base..ctor(); } public override string ToString() { return $"Drunk({Drunkness:N2})"; } } internal class CondensationEvent : HUDEvent { public readonly float Condensation; public CondensationEvent(float condensation) { Condensation = condensation; base..ctor(); } public override string ToString() { return $"Condensation({Condensation:N2})"; } } internal static class Mod { public static int Positive(int x, int m) { int num = x % m; if (num >= 0) { return num; } return num + m; } public static float Positive(float x, float m) { float num = x % m; if (!(num < 0f)) { return num; } return num + m; } public static T Index<T>(IList<T> array, int index) { return array[Positive(index, array.Count)]; } } internal readonly struct RandomWeightedIndex { private readonly int[] Weights; public int TotalWeights { get; } public RandomWeightedIndex(int[] weights) { Weights = weights; TotalWeights = Weights.Sum(); if (TotalWeights == 0) { Weights = Weights.Select((int _) => 1).ToArray(); TotalWeights = Weights.Length; } } private byte[] GetHash(int seed) { byte[] array = new byte[4 * (1 + Weights.Length)]; int num = 0; Buffer.BlockCopy(BitConverter.GetBytes(seed), 0, array, num, 4); int[] weights = Weights; foreach (int value in weights) { num += 4; Buffer.BlockCopy(BitConverter.GetBytes(value), 0, array, num, 4); } return SHA256.Create().ComputeHash(array); } private int GetRawIndex(byte[] hash) { if (TotalWeights == 0) { return -1; } int num = 0; foreach (byte b in hash) { num *= 256 % TotalWeights; num %= TotalWeights; num += b % TotalWeights; num %= TotalWeights; } return num; } private int GetWeightedIndex(int rawIndex) { if (rawIndex < 0 || rawIndex >= TotalWeights) { return -1; } int num = 0; foreach (var item3 in Weights.Select((int x, int i) => (x, i))) { int item = item3.Item1; int item2 = item3.Item2; num += item; if (rawIndex < num) { return item2; } } return -1; } public int GetRandomWeightedIndex(int seed) { byte[] hash = GetHash(seed); int rawIndex = GetRawIndex(hash); return GetWeightedIndex(rawIndex); } public override string ToString() { return $"Weighted(Total={TotalWeights}, Weights=[{string.Join(',', Weights)}])"; } } internal class Config { private const float VolumeDefault = 0.35f; private const float VolumeMin = 0.2f; private const float VolumeMax = 0.5f; public static ConfigEntry<bool> DisplayLyrics { get; private set; } = null; public static ConfigEntry<float> AudioOffset { get; private set; } = null; public static ConfigEntry<bool> SkipExplicitTracks { get; private set; } = null; public static ConfigEntry<bool> OverrideSpawnRates { get; private set; } = null; public static bool ExtrapolateTime { get; private set; } = true; public static bool ShouldSkipWindingPhase { get; private set; } = false; public static ConfigEntry<float> Volume { get; private set; } = null; internal Config(ConfigFile configFile) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Expected O, but got Unknown //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Expected O, but got Unknown //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Expected O, but got Unknown //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Expected O, but got Unknown //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Expected O, but got Unknown //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Expected O, but got Unknown //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Expected O, but got Unknown //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Expected O, but got Unknown //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: Expected O, but got Unknown //IL_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Expected O, but got Unknown //IL_0249: Unknown result type (might be due to invalid IL or missing references) //IL_025e: Unknown result type (might be due to invalid IL or missing references) //IL_0268: Expected O, but got Unknown //IL_0268: Expected O, but got Unknown //IL_0275: Unknown result type (might be due to invalid IL or missing references) //IL_027f: Expected O, but got Unknown DisplayLyrics = configFile.Bind<bool>("General", "Display Lyrics", true, new ConfigDescription("Display lyrics in the HUD tooltip when you hear the music.", (AcceptableValueBase)null, Array.Empty<object>())); LethalConfigManager.AddConfigItem((BaseConfigItem)new BoolCheckBoxConfigItem(DisplayLyrics, false)); Volume = configFile.Bind<float>("General", "Volume", 0.35f, new ConfigDescription("Volume of music played by this mod.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 0.5f), Array.Empty<object>())); LethalConfigManager.AddConfigItem((BaseConfigItem)new FloatSliderConfigItem(Volume, false)); AudioOffset = configFile.Bind<float>("General", "Audio Offset", 0f, new ConfigDescription("Adjust audio offset (in seconds).\n\nIf you are playing with Bluetooth headphones and experiencing a visual desync, try setting this to about negative 0.2.\n\nIf your video output has high latency (like a long HDMI cable etc.), try positive values instead.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-0.5f, 0.5f), Array.Empty<object>())); LethalConfigManager.AddConfigItem((BaseConfigItem)new FloatSliderConfigItem(AudioOffset, false)); SkipExplicitTracks = configFile.Bind<bool>("General", "Skip Explicit Tracks", false, new ConfigDescription("When choosing tracks at random, skip the ones with Explicit Content/Lyrics.", (AcceptableValueBase)null, Array.Empty<object>())); LethalConfigManager.AddConfigItem((BaseConfigItem)new BoolCheckBoxConfigItem(SkipExplicitTracks, false)); OverrideSpawnRates = configFile.Bind<bool>("General", "Override Spawn Rates", true, new ConfigDescription("Deviate from vanilla spawn rates to experience content of this mod more often.", (AcceptableValueBase)null, Array.Empty<object>())); LethalConfigManager.AddConfigItem((BaseConfigItem)new BoolCheckBoxConfigItem(OverrideSpawnRates, false)); AcceptableValueRange<int> val = new AcceptableValueRange<int>(0, 100); HashSet<Language> hashSet = new HashSet<Language>(); ISelectableTrack[] tracks = Plugin.Tracks; foreach (ISelectableTrack selectableTrack in tracks) { Language language = selectableTrack.Language; string text = "Tracks." + language.Short; if (!hashSet.Contains(language)) { hashSet.Add(language); string text2 = "Toggle all " + language.Full + " tracks"; string text3 = "Toggle all tracks in this section ON or OFF. Effective immediately."; string text4 = "Toggle"; LethalConfigManager.AddConfigItem((BaseConfigItem)new GenericButtonConfigItem(text, text2, text3, text4, (GenericButtonHandler)delegate { List<ISelectableTrack> list = Plugin.Tracks.Where((ISelectableTrack t) => t.Language.Equals(language)).ToList(); int value = (list.All((ISelectableTrack t) => t.Weight.Value == 0) ? 50 : 0); foreach (ISelectableTrack item in list) { item.Weight.Value = value; } })); } string text5 = (selectableTrack.IsExplicit ? "Explicit Content/Lyrics!\n\n" : ""); string text6 = "Language: " + language.Full + "\n\n" + text5 + "Random (relative) chance of selecting this track.\n\nSet to zero to effectively disable the track."; selectableTrack.Weight = configFile.Bind<int>(new ConfigDefinition(text, selectableTrack.Name), 50, new ConfigDescription(text6, (AcceptableValueBase)(object)val, new object[1] { selectableTrack })); LethalConfigManager.AddConfigItem((BaseConfigItem)new IntSliderConfigItem(selectableTrack.Weight, false)); } } internal static IAudioTrack OverrideCurrentTrack(IAudioTrack track) { return track; } } [HarmonyPatch(typeof(GameNetworkManager))] internal static class GameNetworkManagerPatch { private const string JesterEnemyPrefabName = "JesterEnemy"; [HarmonyPatch("Start")] [HarmonyPrefix] private static void StartPrefix(GameNetworkManager __instance) { NetworkPrefab val = ((IEnumerable<NetworkPrefab>)NetworkManager.Singleton.NetworkConfig.Prefabs.Prefabs).FirstOrDefault((Func<NetworkPrefab, bool>)((NetworkPrefab prefab) => ((Object)prefab.Prefab).name == "JesterEnemy")); if (val == null) { Debug.LogError((object)"MuzikaGromche JesterEnemy prefab not found!"); return; } val.Prefab.AddComponent<MuzikaGromcheJesterNetworkBehaviour>(); Debug.Log((object)"MuzikaGromche Patched JesterEnemy"); } } internal class MuzikaGromcheJesterNetworkBehaviour : NetworkBehaviour { [CompilerGenerated] private sealed class <ChooseTrackDeferredCoroutine>d__15 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public MuzikaGromcheJesterNetworkBehaviour <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <ChooseTrackDeferredCoroutine>d__15(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown int num = <>1__state; MuzikaGromcheJesterNetworkBehaviour muzikaGromcheJesterNetworkBehaviour = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForEndOfFrame(); <>1__state = 1; return true; case 1: <>1__state = -1; muzikaGromcheJesterNetworkBehaviour.DeferredCoroutine = null; muzikaGromcheJesterNetworkBehaviour.ChooseTrackServerRpc(); 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 const string IntroAudioGameObjectName = "MuzikaGromcheAudio (Intro)"; private const string LoopAudioGameObjectName = "MuzikaGromcheAudio (Loop)"; private int SelectedTrackIndex; internal IAudioTrack? CurrentTrack; internal BeatTimeState? BeatTimeState; internal AudioSource IntroAudioSource; internal AudioSource LoopAudioSource; private Coroutine? DeferredCoroutine; private void Awake() { Transform val = ((Component)this).gameObject.transform.Find("FarAudio"); if ((Object)(object)val == (Object)null) { Debug.LogError((object)"MuzikaGromche JesterEnemy->FarAudio prefab not found!"); return; } GameObject val2 = Object.Instantiate<GameObject>(((Component)val).gameObject, ((Component)this).gameObject.transform); ((Object)val2).name = "MuzikaGromcheAudio (Intro)"; GameObject val3 = Object.Instantiate<GameObject>(((Component)val).gameObject, ((Component)this).gameObject.transform); ((Object)val3).name = "MuzikaGromcheAudio (Loop)"; IntroAudioSource = val2.GetComponent<AudioSource>(); IntroAudioSource.maxDistance = 150f; IntroAudioSource.dopplerLevel = 0f; IntroAudioSource.loop = false; IntroAudioSource.volume = Config.Volume.Value; LoopAudioSource = val3.GetComponent<AudioSource>(); LoopAudioSource.maxDistance = 150f; LoopAudioSource.dopplerLevel = 0f; LoopAudioSource.loop = true; LoopAudioSource.volume = Config.Volume.Value; Config.Volume.SettingChanged += UpdateVolume; Debug.Log((object)"MuzikaGromche MuzikaGromcheJesterNetworkBehaviour Patched JesterEnemy"); } public override void OnDestroy() { Config.Volume.SettingChanged -= UpdateVolume; } private void UpdateVolume(object sender, EventArgs e) { if ((Object)(object)IntroAudioSource != (Object)null && (Object)(object)LoopAudioSource != (Object)null) { IntroAudioSource.volume = Config.Volume.Value; LoopAudioSource.volume = Config.Volume.Value; } } public override void OnNetworkSpawn() { ChooseTrackDeferred(); ISelectableTrack[] tracks = Plugin.Tracks; for (int i = 0; i < tracks.Length; i++) { tracks[i].Weight.SettingChanged += ChooseTrackDeferredDelegate; } Config.SkipExplicitTracks.SettingChanged += ChooseTrackDeferredDelegate; ((NetworkBehaviour)this).OnNetworkSpawn(); } public override void OnNetworkDespawn() { ISelectableTrack[] tracks = Plugin.Tracks; for (int i = 0; i < tracks.Length; i++) { tracks[i].Weight.SettingChanged -= ChooseTrackDeferredDelegate; } Config.SkipExplicitTracks.SettingChanged -= ChooseTrackDeferredDelegate; ((NetworkBehaviour)this).OnNetworkDespawn(); } private void ChooseTrackDeferredDelegate(object sender, EventArgs e) { SelectedTrackIndex = 0; ChooseTrackDeferred(); } private void ChooseTrackDeferred() { if (DeferredCoroutine != null) { ((MonoB