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 <DelayedCacheMapLights>d__17 : IEnumerator<object>, IEnumerator, IDisposable
{
private int <>1__state;
private object <>2__current;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <DelayedCacheMapLights>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 <FlickerRoutine>d__23 : IEnumerator<object>, IEnumerator, IDisposable
{
private int <>1__state;
private object <>2__current;
public List<Light> lights;
private float <duration>5__2;
private float <elapsed>5__3;
private Dictionary<Light, bool> <originalStates>5__4;
private float <originalAmbientIntensity>5__5;
private Color <originalAmbientLight>5__6;
private float <originalReflectionIntensity>5__7;
private float <waitTime>5__8;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <FlickerRoutine>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();
}
}
<originalStates>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;
<duration>5__2 = 1.5f;
<elapsed>5__3 = 0f;
<originalStates>5__4 = lights.ToDictionary((Light l) => l, (Light l) => ((Behaviour)l).enabled);
<originalAmbientIntensity>5__5 = RenderSettings.ambientIntensity;
<originalAmbientLight>5__6 = RenderSettings.ambientLight;
<originalReflectionIntensity>5__7 = RenderSettings.reflectionIntensity;
<>1__state = -3;
break;
case 1:
<>1__state = -3;
<elapsed>5__3 += <waitTime>5__8;
break;
}
if (<elapsed>5__3 < <duration>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 = <originalStates>5__4[light] && flag;
}
}
foreach (Renderer lightRenderer in lightRenderers)
{
SetRendererColor(lightRenderer, flag);
}
RenderSettings.ambientIntensity = <originalAmbientIntensity>5__5 * num;
RenderSettings.ambientLight = <originalAmbientLight>5__6 * num;
RenderSettings.reflectionIntensity = <originalReflectionIntensity>5__7 * num;
<waitTime>5__8 = Random.Range(0.04f, 0.12f);
<>2__current = (object)new WaitForSeconds(<waitTime>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 && <originalStates>5__4.ContainsKey(light))
{
((Behaviour)light).enabled = <originalStates>5__4[light];
}
}
foreach (Renderer lightRenderer in lightRenderers)
{
SetRendererColor(lightRenderer, restore: true);
}
RenderSettings.ambientIntensity = <originalAmbientIntensity>5__5;
RenderSettings.ambientLight = <originalAmbientLight>5__6;
RenderSettings.reflectionIntensity = <originalReflectionIntensity>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<Light> cachedMapLights = new List<Light>();
private static List<Renderer> lightRenderers = new List<Renderer>();
private static Dictionary<Renderer, Color> originalEmissionColors = new Dictionary<Renderer, Color>();
private static Dictionary<Renderer, bool> originalEmissionKeywords = new Dictionary<Renderer, bool>();
private static Dictionary<Renderer, Color> originalBaseColors = new Dictionary<Renderer, Color>();
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<string, string> dictionary = new Dictionary<string, string>
{
{ "Actor", "Eliminate" },
{ "HealthTracker", "Kill" },
{ "ActorDeathAudio", "OnBeastDeath" },
{ "BreakJointsOnDeath", "OnDeath" }
};
foreach (Assembly item in from a in AppDomain.CurrentDomain.GetAssemblies()
where ((ReadOnlySpan<string>)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<float>.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(<DelayedCacheMapLights>d__17))]
private static IEnumerator DelayedCacheMapLights()
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <DelayedCacheMapLights>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<Light>)Resources.FindObjectsOfTypeAll<Light>()).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<Renderer>)Resources.FindObjectsOfTypeAll<Renderer>()).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<AudioSource>();
activeSource.clip = deathClip;
AudioMixerGroup val = ((IEnumerable<AudioMixerGroup>)Resources.FindObjectsOfTypeAll<AudioMixerGroup>()).FirstOrDefault((Func<AudioMixerGroup, bool>)((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(<FlickerRoutine>d__23))]
private static IEnumerator FlickerRoutine(List<Light> lights)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <FlickerRoutine>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);
}
}
}