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)delegate { RescueResult rescueResult = Rescue(); ETGModConsole.Log((object)string.Format("{0}: 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)delegate { OpenRoomResult openRoomResult = ForceOpenCurrentRooms(); ETGModConsole.Log((object)string.Format("{0}: 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)"GungeonUnstuck failed. Check BepInEx log for details.", false); } return rescueResult; } private static OpenRoomResult ForceOpenCurrentRooms() { OpenRoomResult openRoomResult = new OpenRoomResult(); try { ResetGlobalCutsceneState(); RecoverLeekItems(); ResetMinimap(); ResetUI(); List 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)"GungeonUnstuck openroom failed. Check BepInEx log for details.", false); } return openRoomResult; } private static void CancelRunningBossKillCams() { BossKillCam[] array = Object.FindObjectsOfType(); 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(); 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(); 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 componentsAbsoluteInRoom = room.GetComponentsAbsoluteInRoom(); 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 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 GetRoomsToRescue() { List list = new List(); 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 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 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 componentsAbsoluteInRoom = room.GetComponentsAbsoluteInRoom(); 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 GetActiveEnemiesList(RoomHandler room) { FieldInfo fieldInfo = AccessTools.Field(typeof(RoomHandler), "activeEnemies"); if ((object)fieldInfo != null) { return fieldInfo.GetValue(room) as List; } 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 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); } }