using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using HarmonyLib; using Il2CppInterop.Runtime.InteropTypes.Arrays; using LightFlickerZooks; using MelonLoader; using MelonLoader.Utils; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.Audio; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: MelonInfo(typeof(LightFlickerMod), "LightFlickerGB", "1.0.0", "Zooks", null)] [assembly: MelonGame("Boneloaf", "Gang Beasts")] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("SubwayDeathGB")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("sd for GB")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("SubwayDeathGB")] [assembly: AssemblyTitle("SubwayDeathGB")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace LightFlickerZooks { public class LightFlickerMod : MelonMod { [CompilerGenerated] private sealed class d__17 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__17(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(2f); <>1__state = 1; return true; case 1: <>1__state = -1; CacheMapLights(); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__23 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public List lights; private float 5__2; private float 5__3; private Dictionary 5__4; private float 5__5; private Color 5__6; private float 5__7; private float 5__8; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__23(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } 5__4 = null; <>1__state = -2; } private bool MoveNext() { //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Expected O, but got Unknown try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; isFlickering = true; 5__2 = 1.5f; 5__3 = 0f; 5__4 = lights.ToDictionary((Light l) => l, (Light l) => ((Behaviour)l).enabled); 5__5 = RenderSettings.ambientIntensity; 5__6 = RenderSettings.ambientLight; 5__7 = RenderSettings.reflectionIntensity; <>1__state = -3; break; case 1: <>1__state = -3; 5__3 += 5__8; break; } if (5__3 < 5__2) { bool flag = Random.value > 0.45f; float num = (flag ? 1f : 0f); foreach (Light light in lights) { if ((Object)(object)light != (Object)null) { ((Behaviour)light).enabled = 5__4[light] && flag; } } foreach (Renderer lightRenderer in lightRenderers) { SetRendererColor(lightRenderer, flag); } RenderSettings.ambientIntensity = 5__5 * num; RenderSettings.ambientLight = 5__6 * num; RenderSettings.reflectionIntensity = 5__7 * num; 5__8 = Random.Range(0.04f, 0.12f); <>2__current = (object)new WaitForSeconds(5__8); <>1__state = 1; return true; } <>m__Finally1(); return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { //IL_009e: Unknown result type (might be due to invalid IL or missing references) <>1__state = -1; foreach (Light light in lights) { if ((Object)(object)light != (Object)null && 5__4.ContainsKey(light)) { ((Behaviour)light).enabled = 5__4[light]; } } foreach (Renderer lightRenderer in lightRenderers) { SetRendererColor(lightRenderer, restore: true); } RenderSettings.ambientIntensity = 5__5; RenderSettings.ambientLight = 5__6; RenderSettings.reflectionIntensity = 5__7; isFlickering = false; } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private static string soundFilePath; private static AudioClip deathClip; private static bool isFlickering = false; private static bool isMapActive = false; private static float lastTriggerTime = -999f; private static AudioSource activeSource = null; private static readonly string[] AllowedMaps = new string[4] { "subway", "lighthouse", "chute", "grind" }; private static readonly string[] LightKeywords = new string[8] { "light", "neon", "bulb", "lamp", "fixture", "glow", "emiss", "spotlight" }; private static List cachedMapLights = new List(); private static List lightRenderers = new List(); private static Dictionary originalEmissionColors = new Dictionary(); private static Dictionary originalEmissionKeywords = new Dictionary(); private static Dictionary originalBaseColors = new Dictionary(); public override void OnInitializeMelon() { //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Expected O, but got Unknown //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Expected O, but got Unknown soundFilePath = Path.Combine(MelonEnvironment.UserDataDirectory, "LightFlicker", "lightflicker.wav"); Directory.CreateDirectory(Path.GetDirectoryName(soundFilePath)); if (!File.Exists(soundFilePath)) { MelonLogger.Error("[LightFlicker] Place 'lightflicker.wav' in: " + Path.GetDirectoryName(soundFilePath)); } Harmony val = new Harmony("LightFlicker"); Dictionary dictionary = new Dictionary { { "Actor", "Eliminate" }, { "HealthTracker", "Kill" }, { "ActorDeathAudio", "OnBeastDeath" }, { "BreakJointsOnDeath", "OnDeath" } }; foreach (Assembly item in from a in AppDomain.CurrentDomain.GetAssemblies() where ((ReadOnlySpan)new string[4] { "Il2CppAssembly-CSharp", "Il2CppFemur", "Il2CppGB", "Assembly-CSharp" }).Contains(a.GetName().Name) select a) { try { Type[] types = item.GetTypes(); foreach (Type type in types) { if (type == null || !dictionary.ContainsKey(type.Name)) { continue; } string methodTarget = dictionary[type.Name]; foreach (MethodInfo item2 in from m in type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) where m.Name == methodTarget && !m.IsGenericMethod select m) { try { HarmonyMethod val2 = new HarmonyMethod(typeof(LightFlickerMod).GetMethod((type.Name == "Actor") ? "OnActorEliminatedPostfix" : "OnGenericDeathPostfix")); val.Patch((MethodBase)item2, (HarmonyMethod)null, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); MelonLogger.Msg("[LightFlicker] Patched " + type.Name + "." + methodTarget); } catch { } } } } catch { } } } public override void OnLateInitializeMelon() { if (File.Exists(soundFilePath)) { deathClip = LoadWavFile(soundFilePath); } } private static AudioClip LoadWavFile(string filePath) { try { byte[] array = File.ReadAllBytes(filePath); if (array.Length < 44) { return null; } int num = 12; int num2 = 0; int num3 = 0; int num4 = 0; int num5 = 0; int num6 = 0; while (num < array.Length - 8) { char c = (char)array[num]; string text = c.ToString(); c = (char)array[num + 1]; string text2 = c.ToString(); c = (char)array[num + 2]; string text3 = c.ToString(); c = (char)array[num + 3]; string text4 = text + text2 + text3 + c; int num7 = BitConverter.ToInt32(array, num + 4); num += 8; if (num + num7 > array.Length) { break; } if (text4 == "fmt ") { num2 = BitConverter.ToInt16(array, num + 2); num3 = BitConverter.ToInt32(array, num + 4); num4 = BitConverter.ToInt16(array, num + 14); } else if (text4 == "data") { num5 = num; num6 = num7; break; } num += num7; } if (num5 == 0 || num6 == 0 || num2 == 0) { return null; } int num8 = num6 / (num4 / 8); float[] array2 = new float[num8]; for (int i = 0; i < num8; i++) { switch (num4) { case 16: array2[i] = (float)BitConverter.ToInt16(array, num5 + i * 2) / 32768f; break; case 24: { int num9 = num5 + i * 3; int num10 = array[num9] | (array[num9 + 1] << 8) | (array[num9 + 2] << 16); if (((uint)num10 & 0x800000u) != 0) { num10 |= -16777216; } array2[i] = (float)num10 / 8388608f; break; } case 32: array2[i] = BitConverter.ToSingle(array, num5 + i * 4); break; case 8: array2[i] = (float)(array[num5 + i] - 128) / 128f; break; } } AudioClip obj = AudioClip.Create("LightFlickerSound", num8 / num2, num2, num3, false); obj.SetData(Il2CppStructArray.op_Implicit(array2), 0); ((Object)obj).hideFlags = (HideFlags)52; return obj; } catch (Exception ex) { MelonLogger.Error("[LightFlicker] WAV Error: " + ex.Message); return null; } } public override void OnSceneWasLoaded(int buildIndex, string sceneName) { isMapActive = AllowedMaps.Any((string map) => sceneName.ToLower().Contains(map)); isFlickering = false; if (isMapActive) { MelonCoroutines.Start(DelayedCacheMapLights()); return; } cachedMapLights.Clear(); lightRenderers.Clear(); } [IteratorStateMachine(typeof(d__17))] private static IEnumerator DelayedCacheMapLights() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__17(0); } private static void CacheMapLights() { //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) try { cachedMapLights.Clear(); lightRenderers.Clear(); originalEmissionColors.Clear(); originalEmissionKeywords.Clear(); originalBaseColors.Clear(); cachedMapLights.AddRange(((IEnumerable)Resources.FindObjectsOfTypeAll()).Where(delegate(Light l) { //IL_0013: 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) object obj3; if (l == null) { obj3 = null; } else { GameObject gameObject2 = ((Component)l).gameObject; if (gameObject2 == null) { obj3 = null; } else { Scene scene2 = gameObject2.scene; obj3 = ((Scene)(ref scene2)).name; } } return obj3 != null; })); foreach (Renderer item in ((IEnumerable)Resources.FindObjectsOfTypeAll()).Where(delegate(Renderer r) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) Renderer obj = r; object obj2; if (obj == null) { obj2 = null; } else { GameObject gameObject = ((Component)obj).gameObject; if (gameObject == null) { obj2 = null; } else { Scene scene = gameObject.scene; obj2 = ((Scene)(ref scene)).name; } } return obj2 != null && LightKeywords.Any((string k) => ((Object)((Component)r).gameObject).name.ToLower().Contains(k) || ((Object)(object)r.sharedMaterial != (Object)null && ((Object)r.sharedMaterial).name.ToLower().Contains(k))); })) { Material material = item.material; if (!((Object)(object)material != (Object)null)) { continue; } bool flag = false; if (material.HasProperty("_EmissionColor")) { lightRenderers.Add(item); originalEmissionColors[item] = material.GetColor("_EmissionColor"); originalEmissionKeywords[item] = material.IsKeywordEnabled("_EMISSION"); flag = true; } string text = (material.HasProperty("_BaseColor") ? "_BaseColor" : (material.HasProperty("_Color") ? "_Color" : null)); if (text != null) { if (!flag) { lightRenderers.Add(item); } originalBaseColors[item] = material.GetColor(text); } } MelonLogger.Msg($"[LightFlicker] Cached {cachedMapLights.Count} lights & {lightRenderers.Count} meshes."); } catch (Exception ex) { MelonLogger.Error("[LightFlicker] Cache Error: " + ex.Message); } } public static void OnPlayerDeath(Vector3 position) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) if (isMapActive && !(Time.time - lastTriggerTime < 0.15f)) { lastTriggerTime = Time.time; Play3DSound(position); TriggerFlicker(); } } private static void Play3DSound(Vector3 position) { if ((Object)(object)deathClip == (Object)null || ((Object)(object)activeSource != (Object)null && activeSource.isPlaying)) { return; } try { if (!((Object)(object)Camera.main == (Object)null)) { activeSource = ((Component)Camera.main).gameObject.AddComponent(); activeSource.clip = deathClip; AudioMixerGroup val = ((IEnumerable)Resources.FindObjectsOfTypeAll()).FirstOrDefault((Func)((AudioMixerGroup g) => (Object)(object)g != (Object)null && ((Object)g).name.Equals("Vocals", StringComparison.OrdinalIgnoreCase))); if ((Object)(object)val != (Object)null) { activeSource.outputAudioMixerGroup = val; } activeSource.spatialBlend = 1f; activeSource.volume = 0.75f; activeSource.minDistance = 100f; activeSource.maxDistance = 1000f; activeSource.rolloffMode = (AudioRolloffMode)0; activeSource.Play(); Object.Destroy((Object)(object)activeSource, deathClip.length + 0.5f); } } catch (Exception ex) { MelonLogger.Error("[LightFlicker] PlayAudio Error: " + ex.Message); } } private static void TriggerFlicker() { if (!isFlickering) { if (cachedMapLights.Count == 0) { CacheMapLights(); } cachedMapLights.RemoveAll((Light l) => (Object)(object)l == (Object)null); lightRenderers.RemoveAll((Renderer r) => (Object)(object)r == (Object)null); if (cachedMapLights.Count > 0) { MelonCoroutines.Start(FlickerRoutine(cachedMapLights)); } } } private static void SetRendererColor(Renderer r, bool restore) { //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)r == (Object)null || (Object)(object)r.material == (Object)null) { return; } Material material = r.material; string text = (material.HasProperty("_BaseColor") ? "_BaseColor" : (material.HasProperty("_Color") ? "_Color" : null)); if (text != null && originalBaseColors.ContainsKey(r)) { material.SetColor(text, restore ? originalBaseColors[r] : Color.black); } if (!material.HasProperty("_EmissionColor")) { return; } if (restore) { if (originalEmissionColors.ContainsKey(r)) { material.SetColor("_EmissionColor", originalEmissionColors[r]); } if (originalEmissionKeywords.ContainsKey(r) && originalEmissionKeywords[r]) { material.EnableKeyword("_EMISSION"); } else { material.DisableKeyword("_EMISSION"); } } else { material.SetColor("_EmissionColor", Color.black); material.DisableKeyword("_EMISSION"); } } [IteratorStateMachine(typeof(d__23))] private static IEnumerator FlickerRoutine(List lights) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__23(0) { lights = lights }; } private static void TriggerDeath(object instance) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) Component val = (Component)((instance is Component) ? instance : null); if (val != null) { OnPlayerDeath(val.transform.position); } } public static void OnActorEliminatedPostfix(object __instance) { TriggerDeath(__instance); } public static void OnGenericDeathPostfix(object __instance) { TriggerDeath(__instance); } } }