Decompiled source of GungeonUnstuck v1.0.0

plugins/GungeonUnstuck/GungeonUnstuck.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Logging;
using Dungeonator;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("GungeonUnstuck")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("GungeonUnstuck")]
[assembly: AssemblyTitle("GungeonUnstuck")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace GungeonUnstuck;

[BepInPlugin("silstrom.gungeonunstuck", "GungeonUnstuck", "1.0.0")]
public class Plugin : BaseUnityPlugin
{
	private sealed class RescueResult
	{
		public int ClearedPlayers;

		public int RecoveredLeeks;

		public int CompletedBossDeaths;

		public int FixedRooms;

		public int UnsealedRooms;

		public int TriggeredRewards;
	}

	private sealed class OpenRoomResult
	{
		public int Rooms;

		public int IgnoredEnemies;

		public int DoorsUnsealed;

		public int DoorsUnlocked;

		public int DoorsOpened;

		public int BlockersUnsealed;

		public int TeleportersRestored;

		public int MinimapRoomsRevealed;
	}

	public const string PluginGuid = "silstrom.gungeonunstuck";

	public const string PluginName = "GungeonUnstuck";

	public const string PluginVersion = "1.0.0";

	internal static ManualLogSource Log;

	private static readonly string[] UiReasons = new string[13]
	{
		"dragun",
		"dragun_transition",
		"generic",
		"BossIntro",
		"bossKillCam",
		"gm_pause",
		"pause",
		"conversation",
		"conversationBar",
		"minimap",
		"punchout",
		"metal gear",
		string.Empty
	};

	private void Awake()
	{
		Log = ((BaseUnityPlugin)this).Logger;
		((BaseUnityPlugin)this).Logger.LogInfo((object)"GungeonUnstuck v1.0.0 loaded");
	}

	private void Start()
	{
		ETGModConsole.Commands.AddUnit("unstuck", (Action<string[]>)delegate
		{
			RescueResult rescueResult = Rescue();
			ETGModConsole.Log((object)string.Format("<color=#00FF00>{0}:</color> cleared {1} player(s), recovered {2} Leek item(s), completed {3} stuck boss death(s), fixed {4} room(s), unsealed {5} room(s), triggered {6} reward flow(s).", "GungeonUnstuck", rescueResult.ClearedPlayers, rescueResult.RecoveredLeeks, rescueResult.CompletedBossDeaths, rescueResult.FixedRooms, rescueResult.UnsealedRooms, rescueResult.TriggeredRewards), false);
		});
		ETGModConsole.Commands.AddUnit("openroom", (Action<string[]>)delegate
		{
			OpenRoomResult openRoomResult = ForceOpenCurrentRooms();
			ETGModConsole.Log((object)string.Format("<color=#00FF00>{0}:</color> force-opened {1} room(s), ignored {2} stuck enemy/enemies, unsealed {3} door(s), unlocked {4} door(s), opened {5} normal door(s), unsealed {6} blocker(s), restored {7} teleporter(s), revealed {8} minimap room(s).", "GungeonUnstuck", openRoomResult.Rooms, openRoomResult.IgnoredEnemies, openRoomResult.DoorsUnsealed, openRoomResult.DoorsUnlocked, openRoomResult.DoorsOpened, openRoomResult.BlockersUnsealed, openRoomResult.TeleportersRestored, openRoomResult.MinimapRoomsRevealed), false);
		});
		ETGModConsole.Log((object)"GungeonUnstuck v1.0.0 Initialized - commands: unstuck, openroom", false);
	}

	private static RescueResult Rescue()
	{
		RescueResult rescueResult = new RescueResult();
		try
		{
			CancelRunningBossKillCams();
			EndRunningBossIntros();
			ResetGlobalCutsceneState();
			rescueResult.ClearedPlayers = ResetPlayers();
			rescueResult.RecoveredLeeks = RecoverLeekItems();
			ResetCamera();
			ResetUI();
			ResetMinimap();
			ResetScreenFade();
			ResetBossHealthBars();
			StaticReferenceManager.DestroyAllProjectiles();
			rescueResult.CompletedBossDeaths += CompleteStuckDraGunDeaths();
			FixCurrentRooms(rescueResult);
		}
		catch (Exception ex)
		{
			Log.LogError((object)("unstuck failed: " + ex));
			ETGModConsole.Log((object)"<color=#FF0000>GungeonUnstuck failed.</color> Check BepInEx log for details.", false);
		}
		return rescueResult;
	}

	private static OpenRoomResult ForceOpenCurrentRooms()
	{
		OpenRoomResult openRoomResult = new OpenRoomResult();
		try
		{
			ResetGlobalCutsceneState();
			RecoverLeekItems();
			ResetMinimap();
			ResetUI();
			List<RoomHandler> roomsToRescue = GetRoomsToRescue();
			for (int i = 0; i < roomsToRescue.Count; i++)
			{
				RoomHandler val = roomsToRescue[i];
				if (val != null)
				{
					openRoomResult.Rooms++;
					openRoomResult.IgnoredEnemies += IgnoreRoomClearEnemies(val);
					openRoomResult.BlockersUnsealed += ForceOpenRoom(val, openRoomResult);
					openRoomResult.TeleportersRestored += RestoreRoomTeleporters(val);
					openRoomResult.MinimapRoomsRevealed += (RestoreMinimapRoom(val) ? 1 : 0);
				}
			}
		}
		catch (Exception ex)
		{
			Log.LogError((object)("openroom failed: " + ex));
			ETGModConsole.Log((object)"<color=#FF0000>GungeonUnstuck openroom failed.</color> Check BepInEx log for details.", false);
		}
		return openRoomResult;
	}

	private static void CancelRunningBossKillCams()
	{
		BossKillCam[] array = Object.FindObjectsOfType<BossKillCam>();
		for (int i = 0; i < array.Length; i++)
		{
			if ((Object)(object)array[i] != (Object)null)
			{
				array[i].ForceCancelSequence();
			}
		}
		BossKillCam.BossDeathCamRunning = false;
	}

	private static void EndRunningBossIntros()
	{
		GenericIntroDoer[] array = Object.FindObjectsOfType<GenericIntroDoer>();
		FieldInfo fieldInfo = AccessTools.Field(typeof(GenericIntroDoer), "m_isRunning");
		MethodInfo methodInfo = AccessTools.Method(typeof(GenericIntroDoer), "EndSequence", new Type[1] { typeof(bool) }, (Type[])null);
		if ((object)fieldInfo == null || (object)methodInfo == null)
		{
			return;
		}
		foreach (GenericIntroDoer val in array)
		{
			if (!((Object)(object)val == (Object)null) && (bool)fieldInfo.GetValue(val))
			{
				methodInfo.Invoke(val, new object[1] { false });
			}
		}
	}

	private static void ResetGlobalCutsceneState()
	{
		if (GameManager.HasInstance)
		{
			GameManager.Instance.PreventPausing = false;
		}
		GameManager.IsBossIntro = false;
		BossKillCam.BossDeathCamRunning = false;
		SuperReaperController.PreventShooting = false;
		BraveTime.ClearAllMultipliers();
		if ((Object)(object)StickyFrictionManager.Instance != (Object)null)
		{
			StickyFrictionManager.Instance.FrictionEnabled = true;
		}
	}

	private static int ResetPlayers()
	{
		if (!GameManager.HasInstance || GameManager.Instance.AllPlayers == null)
		{
			return 0;
		}
		int num = 0;
		PlayerController[] allPlayers = GameManager.Instance.AllPlayers;
		foreach (PlayerController val in allPlayers)
		{
			if (!((Object)(object)val == (Object)null))
			{
				val.ClearAllInputOverrides();
				val.CurrentInputState = (PlayerInputState)0;
				val.ReinitializeMovementRestrictors();
				val.ToggleGunRenderers(true, string.Empty);
				val.ToggleHandRenderers(true, string.Empty);
				SetPrivateField(val, "m_handlingQueuedAnimation", false);
				if ((Object)(object)((GameActor)val).CurrentGun != (Object)null)
				{
					((GameActor)val).CurrentGun.CeaseAttack(false, (ProjectileData)null);
				}
				if ((Object)(object)((BraveBehaviour)val).healthHaver != (Object)null)
				{
					((BraveBehaviour)val).healthHaver.IsVulnerable = true;
				}
				if ((Object)(object)((BraveBehaviour)val).gameActor != (Object)null)
				{
					((BraveBehaviour)val).gameActor.SuppressEffectUpdates = false;
					val.IsOnFire = false;
					val.CurrentFireMeterValue = 0f;
					val.CurrentPoisonMeterValue = 0f;
				}
				num++;
			}
		}
		return num;
	}

	private static int RecoverLeekItems()
	{
		if (!GameManager.HasInstance || GameManager.Instance.AllPlayers == null)
		{
			return 0;
		}
		int num = 0;
		PlayerController[] allPlayers = GameManager.Instance.AllPlayers;
		foreach (PlayerController val in allPlayers)
		{
			if ((Object)(object)val == (Object)null || val.activeItems == null)
			{
				continue;
			}
			for (int j = 0; j < val.activeItems.Count; j++)
			{
				PlayerItem item = val.activeItems[j];
				if (IsMikuLeek(item))
				{
					RecoverLeekItem(item, val);
					num++;
				}
			}
		}
		return num;
	}

	private static bool IsMikuLeek(PlayerItem item)
	{
		if ((Object)(object)item == (Object)null)
		{
			return false;
		}
		Type type = ((object)item).GetType();
		if (!(type.FullName == "MikuMikuMod.Leek"))
		{
			return type.Name == "Leek";
		}
		return true;
	}

	private static void RecoverLeekItem(PlayerItem item, PlayerController owner)
	{
		if ((Object)(object)item == (Object)null)
		{
			return;
		}
		try
		{
			item.LastOwner = owner;
			((PickupObject)item).CanBeDropped = false;
			item.ClearCooldowns();
			item.ResetSprite();
			SetPlayerItemActive(item, active: false);
			SetPrivateField(item, "m_activeElapsed", 0f);
			SetPrivateField(item, "m_activeDuration", 0f);
			SetPrivateField(item, "m_isDestroyed", false);
			if ((Object)(object)owner != (Object)null)
			{
				owner.ClearInputOverride("Leeking");
				owner.ToggleGunRenderers(true, "Leeking");
				owner.ToggleHandRenderers(true, "Leeking");
				owner.ToggleGunRenderers(true, string.Empty);
				owner.ToggleHandRenderers(true, string.Empty);
				SetPrivateField(owner, "m_handlingQueuedAnimation", false);
				if ((Object)(object)GameUIRoot.Instance != (Object)null)
				{
					GameUIRoot.Instance.UpdateItemData(owner, owner.CurrentItem, owner.activeItems);
				}
			}
		}
		catch (Exception ex)
		{
			Log.LogWarning((object)("Failed to recover Miku Leek item: " + ex.Message));
		}
	}

	private static void SetPlayerItemActive(PlayerItem item, bool active)
	{
		MethodInfo methodInfo = AccessTools.PropertySetter(typeof(PlayerItem), "IsCurrentlyActive");
		if ((object)methodInfo != null)
		{
			methodInfo.Invoke(item, new object[1] { active });
		}
		else
		{
			SetPrivateField(item, "m_isCurrentlyActive", active);
		}
	}

	private static void ResetCamera()
	{
		if (GameManager.HasInstance && !((Object)(object)GameManager.Instance.MainCameraController == (Object)null))
		{
			CameraController mainCameraController = GameManager.Instance.MainCameraController;
			mainCameraController.StartTrackingPlayer();
			mainCameraController.SetManualControl(false, false);
			mainCameraController.PreventAimLook = false;
			mainCameraController.LockX = false;
			mainCameraController.LockY = false;
			mainCameraController.LockToRoom = false;
			mainCameraController.OverrideZoomScale = 1f;
			mainCameraController.OverrideRecoverySpeed = -1f;
			ClearCameraFocusObjects(mainCameraController);
		}
	}

	private static void ResetUI()
	{
		GameUIRoot instance = GameUIRoot.Instance;
		if (!((Object)(object)instance == (Object)null))
		{
			for (int i = 0; i < UiReasons.Length; i++)
			{
				string text = UiReasons[i];
				instance.ShowCoreUI(text);
				instance.ToggleLowerPanels(true, false, text);
				instance.ToggleAllDefaultLabels(true, text);
			}
			ClearOverridableBool(instance, "CoreUIHidden");
			ClearOverridableBool(instance, "ForceLowerPanelsInvisibleOverride");
			ClearOverridableBool(instance, "m_defaultLabelsHidden");
			RefreshCoreUITransition(instance);
			ClearReloadBarInvisibility(instance);
			instance.ToggleLowerPanels(true, false, "unstuck");
			instance.ToggleAllDefaultLabels(true, "unstuck");
			instance.ToggleItemPanels(true);
			instance.HidePauseMenu();
			instance.EndBossKillCam();
			if ((Object)(object)instance.notificationController != (Object)null)
			{
				instance.notificationController.ForceHide();
			}
		}
	}

	private static void ResetMinimap()
	{
		Minimap instance = Minimap.Instance;
		if (!((Object)(object)instance == (Object)null))
		{
			instance.TemporarilyPreventMinimap = false;
			instance.HeldOpen = false;
			if ((Object)(object)instance.UIMinimap != (Object)null)
			{
				instance.UIMinimap.ToggleState(false);
			}
		}
	}

	private static void ResetScreenFade()
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		Pixelator instance = Pixelator.Instance;
		if (!((Object)(object)instance == (Object)null))
		{
			instance.SetFadeColor(Color.clear);
			instance.saturation = 1f;
		}
	}

	private static void ResetBossHealthBars()
	{
		GameUIRoot instance = GameUIRoot.Instance;
		if (!((Object)(object)instance == (Object)null))
		{
			if ((Object)(object)instance.bossController != (Object)null)
			{
				instance.bossController.DisableBossHealth();
			}
			if ((Object)(object)instance.bossController2 != (Object)null)
			{
				instance.bossController2.DisableBossHealth();
			}
			if ((Object)(object)instance.bossControllerSide != (Object)null)
			{
				instance.bossControllerSide.DisableBossHealth();
			}
		}
	}

	private static int CompleteStuckDraGunDeaths()
	{
		int num = 0;
		DraGunController[] array = Object.FindObjectsOfType<DraGunController>();
		foreach (DraGunController val in array)
		{
			if ((Object)(object)val == (Object)null || (Object)(object)((BraveBehaviour)val).healthHaver == (Object)null || !((BraveBehaviour)val).healthHaver.IsDead)
			{
				continue;
			}
			RoomHandler room = (((Object)(object)((BraveBehaviour)val).aiActor != (Object)null) ? ((BraveBehaviour)val).aiActor.ParentRoom : null);
			bool flag = IsEnemyRegisteredInRoom(room, ((BraveBehaviour)val).aiActor);
			try
			{
				val.RestrictMotion(false);
				val.ModifyCamera(false);
				val.BlockPitTiles(false);
				val.IsTransitioning = false;
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Failed to reset DraGun controller state: " + ex.Message));
			}
			CompleteDraGunRoomPlaceables(room);
			if (flag)
			{
				try
				{
					((BraveBehaviour)val).healthHaver.DeathAnimationComplete((tk2dSpriteAnimator)null, (tk2dSpriteAnimationClip)null);
					num++;
				}
				catch (Exception ex2)
				{
					Log.LogWarning((object)("Failed to complete DraGun death animation, deregistering enemy instead: " + ex2.Message));
					TryDeregisterEnemy(room, ((BraveBehaviour)val).aiActor);
				}
			}
		}
		return num;
	}

	private static void CompleteDraGunRoomPlaceables(RoomHandler room)
	{
		if (room == null)
		{
			return;
		}
		List<DraGunRoomPlaceable> componentsAbsoluteInRoom = room.GetComponentsAbsoluteInRoom<DraGunRoomPlaceable>();
		for (int i = 0; i < componentsAbsoluteInRoom.Count; i++)
		{
			DraGunRoomPlaceable val = componentsAbsoluteInRoom[i];
			if (!((Object)(object)val == (Object)null))
			{
				val.DraGunKilled = true;
				try
				{
					val.ExtendDeathBridge();
				}
				catch (Exception ex)
				{
					Log.LogWarning((object)("Failed to extend DraGun death bridge: " + ex.Message));
				}
			}
		}
	}

	private static void FixCurrentRooms(RescueResult result)
	{
		List<RoomHandler> roomsToRescue = GetRoomsToRescue();
		for (int i = 0; i < roomsToRescue.Count; i++)
		{
			RoomHandler val = roomsToRescue[i];
			if (val == null)
			{
				continue;
			}
			bool flag = PruneDeadEnemies(val);
			if (!val.HasActiveEnemies((ActiveEnemyType)1))
			{
				SetPrivateField(val, "numberOfTimedWavesOnDeck", 0);
				val.forceTeleportersActive = true;
				CompleteDraGunRoomPlaceables(val);
				if (ForceUnsealRoom(val))
				{
					result.UnsealedRooms++;
				}
				if (TriggerRoomClearFlowIfNeeded(val))
				{
					result.TriggeredRewards++;
				}
				if (flag || val.IsSealed)
				{
					result.FixedRooms++;
				}
			}
		}
	}

	private static List<RoomHandler> GetRoomsToRescue()
	{
		List<RoomHandler> list = new List<RoomHandler>();
		if (!GameManager.HasInstance)
		{
			return list;
		}
		PlayerController[] allPlayers = GameManager.Instance.AllPlayers;
		if (allPlayers != null)
		{
			for (int i = 0; i < allPlayers.Length; i++)
			{
				if ((Object)(object)allPlayers[i] != (Object)null && allPlayers[i].CurrentRoom != null && !list.Contains(allPlayers[i].CurrentRoom))
				{
					list.Add(allPlayers[i].CurrentRoom);
				}
			}
		}
		if ((Object)(object)GameManager.Instance.BestActivePlayer != (Object)null && GameManager.Instance.BestActivePlayer.CurrentRoom != null && !list.Contains(GameManager.Instance.BestActivePlayer.CurrentRoom))
		{
			list.Add(GameManager.Instance.BestActivePlayer.CurrentRoom);
		}
		return list;
	}

	private static bool PruneDeadEnemies(RoomHandler room)
	{
		bool result = false;
		List<AIActor> activeEnemiesList = GetActiveEnemiesList(room);
		if (activeEnemiesList == null)
		{
			return false;
		}
		for (int num = activeEnemiesList.Count - 1; num >= 0; num--)
		{
			AIActor val = activeEnemiesList[num];
			if ((Object)(object)val == (Object)null)
			{
				activeEnemiesList.RemoveAt(num);
				result = true;
			}
			else if ((Object)(object)((BraveBehaviour)val).healthHaver != (Object)null && ((BraveBehaviour)val).healthHaver.IsDead)
			{
				bool flag = false;
				try
				{
					((BraveBehaviour)val).healthHaver.DeathAnimationComplete((tk2dSpriteAnimator)null, (tk2dSpriteAnimationClip)null);
					flag = true;
				}
				catch (Exception ex)
				{
					Log.LogWarning((object)("Failed to finalize dead enemy, deregistering instead: " + ex.Message));
				}
				if (!flag && activeEnemiesList.Contains(val))
				{
					activeEnemiesList.Remove(val);
				}
				result = true;
			}
		}
		return result;
	}

	private static bool TriggerRoomClearFlowIfNeeded(RoomHandler room)
	{
		if (room == null || !room.EverHadEnemies || GetPrivateBool(room, "m_hasGivenReward"))
		{
			return false;
		}
		try
		{
			if ((Object)(object)GameManager.Instance != (Object)null && (Object)(object)GameManager.Instance.DungeonMusicController != (Object)null)
			{
				GameManager.Instance.DungeonMusicController.NotifyCurrentRoomEnemiesCleared();
			}
			room.OnEnemiesCleared?.Invoke();
			GameManager.BroadcastRoomTalkDoerFsmEvent("roomCleared");
			return true;
		}
		catch (Exception ex)
		{
			Log.LogWarning((object)("Failed to trigger room clear flow: " + ex.Message));
			return false;
		}
	}

	private static bool ForceUnsealRoom(RoomHandler room)
	{
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		bool result = room.IsSealed;
		try
		{
			room.npcSealState = (NPCSealState)0;
			room.UnsealRoom();
		}
		catch (Exception ex)
		{
			Log.LogWarning((object)("Failed to unseal room through RoomHandler: " + ex.Message));
		}
		if (room.connectedDoors != null)
		{
			for (int i = 0; i < room.connectedDoors.Count; i++)
			{
				DungeonDoorController val = room.connectedDoors[i];
				if (!((Object)(object)val == (Object)null))
				{
					if (val.IsSealed)
					{
						result = true;
					}
					try
					{
						val.KeepBossDoorSealed = false;
						val.DoUnseal(room);
						val.IsSealed = false;
					}
					catch (Exception ex2)
					{
						Log.LogWarning((object)("Failed to unseal door: " + ex2.Message));
					}
				}
			}
		}
		if (room.standaloneBlockers != null)
		{
			for (int j = 0; j < room.standaloneBlockers.Count; j++)
			{
				DungeonDoorSubsidiaryBlocker val2 = room.standaloneBlockers[j];
				if (!((Object)(object)val2 == (Object)null))
				{
					if (val2.isSealed)
					{
						result = true;
					}
					try
					{
						val2.Unseal();
					}
					catch (Exception ex3)
					{
						Log.LogWarning((object)("Failed to unseal standalone blocker: " + ex3.Message));
					}
				}
			}
		}
		return result;
	}

	private static int IgnoreRoomClearEnemies(RoomHandler room)
	{
		int num = 0;
		List<AIActor> activeEnemiesList = GetActiveEnemiesList(room);
		if (activeEnemiesList == null)
		{
			return 0;
		}
		for (int i = 0; i < activeEnemiesList.Count; i++)
		{
			AIActor val = activeEnemiesList[i];
			if ((Object)(object)val != (Object)null && !val.IgnoreForRoomClear)
			{
				val.IgnoreForRoomClear = true;
				num++;
			}
		}
		return num;
	}

	private static int ForceOpenRoom(RoomHandler room, OpenRoomResult result)
	{
		//IL_002a: 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_00c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c9: Invalid comparison between Unknown and I4
		int num = 0;
		SetPrivateField(room, "numberOfTimedWavesOnDeck", 0);
		room.CompletelyPreventLeaving = false;
		room.PreventMinimapUpdates = false;
		room.forceTeleportersActive = true;
		room.npcSealState = (NPCSealState)0;
		try
		{
			room.UnsealRoom();
		}
		catch (Exception ex)
		{
			Log.LogWarning((object)("Failed to unseal room in openroom: " + ex.Message));
		}
		if (room.connectedDoors != null)
		{
			for (int i = 0; i < room.connectedDoors.Count; i++)
			{
				DungeonDoorController val = room.connectedDoors[i];
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				bool isSealed = val.IsSealed;
				bool isLocked = val.isLocked;
				bool isOpen = val.IsOpen;
				try
				{
					val.KeepBossDoorSealed = false;
					val.DoUnseal(room);
					val.IsSealed = false;
					if (val.isLocked)
					{
						val.Unlock();
					}
					if ((int)val.Mode == 0 || (int)val.Mode == 2)
					{
						val.Open(false);
					}
				}
				catch (Exception ex2)
				{
					Log.LogWarning((object)("Failed to force-open door: " + ex2.Message));
				}
				if (isSealed)
				{
					result.DoorsUnsealed++;
				}
				if (isLocked)
				{
					result.DoorsUnlocked++;
				}
				if (!isOpen && val.IsOpen)
				{
					result.DoorsOpened++;
				}
			}
		}
		if (room.standaloneBlockers != null)
		{
			for (int j = 0; j < room.standaloneBlockers.Count; j++)
			{
				DungeonDoorSubsidiaryBlocker val2 = room.standaloneBlockers[j];
				if (!((Object)(object)val2 == (Object)null))
				{
					bool isSealed2 = val2.isSealed;
					try
					{
						val2.Unseal();
					}
					catch (Exception ex3)
					{
						Log.LogWarning((object)("Failed to unseal standalone blocker in openroom: " + ex3.Message));
					}
					if (isSealed2)
					{
						num++;
					}
				}
			}
		}
		return num;
	}

	private static int RestoreRoomTeleporters(RoomHandler room)
	{
		int num = 0;
		room.forceTeleportersActive = true;
		List<TeleporterController> componentsAbsoluteInRoom = room.GetComponentsAbsoluteInRoom<TeleporterController>();
		for (int i = 0; i < componentsAbsoluteInRoom.Count; i++)
		{
			TeleporterController val = componentsAbsoluteInRoom[i];
			if (!((Object)(object)val == (Object)null))
			{
				SetPrivateField(val, "m_activated", true);
				if ((Object)(object)val.extantActiveVFX != (Object)null)
				{
					val.extantActiveVFX.SetActive(true);
				}
				if ((Object)(object)val.portalVFX != (Object)null)
				{
					((Component)val.portalVFX).gameObject.SetActive(true);
				}
				num++;
			}
		}
		Minimap instance = Minimap.Instance;
		if ((Object)(object)instance != (Object)null)
		{
			instance.PreventAllTeleports = false;
			if (instance.RoomToTeleportMap != null && instance.RoomToTeleportMap.ContainsKey(room))
			{
				GameObject val2 = instance.RoomToTeleportMap[room];
				if ((Object)(object)val2 != (Object)null)
				{
					val2.SetActive(true);
				}
				UpdateMinimapTeleporterIcon(instance, room);
			}
		}
		return num;
	}

	private static bool RestoreMinimapRoom(RoomHandler room)
	{
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Invalid comparison between Unknown and I4
		if (room == null)
		{
			return false;
		}
		room.PreventMinimapUpdates = false;
		room.RevealedOnMap = true;
		if ((int)room.visibility == 0 || (int)room.visibility == 3)
		{
			room.visibility = (VisibilityStatus)2;
		}
		Minimap instance = Minimap.Instance;
		if ((Object)(object)instance == (Object)null)
		{
			return false;
		}
		instance.TemporarilyPreventMinimap = false;
		instance.PreventAllTeleports = false;
		instance.HeldOpen = false;
		instance.RevealMinimapRoom(room, true, true, true);
		UpdateMinimapTeleporterIcon(instance, room);
		return true;
	}

	private static void UpdateMinimapTeleporterIcon(Minimap minimap, RoomHandler room)
	{
		AccessTools.Method(typeof(Minimap), "UpdateTeleporterIconForRoom", (Type[])null, (Type[])null)?.Invoke(minimap, new object[1] { room });
	}

	private static bool IsEnemyRegisteredInRoom(RoomHandler room, AIActor enemy)
	{
		if (room == null || (Object)(object)enemy == (Object)null)
		{
			return false;
		}
		return GetActiveEnemiesList(room)?.Contains(enemy) ?? false;
	}

	private static void TryDeregisterEnemy(RoomHandler room, AIActor enemy)
	{
		if (room == null || (Object)(object)enemy == (Object)null)
		{
			return;
		}
		try
		{
			room.DeregisterEnemy(enemy, false);
		}
		catch (Exception ex)
		{
			Log.LogWarning((object)("Failed to deregister enemy: " + ex.Message));
		}
	}

	private static List<AIActor> GetActiveEnemiesList(RoomHandler room)
	{
		FieldInfo fieldInfo = AccessTools.Field(typeof(RoomHandler), "activeEnemies");
		if ((object)fieldInfo != null)
		{
			return fieldInfo.GetValue(room) as List<AIActor>;
		}
		return null;
	}

	private static void ClearOverridableBool(object target, string fieldName)
	{
		FieldInfo fieldInfo = AccessTools.Field(target.GetType(), fieldName);
		if ((object)fieldInfo != null)
		{
			object? value = fieldInfo.GetValue(target);
			OverridableBool val = (OverridableBool)((value is OverridableBool) ? value : null);
			if (val != null)
			{
				val.ClearOverrides();
			}
		}
	}

	private static void RefreshCoreUITransition(GameUIRoot ui)
	{
		MethodInfo methodInfo = AccessTools.Method(typeof(GameUIRoot), "RecalculateTargetPositions", (Type[])null, (Type[])null);
		MethodInfo methodInfo2 = AccessTools.Method(typeof(GameUIRoot), "CoreUITransition", (Type[])null, (Type[])null);
		methodInfo?.Invoke(ui, null);
		if ((object)methodInfo2 != null && methodInfo2.Invoke(ui, null) is IEnumerator enumerator)
		{
			((MonoBehaviour)ui).StartCoroutine(enumerator);
		}
	}

	private static void ClearReloadBarInvisibility(GameUIRoot ui)
	{
		FieldInfo fieldInfo = AccessTools.Field(typeof(GameUIRoot), "m_extantReloadBars");
		if ((object)fieldInfo == null || !(fieldInfo.GetValue(ui) is List<GameUIReloadBarController> list))
		{
			return;
		}
		for (int i = 0; i < list.Count; i++)
		{
			if ((Object)(object)list[i] != (Object)null)
			{
				list[i].SetInvisibility(false, "CoreUI");
			}
		}
	}

	private static void ClearCameraFocusObjects(CameraController camera)
	{
		FieldInfo fieldInfo = AccessTools.Field(typeof(CameraController), "m_focusObjects");
		if ((object)fieldInfo != null && fieldInfo.GetValue(camera) is IList list)
		{
			list.Clear();
		}
	}

	private static bool GetPrivateBool(object target, string fieldName)
	{
		FieldInfo fieldInfo = AccessTools.Field(target.GetType(), fieldName);
		if ((object)fieldInfo != null && fieldInfo.GetValue(target) is bool)
		{
			return (bool)fieldInfo.GetValue(target);
		}
		return false;
	}

	private static void SetPrivateField(object target, string fieldName, object value)
	{
		AccessTools.Field(target.GetType(), fieldName)?.SetValue(target, value);
	}
}