Decompiled source of UltraLoneliness v1.0.2

Ultraloneliness.dll

Decompiled 16 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text.RegularExpressions;
using BepInEx;
using HarmonyLib;
using TMPro;
using ULTRAKILL.Cheats;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("0.0.0.0")]
namespace UltraLoneliness;

[BepInPlugin("com.ultraloneliness.mod", "Ultra Loneliness", "1.0.0")]
public class Plugin : BaseUnityPlugin
{
	private static Plugin instance;

	private const float DoorMessageRange = 18f;

	private const float DieMessageCooldown = 8f;

	private static float nextDieMessage;

	private static float nextSecretLevelMessage;

	private static float nextNoCheatingMessage;

	private static bool modActivatingCheats;

	internal static float DieMessageVisibleUntil;

	private static readonly Dictionary<FinalDoor, bool> entranceCache = new Dictionary<FinalDoor, bool>();

	private static bool finishing;

	private static readonly FieldInfo MusicField = typeof(ScreenZone).GetField("music", BindingFlags.Instance | BindingFlags.NonPublic);

	private static readonly FieldInfo JingleField = typeof(ScreenZone).GetField("jingleMusic", BindingFlags.Instance | BindingFlags.NonPublic);

	private NewMovement player;

	private GunControl gunControl;

	private FistControl fistControl;

	private AudioMixerController audioController;

	private float nextLookup;

	private float nextScan;

	private float nextDoorCheck;

	internal static bool DiedOnce;

	private static string lastScene;

	private static bool sceneEventSeen;

	private string lastPolledScene;

	private readonly HashSet<ScreenZone> handledZones = new HashSet<ScreenZone>();

	private readonly List<ShopZone> shopZones = new List<ShopZone>();

	private readonly List<FinalDoor> exitDoors = new List<FinalDoor>();

	private readonly HashSet<FinalDoor> handledDoors = new HashSet<FinalDoor>();

	private int scanCount;

	private readonly Dictionary<FinalDoor, float> lastOpenAttempt = new Dictionary<FinalDoor, float>();

	private bool menuSeen;

	private float menuSeenAt;

	private float nextMenuCheck;

	private float nextBackgroundProbe;

	private float nextMenuChecksPurge;

	private float nextShopCheck;

	private int lookupMisses;

	private readonly HashSet<int> menuChecked = new HashSet<int>();

	private readonly HashSet<Behaviour> menuHiddenSet = new HashSet<Behaviour>();

	private static readonly MainMenuBG[] NoBackgrounds = (MainMenuBG[])(object)new MainMenuBG[0];

	private static readonly List<Scene> MenuSceneBuffer = new List<Scene>();

	private const bool HideV1Art = false;

	private readonly List<Behaviour> menuHidden = new List<Behaviour>();

	private static readonly string[] RemovedChapterEntries = new string[2] { "The Cyber Grind", "Sandbox" };

	private readonly HashSet<int> removedEntries = new HashSet<int>();

	private static readonly string[] MenuStatusPhrases = new string[8] { "EARLY_ACCESS READY", "SYSTEM V1 INITIALIZED", "SYSTEM V1 INITALIZED", "INIT SOCIALS", "OR STAY UP TO DATE", "MERRY CHRISTMAS", "HAPPY HALLOWEEN", "HAPPY EASTER" };

	private static readonly Regex RichTextTag = new Regex("<[^>]+>");

	private static readonly Dictionary<string, bool> statusTextCache = new Dictionary<string, bool>();

	internal static bool ModActivatingCheats => modActivatingCheats;

	internal static bool IsFinishing => finishing;

	internal static void ShowDieMessage()
	{
		if (Time.unscaledTime < nextDieMessage)
		{
			return;
		}
		try
		{
			HudMessageReceiver val = MonoSingleton<HudMessageReceiver>.Instance;
			if ((Object)(object)val == (Object)null)
			{
				nextDieMessage = Time.unscaledTime + 2f;
				return;
			}
			nextDieMessage = Time.unscaledTime + 8f;
			DieMessageVisibleUntil = Time.unscaledTime + 6f;
			val.SendHudMessage("<color=red>D I E</color>", "", "", 0, false, false, true);
		}
		catch (Exception)
		{
			nextDieMessage = Time.unscaledTime + 5f;
		}
	}

	internal static void OnSecretLevelBlocked()
	{
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: 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_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		NewMovement val = MonoSingleton<NewMovement>.Instance;
		if ((Object)(object)val != (Object)null && !val.dead && (Object)(object)val.rb != (Object)null)
		{
			Vector3 val2 = -((Component)val).transform.forward;
			val.rb.velocity = val2 * 12f + Vector3.up * 2f;
		}
		if (Time.unscaledTime < nextSecretLevelMessage)
		{
			return;
		}
		try
		{
			HudMessageReceiver val3 = MonoSingleton<HudMessageReceiver>.Instance;
			if ((Object)(object)val3 == (Object)null)
			{
				nextSecretLevelMessage = Time.unscaledTime + 2f;
				return;
			}
			nextSecretLevelMessage = Time.unscaledTime + 8f;
			DieMessageVisibleUntil = Time.unscaledTime + 6f;
			val3.SendHudMessage("<color=red>NOT THAT EASY</color>", "", "", 0, false, false, true);
		}
		catch (Exception)
		{
			nextSecretLevelMessage = Time.unscaledTime + 5f;
		}
	}

	internal static bool IsSecretLevelName(string sceneName)
	{
		if (string.IsNullOrEmpty(sceneName))
		{
			return false;
		}
		if (!(sceneName == "Level 0-E") && !(sceneName == "Level 1-E"))
		{
			return sceneName.StartsWith("Level P-");
		}
		return true;
	}

	internal static void ShowNoCheatingMessage()
	{
		if (Time.unscaledTime < nextNoCheatingMessage)
		{
			return;
		}
		try
		{
			HudMessageReceiver val = MonoSingleton<HudMessageReceiver>.Instance;
			if ((Object)(object)val == (Object)null)
			{
				nextNoCheatingMessage = Time.unscaledTime + 2f;
				return;
			}
			nextNoCheatingMessage = Time.unscaledTime + 8f;
			DieMessageVisibleUntil = Time.unscaledTime + 6f;
			val.SendHudMessage("<color=red>NO CHEATING</color>", "", "", 0, false, false, true);
		}
		catch (Exception)
		{
			nextNoCheatingMessage = Time.unscaledTime + 5f;
		}
	}

	internal static void OnLockedDoorTouched(FinalDoor door)
	{
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)door == (Object)null))
		{
			NewMovement val = MonoSingleton<NewMovement>.Instance;
			if (!((Object)(object)val == (Object)null) && !val.dead && !(Vector3.Distance(((Component)val).transform.position, ((Component)door).transform.position) > 54f))
			{
				ShowDieMessage();
			}
		}
	}

	internal static void ClearCaches()
	{
		entranceCache.Clear();
	}

	internal static bool IsEntrance(FinalDoor door)
	{
		if ((Object)(object)door == (Object)null)
		{
			return false;
		}
		if (entranceCache.TryGetValue(door, out var value))
		{
			return value;
		}
		bool flag = ComputeIsEntrance(door);
		entranceCache[door] = flag;
		return flag;
	}

	private static bool ComputeIsEntrance(FinalDoor door)
	{
		Transform val = ((Component)door).transform;
		while ((Object)(object)val != (Object)null)
		{
			if (((Object)val).name == "FirstRoom")
			{
				return true;
			}
			val = val.parent;
		}
		if ((Object)(object)((Component)door).GetComponentInParent<FirstRoomPrefab>() != (Object)null)
		{
			return true;
		}
		FirstRoomPrefab[] array = Object.FindObjectsOfType<FirstRoomPrefab>(true);
		for (int i = 0; i < array.Length; i++)
		{
			if ((Object)(object)array[i].finalDoor == (Object)(object)door)
			{
				return true;
			}
		}
		return false;
	}

	internal static bool IsNormalExitLevel()
	{
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		string text = SceneHelper.CurrentScene;
		if (string.IsNullOrEmpty(text))
		{
			Scene activeScene = SceneManager.GetActiveScene();
			text = ((Scene)(ref activeScene)).name;
		}
		if (!(text == "Level 1-1"))
		{
			return text == "Level 8-4";
		}
		return true;
	}

	internal static void BeatLevel(NewMovement nm)
	{
		if (!finishing)
		{
			finishing = true;
			if ((Object)(object)instance == (Object)null)
			{
				finishing = false;
			}
			else
			{
				((MonoBehaviour)instance).StartCoroutine(instance.FinishLevel(nm));
			}
		}
	}

	private IEnumerator FinishLevel(NewMovement nm)
	{
		bool flag = false;
		try
		{
			SceneHelper.SpawnFinalPitAndFinish();
			if ((Object)(object)nm != (Object)null && (Object)(object)nm.rb != (Object)null)
			{
				nm.rb.velocity = Vector3.zero;
			}
			Physics.SyncTransforms();
			flag = true;
		}
		catch (Exception)
		{
			finishing = false;
		}
		if (!flag)
		{
			ScreenFade.FromBlack();
			yield break;
		}
		FinalRoom finalRoom = null;
		for (int i = 0; i < 20; i++)
		{
			yield return null;
			finalRoom = FindFinalRoom(allowInactive: false);
			if ((Object)(object)finalRoom != (Object)null)
			{
				break;
			}
		}
		if ((Object)(object)finalRoom == (Object)null)
		{
			finalRoom = FindFinalRoom(allowInactive: true);
		}
		if ((Object)(object)finalRoom == (Object)null)
		{
			finishing = false;
			ScreenFade.FromBlack();
			yield break;
		}
		try
		{
			PrepareFinalArea(finalRoom, everything: false);
			if (!((Component)finalRoom).gameObject.activeSelf)
			{
				((Component)finalRoom).gameObject.SetActive(true);
			}
			if ((Object)(object)finalRoom.doorOpener != (Object)null)
			{
				finalRoom.doorOpener.SetActive(true);
			}
			Physics.SyncTransforms();
			if ((Object)(object)nm != (Object)null && (Object)(object)finalRoom.dropPoint != (Object)null)
			{
				((Component)nm).transform.position = finalRoom.dropPoint.position;
				if ((Object)(object)nm.rb != (Object)null)
				{
					nm.rb.velocity = Vector3.zero;
				}
				Physics.SyncTransforms();
			}
			else
			{
				_ = (Object)(object)finalRoom.dropPoint == (Object)null;
			}
		}
		catch (Exception)
		{
			finishing = false;
		}
		float holdUntil = Time.unscaledTime + 3f;
		bool fallbackUsed = false;
		while (Time.unscaledTime < holdUntil && !((Object)(object)finalRoom == (Object)null) && !((Object)(object)finalRoom.dropPoint == (Object)null) && !HasGroundBelow(finalRoom.dropPoint.position, nm))
		{
			if (!fallbackUsed)
			{
				fallbackUsed = true;
				PrepareFinalArea(finalRoom, everything: true);
			}
			if ((Object)(object)nm != (Object)null)
			{
				((Component)nm).transform.position = finalRoom.dropPoint.position;
				if ((Object)(object)nm.rb != (Object)null)
				{
					nm.rb.velocity = Vector3.zero;
				}
			}
			Physics.SyncTransforms();
			yield return null;
		}
		FixNextLevel(finalRoom);
		yield return null;
		ForceOpenFinalRoom(finalRoom, retrigger: true);
		yield return (object)new WaitForSeconds(1.5f);
		ForceOpenFinalRoom(finalRoom, retrigger: false);
	}

	private static bool HasGroundBelow(Vector3 position, NewMovement nm)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//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_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		RaycastHit[] array = Physics.RaycastAll(position + Vector3.up * 0.5f, Vector3.down, 200f, -5, (QueryTriggerInteraction)2);
		for (int i = 0; i < array.Length; i++)
		{
			RaycastHit val = array[i];
			if (!((Object)(object)((RaycastHit)(ref val)).collider == (Object)null) && (!((Object)(object)nm != (Object)null) || !((Component)((RaycastHit)(ref val)).collider).transform.IsChildOf(((Component)nm).transform)) && (!((RaycastHit)(ref val)).collider.isTrigger || !((Object)(object)((Component)((RaycastHit)(ref val)).collider).GetComponentInParent<FinalPit>() == (Object)null)))
			{
				return true;
			}
		}
		return false;
	}

	private static void Activate(GameObject obj)
	{
		if ((Object)(object)obj == (Object)null || obj.activeInHierarchy)
		{
			return;
		}
		Transform val = obj.transform;
		while ((Object)(object)val != (Object)null)
		{
			if (!((Component)val).gameObject.activeSelf)
			{
				((Component)val).gameObject.SetActive(true);
			}
			val = val.parent;
		}
	}

	private static void PrepareFinalArea(FinalRoom finalRoom, bool everything)
	{
		try
		{
			if ((Object)(object)finalRoom != (Object)null)
			{
				Activate(((Component)finalRoom).gameObject);
			}
			Door[] array = Object.FindObjectsOfType<Door>(true);
			foreach (Door val in array)
			{
				if ((Object)(object)val == (Object)null || val.activatedRooms == null)
				{
					continue;
				}
				GameObject[] activatedRooms = val.activatedRooms;
				foreach (GameObject val2 in activatedRooms)
				{
					if (!((Object)(object)val2 == (Object)null))
					{
						bool flag = (Object)(object)finalRoom != (Object)null && (((Component)finalRoom).transform.IsChildOf(val2.transform) || ((Object)(object)finalRoom.dropPoint != (Object)null && finalRoom.dropPoint.IsChildOf(val2.transform)));
						if (everything || flag)
						{
							Activate(val2);
						}
					}
				}
			}
			FinalDoor[] array2 = Object.FindObjectsOfType<FinalDoor>(true);
			foreach (FinalDoor val3 in array2)
			{
				if ((Object)(object)val3 == (Object)null || IsEntrance(val3) || val3.doors == null)
				{
					continue;
				}
				array = val3.doors;
				foreach (Door val4 in array)
				{
					if (!((Object)(object)val4 == (Object)null) && val4.activatedRooms != null)
					{
						GameObject[] activatedRooms = val4.activatedRooms;
						for (int k = 0; k < activatedRooms.Length; k++)
						{
							Activate(activatedRooms[k]);
						}
					}
				}
			}
			if (everything)
			{
				CheckPoint[] array3 = Object.FindObjectsOfType<CheckPoint>(true);
				foreach (CheckPoint val5 in array3)
				{
					if ((Object)(object)val5 == (Object)null)
					{
						continue;
					}
					if (val5.rooms != null)
					{
						GameObject[] activatedRooms = val5.rooms;
						for (int j = 0; j < activatedRooms.Length; j++)
						{
							Activate(activatedRooms[j]);
						}
					}
					if (val5.newRooms != null)
					{
						foreach (GameObject newRoom in val5.newRooms)
						{
							Activate(newRoom);
						}
					}
					if (val5.defaultRooms == null)
					{
						continue;
					}
					foreach (GameObject defaultRoom in val5.defaultRooms)
					{
						Activate(defaultRoom);
					}
				}
			}
			Physics.SyncTransforms();
		}
		catch (Exception)
		{
		}
	}

	private static int FindLevelNumber(string sceneName)
	{
		if (string.IsNullOrEmpty(sceneName))
		{
			return -1;
		}
		for (int i = 1; i <= 60; i++)
		{
			string sceneName2 = GetMissionName.GetSceneName(i);
			if (!string.IsNullOrEmpty(sceneName2) && sceneName2 == sceneName)
			{
				return i;
			}
		}
		return -1;
	}

	internal static string NextLevelName()
	{
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		if (SceneHelper.IsPlayingCustom)
		{
			return null;
		}
		StatsManager val = MonoSingleton<StatsManager>.Instance;
		int num = FindLevelNumber(SceneHelper.CurrentScene);
		if (num < 1)
		{
			Scene activeScene = SceneManager.GetActiveScene();
			num = FindLevelNumber(((Scene)(ref activeScene)).name);
		}
		if (num < 1 && (Object)(object)val != (Object)null)
		{
			num = val.levelNumber;
		}
		if (num < 1)
		{
			return null;
		}
		string sceneName = GetMissionName.GetSceneName(num + 1);
		if (!IsReleased(sceneName))
		{
			return "Main Menu";
		}
		return sceneName;
	}

	private static bool IsReleased(string sceneName)
	{
		if (string.IsNullOrEmpty(sceneName))
		{
			return false;
		}
		if (sceneName.StartsWith("Level 9-"))
		{
			return false;
		}
		if (sceneName.EndsWith("-E"))
		{
			if (!(sceneName == "Level 0-E"))
			{
				return sceneName == "Level 1-E";
			}
			return true;
		}
		if (sceneName.StartsWith("Level P-"))
		{
			if (!(sceneName == "Level P-1"))
			{
				return sceneName == "Level P-2";
			}
			return true;
		}
		return true;
	}

	private static void FixNextLevel(FinalRoom finalRoom)
	{
		try
		{
			string text = NextLevelName();
			if (text == null)
			{
				return;
			}
			StatsManager val = MonoSingleton<StatsManager>.Instance;
			FinalPit[] array = Resources.FindObjectsOfTypeAll<FinalPit>();
			foreach (FinalPit val2 in array)
			{
				if (!((Object)(object)val2 == (Object)null))
				{
					val2.targetLevelName = text;
				}
			}
			if ((Object)(object)val != (Object)null && (Object)(object)val.fr != (Object)null)
			{
				val.fr.targetLevelName = text;
			}
		}
		catch (Exception)
		{
		}
	}

	private static void ForceOpenFinalRoom(FinalRoom finalRoom, bool retrigger)
	{
		try
		{
			if ((Object)(object)finalRoom == (Object)null)
			{
				return;
			}
			if (retrigger && (Object)(object)finalRoom.doorOpener != (Object)null)
			{
				finalRoom.doorOpener.SetActive(false);
				finalRoom.doorOpener.SetActive(true);
			}
			HashSet<FinalDoor> hashSet = new HashSet<FinalDoor>(((Component)finalRoom).GetComponentsInChildren<FinalDoor>(true));
			if ((Object)(object)finalRoom.doorOpener != (Object)null)
			{
				FinalDoor componentInParent = finalRoom.doorOpener.GetComponentInParent<FinalDoor>();
				if ((Object)(object)componentInParent != (Object)null)
				{
					hashSet.Add(componentInParent);
				}
			}
			foreach (FinalDoor item in hashSet)
			{
				if ((Object)(object)item == (Object)null)
				{
					continue;
				}
				if (!((Component)item).gameObject.activeSelf)
				{
					((Component)item).gameObject.SetActive(true);
				}
				((MonoBehaviour)item).CancelInvoke("OpenDoors");
				item.opened = false;
				item.aboutToOpen = false;
				if (item.doors != null)
				{
					Door[] doors = item.doors;
					foreach (Door val in doors)
					{
						if (!((Object)(object)val == (Object)null))
						{
							if (val.locked)
							{
								val.Unlock();
							}
							val.open = false;
						}
					}
				}
				item.OpenDoors();
			}
		}
		catch (Exception)
		{
		}
	}

	private static FinalRoom FindFinalRoom(bool allowInactive)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		Scene activeScene = SceneManager.GetActiveScene();
		FinalRoom val = null;
		FinalRoom[] array = Resources.FindObjectsOfTypeAll<FinalRoom>();
		foreach (FinalRoom val2 in array)
		{
			if (!((Object)(object)val2 == (Object)null) && !(((Component)val2).gameObject.scene != activeScene))
			{
				if (((Component)val2).gameObject.activeInHierarchy)
				{
					return val2;
				}
				if ((Object)(object)val == (Object)null)
				{
					val = val2;
				}
			}
		}
		if (!allowInactive)
		{
			return null;
		}
		return val;
	}

	private static void PatchSafe(Harmony harmony, Type patchClass)
	{
		try
		{
			harmony.PatchAll(patchClass);
		}
		catch (Exception)
		{
		}
	}

	private void Awake()
	{
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Expected O, but got Unknown
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Expected O, but got Unknown
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_005e: Expected O, but got Unknown
		//IL_005e: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: Expected O, but got Unknown
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Expected O, but got Unknown
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_008e: Expected O, but got Unknown
		//IL_008e: Unknown result type (might be due to invalid IL or missing references)
		//IL_009e: Expected O, but got Unknown
		//IL_009e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ae: Expected O, but got Unknown
		//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: Expected O, but got Unknown
		//IL_00be: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ce: Expected O, but got Unknown
		//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_00de: Expected O, but got Unknown
		//IL_00de: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ee: Expected O, but got Unknown
		//IL_00fd: Expected O, but got Unknown
		instance = this;
		((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
		SceneManager.sceneLoaded += OnSceneLoaded;
		Harmony val = new Harmony("com.ultraloneliness.mod");
		PatchSafe(val, typeof(ExitDoorPatches));
		PatchSafe(val, typeof(HurtPatch));
		PatchSafe(val, typeof(ExplosionPatch));
		PatchSafe(val, typeof(CannonballBreakPatch));
		PatchSafe(val, typeof(CannonballExplodePatch));
		PatchSafe(val, typeof(NapalmFirePatch));
		PatchSafe(val, typeof(NextLevelPatches));
		PatchSafe(val, typeof(SecretLevelPatches));
		PatchSafe(val, typeof(CheatActivationPatches));
		PatchSafe(val, typeof(HideUiTextboxPatch));
		PatchSafe(val, typeof(DoorOpenPatch));
		PatchSafe(val, typeof(DoorUnlockPatch));
		PatchSafe(val, typeof(KnuckleblasterDoorPatch));
		ViewmodelShake.Hook();
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Ultra Loneliness loaded");
	}

	private void OnDestroy()
	{
		if ((Object)(object)instance == (Object)(object)this)
		{
			instance = null;
		}
		ViewmodelShake.Unhook();
		ScreenFade.Cleanup();
		SceneManager.sceneLoaded -= OnSceneLoaded;
	}

	private static void MuteSource(ScreenZone zone, FieldInfo field)
	{
		if (!(field == null))
		{
			object? value = field.GetValue(zone);
			AudioSource val = (AudioSource)((value is AudioSource) ? value : null);
			if ((Object)(object)val != (Object)null && !val.mute)
			{
				val.mute = true;
				val.Stop();
			}
		}
	}

	private static bool IsPhysicallyOpen(FinalDoor door)
	{
		if (door.doors == null || door.doors.Length == 0)
		{
			return door.opened;
		}
		Door[] doors = door.doors;
		foreach (Door val in doors)
		{
			if ((Object)(object)val != (Object)null && !val.open)
			{
				return false;
			}
		}
		return true;
	}

	private void PollSceneChange()
	{
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		if (!sceneEventSeen)
		{
			Scene activeScene = SceneManager.GetActiveScene();
			string name = ((Scene)(ref activeScene)).name;
			if (!(name == lastPolledScene))
			{
				lastPolledScene = name;
				ResetForScene(name);
			}
		}
	}

	private void Update()
	{
		//IL_0360: Unknown result type (might be due to invalid IL or missing references)
		//IL_036c: Unknown result type (might be due to invalid IL or missing references)
		PollSceneChange();
		ScreenFade.Tick();
		ViewmodelShake.Tick(player, gunControl, fistControl);
		if ((Object)(object)player != (Object)null && player.dead)
		{
			DiedOnce = true;
		}
		if (Time.unscaledTime >= nextMenuCheck)
		{
			nextMenuCheck = Time.unscaledTime + ((menuSeen && Time.unscaledTime - menuSeenAt > 10f) ? 4f : 1f);
			StripMainMenu();
		}
		if (Time.unscaledTime >= nextLookup)
		{
			if ((Object)(object)player == (Object)null)
			{
				player = Object.FindObjectOfType<NewMovement>();
			}
			if ((Object)(object)player != (Object)null)
			{
				if ((Object)(object)gunControl == (Object)null)
				{
					gunControl = Object.FindObjectOfType<GunControl>();
				}
				if ((Object)(object)fistControl == (Object)null)
				{
					fistControl = Object.FindObjectOfType<FistControl>();
				}
			}
			if ((Object)(object)audioController == (Object)null)
			{
				audioController = Object.FindObjectOfType<AudioMixerController>();
			}
			bool flag = (Object)(object)player == (Object)null || (Object)(object)gunControl == (Object)null || (Object)(object)fistControl == (Object)null || (Object)(object)audioController == (Object)null;
			lookupMisses = (flag ? Mathf.Min(lookupMisses + 1, 3) : 0);
			nextLookup = Time.unscaledTime + (flag ? (0.5f * (float)(1 << lookupMisses)) : 0.5f);
		}
		if (Time.unscaledTime >= nextShopCheck)
		{
			nextShopCheck = Time.unscaledTime + 0.5f;
			foreach (ShopZone shopZone in shopZones)
			{
				if ((Object)(object)shopZone != (Object)null && !shopZone.forcedOff)
				{
					shopZone.ForceOff();
				}
			}
		}
		if (Time.unscaledTime >= nextScan)
		{
			nextScan = Time.unscaledTime + ((scanCount < 3) ? 2f : 30f);
			scanCount++;
			ScanScene();
		}
		if (!(Time.unscaledTime >= nextDoorCheck) || finishing)
		{
			return;
		}
		nextDoorCheck = Time.unscaledTime + 0.5f;
		if (IsNormalExitLevel())
		{
			return;
		}
		for (int num = exitDoors.Count - 1; num >= 0; num--)
		{
			FinalDoor val = exitDoors[num];
			float value;
			if ((Object)(object)val == (Object)null)
			{
				exitDoors.RemoveAt(num);
			}
			else if (!DiedOnce)
			{
				((MonoBehaviour)val).CancelInvoke("OpenDoors");
				if (val.opened || val.aboutToOpen)
				{
					val.Close();
				}
				val.opened = false;
				val.aboutToOpen = false;
				if (val.doors != null)
				{
					Door[] doors = val.doors;
					foreach (Door val2 in doors)
					{
						if ((Object)(object)val2 != (Object)null && val2.open)
						{
							val2.open = false;
							try
							{
								((Component)val2).SendMessage("Close", (SendMessageOptions)1);
							}
							catch
							{
							}
						}
					}
				}
				if ((Object)(object)player != (Object)null && !player.dead && Vector3.Distance(((Component)player).transform.position, ((Component)val).transform.position) <= 18f)
				{
					ShowDieMessage();
				}
			}
			else if ((Object)(object)player != (Object)null && !player.dead && !IsPhysicallyOpen(val) && (!lastOpenAttempt.TryGetValue(val, out value) || !(Time.unscaledTime - value < 3f)))
			{
				lastOpenAttempt[val] = Time.unscaledTime;
				((MonoBehaviour)val).CancelInvoke("OpenDoors");
				val.opened = false;
				val.aboutToOpen = false;
				val.Open();
			}
		}
	}

	private void ScanScene()
	{
		FinalDoor[] array = Object.FindObjectsOfType<FinalDoor>(true);
		foreach (FinalDoor val in array)
		{
			if (handledDoors.Add(val) && !IsEntrance(val))
			{
				exitDoors.Add(val);
			}
		}
		ScreenZone[] array2 = Object.FindObjectsOfType<ScreenZone>(true);
		foreach (ScreenZone val2 in array2)
		{
			if (!handledZones.Add(val2))
			{
				continue;
			}
			MuteSource(val2, MusicField);
			MuteSource(val2, JingleField);
			ShopZone val3 = (ShopZone)(object)((val2 is ShopZone) ? val2 : null);
			if ((Object)(object)val3 != (Object)null)
			{
				shopZones.Add(val3);
				if (!val3.forcedOff)
				{
					val3.ForceOff();
				}
			}
		}
	}

	private void LateUpdate()
	{
		for (int i = 0; i < menuHidden.Count; i++)
		{
			Behaviour val = menuHidden[i];
			if ((Object)(object)val != (Object)null && val.enabled)
			{
				val.enabled = false;
			}
		}
		if ((Object)(object)audioController != (Object)null && (Object)(object)audioController.musicSound != (Object)null)
		{
			audioController.musicSound.SetFloat("allVolume", -80f);
		}
	}

	private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
	{
		sceneEventSeen = true;
		ResetForScene(((Scene)(ref scene)).name);
	}

	private void ResetForScene(string sceneName)
	{
		if (sceneName != lastScene)
		{
			DiedOnce = false;
			lastScene = sceneName;
		}
		player = null;
		gunControl = null;
		fistControl = null;
		audioController = null;
		ViewmodelShake.ResetForScene();
		ScreenFade.FromBlack();
		nextDieMessage = 0f;
		DieMessageVisibleUntil = 0f;
		nextLookup = 0f;
		nextScan = 0f;
		nextDoorCheck = 0f;
		handledZones.Clear();
		shopZones.Clear();
		menuHidden.Clear();
		menuHiddenSet.Clear();
		menuChecked.Clear();
		removedEntries.Clear();
		exitDoors.Clear();
		handledDoors.Clear();
		lastOpenAttempt.Clear();
		PunchDoors.Reset();
		ClearCaches();
		scanCount = 0;
		finishing = false;
		((MonoBehaviour)this).StartCoroutine(EnableWhenReady());
		((MonoBehaviour)this).StartCoroutine(RemoveOrbs());
		menuSeen = false;
		menuSeenAt = 0f;
		nextMenuCheck = 0f;
		nextBackgroundProbe = 0f;
		nextMenuChecksPurge = 0f;
		nextShopCheck = 0f;
		lookupMisses = 0;
	}

	private static List<Scene> FindMenuScenes()
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		List<Scene> menuSceneBuffer = MenuSceneBuffer;
		menuSceneBuffer.Clear();
		for (int i = 0; i < SceneManager.sceneCount; i++)
		{
			Scene sceneAt = SceneManager.GetSceneAt(i);
			if (((Scene)(ref sceneAt)).isLoaded && ((Scene)(ref sceneAt)).name == "Main Menu")
			{
				menuSceneBuffer.Add(sceneAt);
			}
		}
		if (menuSceneBuffer.Count == 0 && SceneHelper.CurrentScene == "Main Menu")
		{
			menuSceneBuffer.Add(SceneManager.GetActiveScene());
		}
		return menuSceneBuffer;
	}

	private void StripMainMenu()
	{
		try
		{
			List<Scene> list = FindMenuScenes();
			MainMenuBG[] noBackgrounds = NoBackgrounds;
			if (list.Count > 0)
			{
				noBackgrounds = Object.FindObjectsOfType<MainMenuBG>(true);
			}
			else
			{
				if (Time.unscaledTime < nextBackgroundProbe)
				{
					return;
				}
				nextBackgroundProbe = Time.unscaledTime + 15f;
				noBackgrounds = Object.FindObjectsOfType<MainMenuBG>(true);
				if (noBackgrounds.Length == 0)
				{
					return;
				}
			}
			if (!menuSeen)
			{
				menuSeen = true;
				menuSeenAt = Time.unscaledTime;
			}
			MainMenuBG[] array = noBackgrounds;
			foreach (MainMenuBG val in array)
			{
				if (!((Object)(object)val == (Object)null))
				{
					RawImage component = ((Component)val).GetComponent<RawImage>();
					if ((Object)(object)component != (Object)null)
					{
						((Behaviour)component).enabled = false;
					}
					((Behaviour)val).enabled = false;
				}
			}
			menuHidden.RemoveAll((Behaviour b) => (Object)(object)b == (Object)null);
			menuHiddenSet.RemoveWhere((Behaviour b) => (Object)(object)b == (Object)null);
			if (Time.unscaledTime >= nextMenuChecksPurge)
			{
				nextMenuChecksPurge = Time.unscaledTime + 15f;
				menuChecked.Clear();
			}
			Graphic[] array2 = Object.FindObjectsOfType<Graphic>(true);
			foreach (Graphic val2 in array2)
			{
				if ((Object)(object)val2 == (Object)null || menuHiddenSet.Contains((Behaviour)(object)val2))
				{
					continue;
				}
				Text val3 = (Text)(object)((val2 is Text) ? val2 : null);
				int instanceID = ((Object)val2).GetInstanceID();
				if (!menuChecked.Contains(instanceID))
				{
					if (IsLogo(val2) || IsMenuBackground(val2))
					{
						HideMenuElement((Behaviour)(object)val2);
						continue;
					}
					if ((Object)(object)val3 == (Object)null)
					{
						menuChecked.Add(instanceID);
					}
				}
				if ((Object)(object)val3 != (Object)null && IsMenuStatusText(val3.text))
				{
					HideMenuElement((Behaviour)(object)val3);
				}
			}
			TMP_Text[] array3 = Object.FindObjectsOfType<TMP_Text>(true);
			foreach (TMP_Text val4 in array3)
			{
				if ((Object)(object)val4 != (Object)null && !menuHiddenSet.Contains((Behaviour)(object)val4) && (IsLogoText(val4.text) || IsMenuStatusText(val4.text)))
				{
					HideMenuElement((Behaviour)(object)val4);
				}
			}
			RemoveChapterEntries();
		}
		catch (Exception)
		{
		}
	}

	private void HideMenuElement(Behaviour b)
	{
		if (!((Object)(object)b == (Object)null))
		{
			if (menuHiddenSet.Add(b))
			{
				menuHidden.Add(b);
			}
			b.enabled = false;
		}
	}

	private static bool HasAncestorNamed(Transform t, string name)
	{
		while ((Object)(object)t != (Object)null)
		{
			if (((Object)t).name == name)
			{
				return true;
			}
			t = t.parent;
		}
		return false;
	}

	private static bool IsMenuBackground(Graphic g)
	{
		RawImage val = (RawImage)(object)((g is RawImage) ? g : null);
		if ((Object)(object)val != (Object)null && (Object)(object)val.texture != (Object)null && ((Object)val.texture).name.IndexOf("circuit", StringComparison.OrdinalIgnoreCase) >= 0)
		{
			return true;
		}
		if (HasAncestorNamed(((Component)g).transform, "BackgroundSwapper"))
		{
			return true;
		}
		return false;
	}

	private void RemoveChapterEntries()
	{
		Button[] array = Object.FindObjectsOfType<Button>(true);
		foreach (Button val in array)
		{
			if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).transform.parent == (Object)null) && !(((Object)((Component)val).transform.parent).name != "Chapters") && Array.IndexOf(RemovedChapterEntries, ((Object)((Component)val).gameObject).name) >= 0 && removedEntries.Add(((Object)((Component)val).gameObject).GetInstanceID()))
			{
				LayoutElement val2 = ((Component)val).GetComponent<LayoutElement>();
				if ((Object)(object)val2 == (Object)null)
				{
					val2 = ((Component)val).gameObject.AddComponent<LayoutElement>();
				}
				val2.ignoreLayout = true;
				CanvasGroup val3 = ((Component)val).GetComponent<CanvasGroup>();
				if ((Object)(object)val3 == (Object)null)
				{
					val3 = ((Component)val).gameObject.AddComponent<CanvasGroup>();
				}
				val3.alpha = 0f;
				val3.interactable = false;
				val3.blocksRaycasts = false;
				((Selectable)val).interactable = false;
			}
		}
	}

	private static bool IsMenuStatusText(string text)
	{
		if (string.IsNullOrEmpty(text))
		{
			return false;
		}
		if (statusTextCache.TryGetValue(text, out var value))
		{
			return value;
		}
		string text2 = RichTextTag.Replace(text, "").Trim().ToUpperInvariant();
		bool flag = false;
		if (text2.Length > 0)
		{
			string[] menuStatusPhrases = MenuStatusPhrases;
			foreach (string value2 in menuStatusPhrases)
			{
				if (text2.Contains(value2))
				{
					flag = true;
					break;
				}
			}
		}
		if (statusTextCache.Count > 512)
		{
			statusTextCache.Clear();
		}
		statusTextCache[text] = flag;
		return flag;
	}

	private static bool IsLogoText(string text)
	{
		if (text != null)
		{
			return string.Equals(text.Trim(), "ULTRAKILL", StringComparison.OrdinalIgnoreCase);
		}
		return false;
	}

	private static bool IsLogoName(string name)
	{
		if (string.IsNullOrEmpty(name))
		{
			return false;
		}
		if (name.IndexOf("logo", StringComparison.OrdinalIgnoreCase) < 0)
		{
			return name.IndexOf("ultrakill", StringComparison.OrdinalIgnoreCase) >= 0;
		}
		return true;
	}

	private static bool IsLogo(Graphic g)
	{
		if (IsLogoName(((Object)((Component)g).gameObject).name))
		{
			return true;
		}
		Image val = (Image)(object)((g is Image) ? g : null);
		if ((Object)(object)val != (Object)null && (Object)(object)val.sprite != (Object)null && IsLogoName(((Object)val.sprite).name))
		{
			return true;
		}
		RawImage val2 = (RawImage)(object)((g is RawImage) ? g : null);
		if ((Object)(object)val2 != (Object)null && (Object)(object)val2.texture != (Object)null && IsLogoName(((Object)val2.texture).name))
		{
			return true;
		}
		Text val3 = (Text)(object)((g is Text) ? g : null);
		if ((Object)(object)val3 != (Object)null)
		{
			return IsLogoText(val3.text);
		}
		return false;
	}

	private IEnumerator EnableWhenReady()
	{
		bool spawnsDone = false;
		bool uiDone = false;
		for (int i = 0; i < 20; i++)
		{
			yield return (object)new WaitForSeconds(0.5f);
			CheatsManager val = Object.FindObjectOfType<CheatsManager>();
			if ((Object)(object)val == (Object)null)
			{
				continue;
			}
			if (!spawnsDone)
			{
				DisableEnemySpawns cheatInstance = val.GetCheatInstance<DisableEnemySpawns>();
				if (cheatInstance != null)
				{
					if (!cheatInstance.IsActive)
					{
						modActivatingCheats = true;
						try
						{
							val.SetCheatActive((ICheat)(object)cheatInstance, true, false);
						}
						finally
						{
							modActivatingCheats = false;
						}
					}
					spawnsDone = true;
				}
			}
			if (!uiDone)
			{
				HideUI cheatInstance2 = val.GetCheatInstance<HideUI>();
				if (cheatInstance2 != null)
				{
					if (!cheatInstance2.IsActive)
					{
						modActivatingCheats = true;
						try
						{
							val.SetCheatActive((ICheat)(object)cheatInstance2, true, false);
						}
						finally
						{
							modActivatingCheats = false;
						}
					}
					uiDone = true;
				}
			}
			if (spawnsDone && uiDone)
			{
				break;
			}
		}
	}

	private IEnumerator RemoveOrbs()
	{
		yield return (object)new WaitForSeconds(1f);
		Bonus[] array = Object.FindObjectsOfType<Bonus>(true);
		for (int i = 0; i < array.Length; i++)
		{
			Object.Destroy((Object)(object)((Component)array[i]).gameObject);
		}
	}
}
[HarmonyPatch]
internal static class ExitDoorPatches
{
	[HarmonyPrefix]
	[HarmonyPatch(typeof(FinalDoor), "Open")]
	private static bool BlockOpen(FinalDoor __instance)
	{
		int num;
		if (!Plugin.DiedOnce && !Plugin.IsFinishing && !Plugin.IsNormalExitLevel())
		{
			num = (Plugin.IsEntrance(__instance) ? 1 : 0);
			if (num == 0)
			{
				Plugin.OnLockedDoorTouched(__instance);
			}
		}
		else
		{
			num = 1;
		}
		return (byte)num != 0;
	}

	[HarmonyPrefix]
	[HarmonyPatch(typeof(FinalDoor), "OpenDoors")]
	private static bool BlockOpenDoors(FinalDoor __instance)
	{
		int num;
		if (!Plugin.DiedOnce && !Plugin.IsFinishing && !Plugin.IsNormalExitLevel())
		{
			num = (Plugin.IsEntrance(__instance) ? 1 : 0);
			if (num == 0)
			{
				Plugin.OnLockedDoorTouched(__instance);
			}
		}
		else
		{
			num = 1;
		}
		return (byte)num != 0;
	}
}
[HarmonyPatch(typeof(HideUICheatGroup), "Update")]
internal static class HideUiTextboxPatch
{
	private static void Postfix(HideUICheatGroup __instance)
	{
		if (Time.unscaledTime > Plugin.DieMessageVisibleUntil)
		{
			return;
		}
		HudMessageReceiver instance = MonoSingleton<HudMessageReceiver>.Instance;
		if (!((Object)(object)instance == (Object)null) && ((Component)instance).transform.IsChildOf(((Component)__instance).transform))
		{
			CanvasGroup component = ((Component)__instance).GetComponent<CanvasGroup>();
			if ((Object)(object)component != (Object)null)
			{
				((Behaviour)component).enabled = false;
			}
		}
	}
}
internal static class ScreenFade
{
	private const float FadeInSeconds = 1.2f;

	private const float FadeOutSeconds = 1.5f;

	private static GameObject root;

	private static CanvasGroup group;

	private static float target;

	private static float speed = 1f;

	internal static void ToBlack()
	{
		Ensure();
		target = 1f;
		speed = 5f / 6f;
	}

	internal static void FromBlack()
	{
		target = 0f;
		speed = 2f / 3f;
	}

	internal static void Tick()
	{
		if (!((Object)(object)group == (Object)null))
		{
			group.alpha = Mathf.MoveTowards(group.alpha, target, speed * Time.unscaledDeltaTime);
		}
	}

	internal static void Cleanup()
	{
		if ((Object)(object)root != (Object)null)
		{
			Object.Destroy((Object)(object)root);
		}
		root = null;
		group = null;
		target = 0f;
	}

	private static void Ensure()
	{
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Expected O, but got Unknown
		//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00df: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)root != (Object)null) || !((Object)(object)group != (Object)null))
		{
			root = new GameObject("UltraLoneliness_Fade");
			((Object)root).hideFlags = (HideFlags)61;
			Object.DontDestroyOnLoad((Object)(object)root);
			Canvas obj = root.AddComponent<Canvas>();
			obj.renderMode = (RenderMode)0;
			obj.sortingOrder = 32767;
			group = root.AddComponent<CanvasGroup>();
			group.alpha = 0f;
			group.interactable = false;
			group.blocksRaycasts = false;
			GameObject val = new GameObject("Black", new Type[1] { typeof(RectTransform) });
			val.transform.SetParent(root.transform, false);
			RectTransform component = val.GetComponent<RectTransform>();
			component.anchorMin = Vector2.zero;
			component.anchorMax = Vector2.one;
			component.offsetMin = Vector2.zero;
			component.offsetMax = Vector2.zero;
			RawImage obj2 = val.AddComponent<RawImage>();
			((Graphic)obj2).color = Color.black;
			((Graphic)obj2).raycastTarget = false;
		}
	}
}
internal static class ViewmodelShake
{
	private struct Saved
	{
		public Transform transform;

		public Vector3 position;

		public Quaternion rotation;
	}

	private const float MaxPosition = 0.02f;

	private const float MaxRotation = 1.5f;

	private const float RampSeconds = 420f;

	private const float MinFrequency = 5f;

	private const float MaxFrequency = 15f;

	private const float SmoothTime = 4f;

	private static readonly List<Saved> saved = new List<Saved>();

	private static float intensity;

	private static float intensityVelocity;

	private static float checkpointProgress;

	private static float nextCheckpointScan;

	private static float nextCheckpointRefresh;

	private static readonly List<CheckPoint> checkpointCache = new List<CheckPoint>();

	private static int noiseFrame = -1;

	private static Vector3 noisePosition;

	private static Vector3 noiseRotation;

	private static Transform gunTransform;

	private static Transform fistTransform;

	private static bool hooked;

	internal static void Hook()
	{
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Expected O, but got Unknown
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Expected O, but got Unknown
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Expected O, but got Unknown
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Expected O, but got Unknown
		if (!hooked)
		{
			hooked = true;
			Camera.onPreCull = (CameraCallback)Delegate.Combine((Delegate?)(object)Camera.onPreCull, (Delegate?)new CameraCallback(OnPreCull));
			Camera.onPostRender = (CameraCallback)Delegate.Combine((Delegate?)(object)Camera.onPostRender, (Delegate?)new CameraCallback(OnPostRender));
			RenderPipelineManager.beginCameraRendering += OnBeginSrp;
			RenderPipelineManager.endCameraRendering += OnEndSrp;
		}
	}

	internal static void Unhook()
	{
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Expected O, but got Unknown
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Expected O, but got Unknown
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Expected O, but got Unknown
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Expected O, but got Unknown
		if (hooked)
		{
			hooked = false;
			Camera.onPreCull = (CameraCallback)Delegate.Remove((Delegate?)(object)Camera.onPreCull, (Delegate?)new CameraCallback(OnPreCull));
			Camera.onPostRender = (CameraCallback)Delegate.Remove((Delegate?)(object)Camera.onPostRender, (Delegate?)new CameraCallback(OnPostRender));
			RenderPipelineManager.beginCameraRendering -= OnBeginSrp;
			RenderPipelineManager.endCameraRendering -= OnEndSrp;
			Restore();
		}
	}

	internal static void ResetForScene()
	{
		Restore();
		intensity = 0f;
		intensityVelocity = 0f;
		checkpointProgress = 0f;
		nextCheckpointScan = 0f;
		nextCheckpointRefresh = 0f;
		checkpointCache.Clear();
		noiseFrame = -1;
		gunTransform = null;
		fistTransform = null;
	}

	internal static void Tick(NewMovement nm, GunControl gun, FistControl fist)
	{
		Restore();
		gunTransform = (((Object)(object)gun != (Object)null) ? ((Component)gun).transform : null);
		fistTransform = (((Object)(object)fist != (Object)null) ? ((Component)fist).transform : null);
		float num = 0f;
		if ((Object)(object)nm != (Object)null && !Plugin.IsFinishing)
		{
			StatsManager instance = MonoSingleton<StatsManager>.Instance;
			if ((Object)(object)instance != (Object)null)
			{
				if (Time.unscaledTime >= nextCheckpointScan)
				{
					nextCheckpointScan = Time.unscaledTime + 2f;
					checkpointProgress = ScanCheckpoints();
				}
				float num2 = Mathf.Clamp01(instance.seconds / 420f);
				num = Mathf.Max(checkpointProgress, num2);
			}
		}
		float deltaTime = Time.deltaTime;
		if (deltaTime > 0f)
		{
			intensity = Mathf.SmoothDamp(intensity, num, ref intensityVelocity, 4f, float.PositiveInfinity, deltaTime);
		}
		intensity = Mathf.Clamp01(intensity);
	}

	private static float ScanCheckpoints()
	{
		int num = 0;
		int num2 = 0;
		if (Time.unscaledTime >= nextCheckpointRefresh)
		{
			nextCheckpointRefresh = Time.unscaledTime + 30f;
			checkpointCache.Clear();
			checkpointCache.AddRange(Object.FindObjectsOfType<CheckPoint>(true));
		}
		for (int i = 0; i < checkpointCache.Count; i++)
		{
			CheckPoint val = checkpointCache[i];
			if (!((Object)(object)val == (Object)null))
			{
				num++;
				if (val.activated)
				{
					num2++;
				}
			}
		}
		if (num < 2)
		{
			return 0f;
		}
		return (float)num2 / (float)num;
	}

	private static void OnPreCull(Camera cam)
	{
		Apply();
	}

	private static void OnPostRender(Camera cam)
	{
		Restore();
	}

	private static void OnBeginSrp(ScriptableRenderContext context, Camera cam)
	{
		Apply();
	}

	private static void OnEndSrp(ScriptableRenderContext context, Camera cam)
	{
		Restore();
	}

	private static float Noise(float time, float frequency, float seed)
	{
		return Mathf.Clamp((Mathf.PerlinNoise(time * frequency, seed * 7.13f) - 0.5f) * 2f, -1f, 1f);
	}

	private static void Apply()
	{
		//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_0104: Unknown result type (might be due to invalid IL or missing references)
		//IL_0109: Unknown result type (might be due to invalid IL or missing references)
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
		Restore();
		if (!(intensity <= 0.001f) && (!((Object)(object)gunTransform == (Object)null) || !((Object)(object)fistTransform == (Object)null)))
		{
			if (noiseFrame != Time.frameCount)
			{
				noiseFrame = Time.frameCount;
				float time = Time.time;
				float frequency = Mathf.Lerp(5f, 15f, intensity);
				float num = Mathf.Pow(intensity, 1.3f);
				noisePosition = new Vector3(Noise(time, frequency, 1f), Noise(time, frequency, 2f), Noise(time, frequency, 3f)) * (0.02f * num);
				noiseRotation = new Vector3(Noise(time, frequency, 4f), Noise(time, frequency, 5f), Noise(time, frequency, 6f) * 0.6f) * (1.5f * num);
			}
			ApplyTo(gunTransform, noisePosition, noiseRotation);
			ApplyTo(fistTransform, noisePosition, noiseRotation);
		}
	}

	private static void ApplyTo(Transform target, Vector3 position, Vector3 rotation)
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: 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_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)target == (Object)null))
		{
			Saved item = default(Saved);
			item.transform = target;
			item.position = target.localPosition;
			item.rotation = target.localRotation;
			saved.Add(item);
			target.localPosition = item.position + position;
			target.localRotation = item.rotation * Quaternion.Euler(rotation);
		}
	}

	private static void Restore()
	{
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		for (int i = 0; i < ViewmodelShake.saved.Count; i++)
		{
			Saved saved = ViewmodelShake.saved[i];
			if (!((Object)(object)saved.transform == (Object)null))
			{
				saved.transform.localPosition = saved.position;
				saved.transform.localRotation = saved.rotation;
			}
		}
		ViewmodelShake.saved.Clear();
	}
}
[HarmonyPatch(typeof(NewMovement), "GetHurt", new Type[]
{
	typeof(int),
	typeof(bool),
	typeof(float),
	typeof(bool),
	typeof(bool),
	typeof(float),
	typeof(bool)
})]
internal static class HurtPatch
{
	private static int hpBefore;

	private static void Prefix(NewMovement __instance, ref int damage)
	{
		hpBefore = __instance.hp;
		if (damage > 0 && CannonballBreakPatch.Recent())
		{
			damage = 0;
		}
		if (damage > 0 && __instance.hp - damage < 1)
		{
			damage = Mathf.Max(0, __instance.hp - 1);
		}
	}

	private static void Postfix(NewMovement __instance)
	{
		if (__instance.hp < 1)
		{
			__instance.hp = 1;
		}
		if (!__instance.dead && !Plugin.IsFinishing && __instance.hp < hpBefore)
		{
			ScreenFade.ToBlack();
			Plugin.BeatLevel(__instance);
		}
	}
}
[HarmonyPatch(typeof(Explosion), "Collide")]
internal static class ExplosionPatch
{
	private struct DamageState
	{
		public bool changed;

		public int originalDamage;
	}

	private static void Prefix(Explosion __instance, Collider other, ref DamageState __state)
	{
		if (!((Object)(object)__instance == (Object)null) && !((Object)(object)other == (Object)null) && ((Component)other).gameObject.CompareTag("Player"))
		{
			bool flag = __instance.rocketExplosion && !__instance.enemy;
			GameObject sourceWeapon = __instance.sourceWeapon;
			bool flag2 = !__instance.enemy && CannonballBreakPatch.IsFromPlayerCannonball(__instance);
			if ((!((Object)(object)sourceWeapon == (Object)null) || flag || flag2) && (flag || flag2 || (Object)(object)sourceWeapon.GetComponentInParent<Railcannon>() != (Object)null || (Object)(object)sourceWeapon.GetComponentInParent<Shotgun>() != (Object)null || (Object)(object)sourceWeapon.GetComponentInParent<ShotgunHammer>() != (Object)null || (Object)(object)sourceWeapon.GetComponentInParent<RocketLauncher>() != (Object)null) && __instance.damage > 0)
			{
				__state.changed = true;
				__state.originalDamage = __instance.damage;
				__instance.damage = 0;
			}
		}
	}

	private static void Postfix(Explosion __instance, DamageState __state)
	{
		if (__state.changed && !((Object)(object)__instance == (Object)null))
		{
			__instance.damage = __state.originalDamage;
		}
	}
}
[HarmonyPatch(typeof(Cannonball), "Break")]
internal static class CannonballBreakPatch
{
	internal static Vector3 lastPos;

	internal static float lastTime = -100f;

	private static void Prefix(Cannonball __instance)
	{
		Mark(__instance);
	}

	internal static void Mark(Cannonball cannonball)
	{
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)cannonball == (Object)null) && !((Object)(object)cannonball.sisy != (Object)null))
		{
			lastPos = ((Component)cannonball).transform.position;
			lastTime = Time.time;
		}
	}

	internal static bool Recent()
	{
		return Time.time - lastTime < 0.6f;
	}

	internal static bool IsFromPlayerCannonball(Explosion explosion)
	{
		//IL_001a: 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_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		if (Time.time - lastTime > 1.5f)
		{
			return false;
		}
		Vector3 val = ((Component)explosion).transform.position - lastPos;
		return ((Vector3)(ref val)).sqrMagnitude < 100f;
	}
}
[HarmonyPatch(typeof(Cannonball), "Explode")]
internal static class CannonballExplodePatch
{
	private static void Prefix(Cannonball __instance)
	{
		CannonballBreakPatch.Mark(__instance);
	}
}
[HarmonyPatch(typeof(FireZone), "OnTriggerStay")]
internal static class NapalmFirePatch
{
	private static void Prefix(FireZone __instance, ref bool __state)
	{
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Invalid comparison between Unknown and I4
		__state = __instance.canHurtPlayer;
		if ((int)__instance.source == 2)
		{
			__instance.canHurtPlayer = false;
		}
	}

	private static void Postfix(FireZone __instance, bool __state)
	{
		__instance.canHurtPlayer = __state;
	}
}
[HarmonyPatch]
internal static class NextLevelPatches
{
	[HarmonyPrefix]
	[HarmonyPatch(typeof(FinalPit), "SendInfo")]
	private static void PitSendInfo(FinalPit __instance)
	{
		if (Plugin.IsFinishing)
		{
			string text = Plugin.NextLevelName();
			if (text != null)
			{
				__instance.targetLevelName = text;
			}
		}
	}

	[HarmonyPrefix]
	[HarmonyPatch(typeof(FinalRank), "LevelChange")]
	private static void RankLevelChange(FinalRank __instance)
	{
		if (Plugin.IsFinishing)
		{
			string text = Plugin.NextLevelName();
			if (text != null && __instance.targetLevelName != text)
			{
				__instance.targetLevelName = text;
			}
		}
	}
}
[HarmonyPatch]
internal static class SecretLevelPatches
{
	[HarmonyTargetMethods]
	private static IEnumerable<MethodBase> TargetMethods()
	{
		MethodInfo[] methods = typeof(SceneManager).GetMethods(BindingFlags.Static | BindingFlags.Public);
		foreach (MethodInfo methodInfo in methods)
		{
			if (!(methodInfo.Name != "LoadScene") || !(methodInfo.Name != "LoadSceneAsync"))
			{
				ParameterInfo[] parameters = methodInfo.GetParameters();
				if (parameters.Length != 0 && parameters[0].ParameterType == typeof(string))
				{
					yield return methodInfo;
				}
			}
		}
	}

	private static bool Prefix(string sceneName)
	{
		if (!Plugin.IsSecretLevelName(sceneName))
		{
			return true;
		}
		Plugin.OnSecretLevelBlocked();
		return false;
	}
}
[HarmonyPatch]
internal static class CheatActivationPatches
{
	[HarmonyTargetMethods]
	private static IEnumerable<MethodBase> TargetMethods()
	{
		MethodInfo[] methods = typeof(CheatsManager).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		foreach (MethodInfo methodInfo in methods)
		{
			if (methodInfo.Name == "SetCheatActive")
			{
				yield return methodInfo;
			}
		}
	}

	private static void Prefix(object __0, ref bool __1)
	{
		if (Plugin.ModActivatingCheats)
		{
			return;
		}
		if (__0 is DisableEnemySpawns || __0 is HideUI)
		{
			PropertyInfo propertyInfo = __0?.GetType().GetProperty("IsActive", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (propertyInfo != null && propertyInfo.PropertyType == typeof(bool))
			{
				__1 = (bool)propertyInfo.GetValue(__0, null);
			}
			else
			{
				__1 = false;
			}
			Plugin.ShowNoCheatingMessage();
		}
		else if (__1)
		{
			__1 = false;
			Plugin.ShowNoCheatingMessage();
		}
	}
}
internal static class PunchDoors
{
	private static readonly Dictionary<Door, bool> finalDoorParts = new Dictionary<Door, bool>();

	private static readonly Dictionary<Door, bool> gatedDoors = new Dictionary<Door, bool>();

	private static readonly HashSet<Door> releasedDoors = new HashSet<Door>();

	private static bool allowOpen;

	internal static void Reset()
	{
		finalDoorParts.Clear();
		gatedDoors.Clear();
		releasedDoors.Clear();
	}

	internal static void MarkReleased(Door door)
	{
		releasedDoors.Add(door);
	}

	internal static bool IsLockedDoor(Door door)
	{
		if (door.locked)
		{
			return true;
		}
		if ((Object)(object)door.noPass != (Object)null && door.noPass.activeSelf)
		{
			return true;
		}
		return IsGated(door);
	}

	private static bool ArrayHas(Door[] doors, Door door)
	{
		if (doors != null)
		{
			return Array.IndexOf(doors, door) >= 0;
		}
		return false;
	}

	private static bool IsGated(Door door)
	{
		if (!door.gotValues)
		{
			return false;
		}
		if (gatedDoors.TryGetValue(door, out var value))
		{
			return value;
		}
		bool flag = door.docons == null || door.docons.Length == 0;
		if (!flag && (Object)(object)((Component)door).GetComponentInChildren<DoorLock>(true) != (Object)null)
		{
			flag = true;
		}
		if (!flag)
		{
			DoorLock[] array = Object.FindObjectsOfType<DoorLock>(true);
			foreach (DoorLock val in array)
			{
				if ((Object)(object)val != (Object)null && (Object)(object)val.parentDoor == (Object)(object)door)
				{
					flag = true;
					break;
				}
			}
		}
		if (!flag)
		{
			ItemPlaceZone[] array2 = Object.FindObjectsOfType<ItemPlaceZone>(true);
			foreach (ItemPlaceZone val2 in array2)
			{
				if ((Object)(object)val2 != (Object)null && (ArrayHas(val2.doors, door) || ArrayHas(val2.reverseDoors, door)))
				{
					flag = true;
					break;
				}
			}
		}
		gatedDoors[door] = flag;
		return flag;
	}

	internal static bool IsFinalDoorPart(Door door)
	{
		if (finalDoorParts.TryGetValue(door, out var value))
		{
			return value;
		}
		bool flag = (Object)(object)((Component)door).GetComponentInParent<FinalDoor>() != (Object)null;
		if (!flag)
		{
			FinalDoor[] array = Object.FindObjectsOfType<FinalDoor>(true);
			foreach (FinalDoor val in array)
			{
				if ((Object)(object)val != (Object)null && val.doors != null && Array.IndexOf(val.doors, door) >= 0)
				{
					flag = true;
					break;
				}
			}
		}
		finalDoorParts[door] = flag;
		return flag;
	}

	internal static bool CanOpen(Door door)
	{
		if (allowOpen || IsFinalDoorPart(door))
		{
			return true;
		}
		if (!door.gotValues)
		{
			return false;
		}
		if (!releasedDoors.Contains(door))
		{
			return IsLockedDoor(door);
		}
		return true;
	}

	internal static void PunchOpen(Door door)
	{
		allowOpen = true;
		try
		{
			door.Open(false, false);
		}
		finally
		{
			allowOpen = false;
		}
	}
}
[HarmonyPatch(typeof(Door), "Open")]
internal static class DoorOpenPatch
{
	private static bool Prefix(Door __instance)
	{
		return PunchDoors.CanOpen(__instance);
	}
}
[HarmonyPatch(typeof(Door), "Unlock")]
internal static class DoorUnlockPatch
{
	private static void Prefix(Door __instance)
	{
		if ((Object)(object)__instance != (Object)null && __instance.locked)
		{
			PunchDoors.MarkReleased(__instance);
		}
	}
}
[HarmonyPatch(typeof(Punch), "ActiveFrame")]
internal static class KnuckleblasterDoorPatch
{
	private static readonly RaycastHit[] HitBuffer = (RaycastHit[])(object)new RaycastHit[32];

	private static void Postfix(Punch __instance)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Invalid comparison between Unknown and I4
		//IL_0020: 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)
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		if ((int)__instance.type != 1)
		{
			return;
		}
		Camera main = Camera.main;
		if ((Object)(object)main == (Object)null)
		{
			return;
		}
		int num = Physics.RaycastNonAlloc(((Component)main).transform.position, ((Component)main).transform.forward, HitBuffer, 4f, -1, (QueryTriggerInteraction)1);
		for (int i = 1; i < num; i++)
		{
			RaycastHit val = HitBuffer[i];
			int num2 = i - 1;
			while (num2 >= 0 && ((RaycastHit)(ref HitBuffer[num2])).distance > ((RaycastHit)(ref val)).distance)
			{
				HitBuffer[num2 + 1] = HitBuffer[num2];
				num2--;
			}
			HitBuffer[num2 + 1] = val;
		}
		for (int j = 0; j < num; j++)
		{
			RaycastHit val2 = HitBuffer[j];
			if (!((Object)(object)((Component)((RaycastHit)(ref val2)).collider).GetComponentInParent<NewMovement>() != (Object)null))
			{
				Door componentInParent = ((Component)((RaycastHit)(ref val2)).collider).GetComponentInParent<Door>();
				if ((Object)(object)componentInParent != (Object)null && !componentInParent.open && !PunchDoors.IsLockedDoor(componentInParent) && !PunchDoors.IsFinalDoorPart(componentInParent))
				{
					PunchDoors.PunchOpen(componentInParent);
				}
				break;
			}
		}
	}
}