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;
}
}
}
}