Decompiled source of Pantheon Of Pharloom v1.2.0

PantheonOfPharloom.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using GlobalEnums;
using HarmonyLib;
using HutongGames.PlayMaker;
using HutongGames.PlayMaker.Actions;
using InControl;
using JetBrains.Annotations;
using Microsoft.CodeAnalysis;
using MonoMod.RuntimeDetour;
using PantheonOfPharloom.Actions;
using TMProOld;
using TeamCherry.Localization;
using TeamCherry.NestedFadeGroup;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("PantheonOfPharloom")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+f23fd608e16d580bb6b558662db10d0111a44789")]
[assembly: AssemblyProduct("PantheonOfPharloom")]
[assembly: AssemblyTitle("PantheonOfPharloom")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
	internal static class IsExternalInit
	{
	}
}
namespace PantheonOfPharloom
{
	internal class UserState
	{
		public string Scene { get; init; }

		public string Marker { get; init; }

		public HeroItemsState Items { get; init; }
	}
	public static class FadeSceneInHook
	{
		private static Hook _hook;

		private static bool _enabled = true;

		public static void Init()
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			_hook = new Hook((MethodBase)typeof(GameManager).GetMethod("FadeSceneIn", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic), (Delegate)new Action<Action<GameManager>, GameManager>(FadeSceneInDetour));
		}

		public static void SetEnabled(bool enabled)
		{
			_enabled = enabled;
		}

		private static void FadeSceneInDetour(Action<GameManager> orig, GameManager self)
		{
			if (!_enabled)
			{
				orig(self);
				PopLogger.Log("[FadeSceneInHook] Forcing fade-in.");
			}
			else
			{
				PopLogger.Log("[FadeSceneInHook] Skipping fade-in.");
			}
		}

		public static void ForceCall()
		{
			SetEnabled(enabled: false);
			GameManager.instance.FadeSceneIn();
			SetEnabled(enabled: true);
		}

		public static void Unload()
		{
			Hook hook = _hook;
			if (hook != null)
			{
				hook.Dispose();
			}
			_hook = null;
		}
	}
	public class BossRushController : MonoBehaviour
	{
		private static readonly bool DO_TELEPORT = true;

		private List<Encounter> _encounters;

		private int _encounterIndex = -1;

		private bool _isActive;

		public static BossRushController Instance;

		private readonly bool _debug;

		private UserState _userState;

		public static Dictionary<string, bool> _playerDataBools = new Dictionary<string, bool>();

		private static HashSet<string> _excludeList = new HashSet<string>
		{
			"hasDash", "hasBrolly", "hasSuperJump", "HasSeenEvaHeal", "hasHarpoonDash", "hasChargeSlash", "hasNeedolin", "hasWalljump", "hasDoubleJump", "hasNeedolinMemoryPowerup",
			"HasBoundCrestUpgrader", "UnlockedExtraBlueSlot", "UnlockedExtraYellowSlot", "UnlockedFastTravel", "UnlockedFastTravelTeleport", "hasQuill", "mapAllRooms", "HasAllMaps", "HasWhiteFlower", "completedTutorial",
			"SeenBindPrompt", "seenDreamNailPrompt", "SeenToolGetPrompt", "SeenToolWeaponGetPrompt", "SeenToolEquipPrompt", "SeenToolUsePrompt", "LightningToolToggle"
		};

		public bool AllowUI
		{
			get
			{
				if (_isActive)
				{
					return _debug;
				}
				return true;
			}
		}

		public bool IsActive => _isActive;

		public Encounter CurrentEncounter => _encounters[_encounterIndex];

		public Encounter NextEncounter => _encounters[_encounterIndex + 1];

		private void Awake()
		{
			Instance = this;
		}

		private static void PatchPlayerData()
		{
			_playerDataBools = new Dictionary<string, bool>();
			string[] array = (from x in typeof(PlayerData).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
				select x.Name into x
				where !_excludeList.Contains(x)
				select x).ToArray();
			CacheUtils.CachePlayerDataBools(array);
			string[] array2 = array;
			foreach (string text in array2)
			{
				_playerDataBools[text] = PlayerData.instance.GetBool(text);
				PlayerData.instance.SetBool(text, text.StartsWith("encountered", StringComparison.InvariantCulture));
			}
		}

		private static void RestorePlayerData()
		{
			if (PlayerData.instance != null)
			{
				CacheUtils.Restore();
			}
		}

		private void RestoreSpawnScene()
		{
			PlayerData.instance.respawnScene = _userState.Scene;
			PlayerData.instance.respawnMarkerName = _userState.Marker;
			PlayerData.instance.tempRespawnScene = "";
			PlayerData.instance.tempRespawnMarker = "";
			PopLogger.Log("restoring scene and stuff: " + PlayerData.instance.tempRespawnScene + ", " + PlayerData.instance.tempRespawnMarker);
		}

		private void AfterDeathOrCompletion()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			Reset();
			HeroItemsState items = _userState.Items;
			((HeroItemsState)(ref items)).Apply(HeroController.instance);
		}

		private void OnHornetDeath()
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Expected O, but got Unknown
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Expected O, but got Unknown
			if (_userState != null)
			{
				RestoreSpawnScene();
			}
			_encounters[_encounterIndex].OnExit?.Invoke();
			GameManager.instance.OnFinishedEnteringScene -= new EnterSceneEvent(OnNewEncounterLoad);
			GameManager.instance.OnFinishedEnteringScene += new EnterSceneEvent(Once);
			void Once()
			{
				//IL_0042: Unknown result type (might be due to invalid IL or missing references)
				//IL_004c: Expected O, but got Unknown
				PopLogger.Log("called once...");
				AfterDeathOrCompletion();
				if (!string.IsNullOrEmpty(PlayerData.instance.HeroCorpseScene))
				{
					HeroController.instance.CocoonBroken();
					EventRegister.SendEvent(EventRegisterEvents.BreakHeroCorpse, (GameObject)null);
				}
				GameManager.instance.OnFinishedEnteringScene -= new EnterSceneEvent(Once);
			}
		}

		public static void SetupNewSequence(List<Encounter> encounters, bool transition, bool recordState = true)
		{
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			if (encounters.Count == 0)
			{
				PopLogger.LogError("Cannot start boss rush with 0 encounters.");
				return;
			}
			if (Instance._isActive)
			{
				Instance.Reset();
				PopLogger.LogError("Active sequence already exists, thsi should not happen...");
			}
			if (recordState)
			{
				PopLogger.Log("recording: " + PlayerData.instance.respawnScene + ", " + PlayerData.instance.respawnMarkerName);
				Instance._userState = new UserState
				{
					Scene = PlayerData.instance.respawnScene,
					Marker = PlayerData.instance.respawnMarkerName,
					Items = HeroItemsState.Record(HeroController.instance)
				};
			}
			PopLogger.Log($"Starting new boss sequence of length {encounters.Count}");
			HeroController.instance.OnDeath += Instance.OnHornetDeath;
			Instance._encounters = encounters;
			Instance._isActive = true;
			PatchPlayerData();
			FadeSceneInHook.Init();
			FadeSceneInHook.SetEnabled(enabled: true);
			if (transition)
			{
				Instance.NextBoss();
			}
		}

		private void BeginBossRushCompletion(float delay, IEnumerator finishCallback)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: 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_0040: 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_0074: Expected O, but got Unknown
			PopLogger.Log("Completed boss rush!");
			FadeSceneInHook.SetEnabled(enabled: false);
			if (_userState != null)
			{
				RestoreSpawnScene();
			}
			string sceneName = default(string);
			string entryGateName = default(string);
			GameManager.instance.GetRespawnInfo(ref sceneName, ref entryGateName);
			StartTransitionWithCoroutine(new SceneLoadInfo
			{
				SceneName = sceneName,
				EntryGateName = entryGateName,
				PreventCameraFadeOut = true,
				AlwaysUnloadUnusedAssets = true
			}, delay, finishCallback, delegate
			{
				GameManager.instance.RespawningHero = true;
			});
		}

		private void NextBoss()
		{
			if (_encounterIndex >= 0)
			{
				CurrentEncounter.OnExit?.Invoke();
			}
			_encounterIndex++;
			PopLogger.Log("calling NextBoss.");
			if (_encounterIndex == _encounters.Count)
			{
				PopLogger.Log("end reached");
				BeginBossRushCompletion(_encounters[_encounterIndex - 1].TransitionDelay, SceneAfterFinish());
				return;
			}
			Encounter encounter = _encounters[_encounterIndex];
			encounter.BeforeEnter?.Invoke();
			PopLogger.Log($"Starting next boss scene: {encounter.SceneInfo}");
			StartTransitionWithCallback(encounter.SceneInfo, (_encounterIndex == 0) ? 0f : _encounters[_encounterIndex - 1].TransitionDelay, OnNewEncounterLoad);
			IEnumerator SceneAfterFinish()
			{
				_encounters[_encounterIndex - 1].AfterExit?.Invoke();
				AfterDeathOrCompletion();
				yield return null;
				PopLogger.Log("created fireworks");
			}
		}

		private void TransitionFromBench()
		{
			CurrentEncounter.OnExit?.Invoke();
			_encounterIndex++;
			Encounter encounter = _encounters[_encounterIndex];
			encounter.BeforeEnter?.Invoke();
			StartTransitionWithCallback(encounter.SceneInfo, 0f, OnNewEncounterLoad, doTransition: false);
		}

		private void PatchBadStates()
		{
			GameManager.instance.SetTimeScale(1f);
			FSMUtility.LocateMyFSM(((Component)((Component)GameCameras.instance.hudCamera).transform.Find("In-game/Anchor TL/Hud Canvas Offset/Hud Canvas")).gameObject, "Slide Out").SendEvent("IN");
			EventRegister.SendEvent("SHOW HP", (GameObject)null);
		}

		private void TeleportPlayerToCustomSpawn(Vector3 position)
		{
			//IL_000a: 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_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_002f: 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)
			Extensions.SetPosition2D(HeroController.instance.transform, Vector2.op_Implicit(position));
			Vector3 position2 = HeroController.instance.transform.position;
			GameManager.instance.cameraCtrl.SnapTo(position2.x, position2.y);
		}

		private void OnNewEncounterLoad()
		{
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Expected O, but got Unknown
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			PopLogger.Log("Encounter loaded...");
			if (_encounterIndex > 0)
			{
				_encounters[_encounterIndex - 1].AfterExit?.Invoke();
			}
			CurrentEncounter.AfterEnter?.Invoke();
			PatchBadStates();
			IEncounterCompletedNotification encounterCompletedNotification = EncounterCompletionRegistry.AddEncounterCompletion(Object.Instantiate<GameObject>(new GameObject("BossRushController")), CurrentEncounter);
			if (encounterCompletedNotification is BenchTransitionNotification benchTransitionNotification)
			{
				benchTransitionNotification.nextScene = NextEncounter.SceneInfo.SceneName;
				benchTransitionNotification.nextGate = NextEncounter.SceneInfo.EntryGateName;
				encounterCompletedNotification.OnEncounterCompleted += delegate
				{
					PopLogger.Log("Transitioning from bench....");
					TransitionFromBench();
				};
				((MonoBehaviour)GameManager.instance).StartCoroutine(WaitThenFade(0.1f));
				return;
			}
			HealthManager[] array = BossEncounterCompleteNotification.GetHealthManagers(CurrentEncounter.BossPathFromRoot).ToArray();
			if (DO_TELEPORT && !CurrentEncounter.SkipTeleport)
			{
				if (CurrentEncounter.CustomSpawnPoint.HasValue)
				{
					TeleportPlayerToCustomSpawn(Vector2.op_Implicit(CurrentEncounter.CustomSpawnPoint.Value));
				}
				else if (array.Length != 0)
				{
					Vector3 position = HeroController.instance.FindGroundPoint(Vector2.op_Implicit(((Component)array[0]).transform.position), true);
					TeleportPlayerToCustomSpawn(position);
				}
				else
				{
					PopLogger.LogError("Could not find boss to teleport to, set custom spawn point");
				}
			}
			else
			{
				PopLogger.Log("skipping teleport");
			}
			HealthManager[] array2 = array;
			foreach (HealthManager val in array2)
			{
				CurrentEncounter.ScaleHealth?.Invoke(val);
				PopLogger.LogWarning($"Scaled HP for {val}");
			}
			if (TransitionPoint.TransitionPoints != null)
			{
				foreach (TransitionPoint transitionPoint in TransitionPoint.TransitionPoints)
				{
					if (transitionPoint != null && !((Object)transitionPoint).name.Contains("door"))
					{
						transitionPoint.activated = false;
						if (transitionPoint.collider != null)
						{
							transitionPoint.collider.isTrigger = false;
						}
						PopLogger.Log($"patched transition: {transitionPoint}");
					}
				}
			}
			if (TransitionPoint.TransitionPoints == null)
			{
				new List<TransitionPoint>();
			}
			encounterCompletedNotification.OnEncounterCompleted += delegate
			{
				PopLogger.Log("calling current encounte exit....");
				NextBoss();
			};
			((MonoBehaviour)GameManager.instance).StartCoroutine(WaitThenFade(0.3f));
			static IEnumerator WaitThenFade(float delay)
			{
				yield return (object)new WaitForSeconds(delay);
				FadeSceneInHook.ForceCall();
			}
		}

		private void StartTransitionWithCallback(SceneLoadInfo info, float delay = 0f, Action callback = null, bool doTransition = true)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			if (doTransition)
			{
				((MonoBehaviour)this).StartCoroutine(DoTransition(info, delay));
			}
			GameManager.instance.OnFinishedEnteringScene += new EnterSceneEvent(Wrapper);
			void Wrapper()
			{
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0016: Expected O, but got Unknown
				GameManager.instance.OnFinishedEnteringScene -= new EnterSceneEvent(Wrapper);
				callback?.Invoke();
				HeroController.instance.acceptingInput = true;
			}
		}

		private void StartTransitionWithCoroutine(SceneLoadInfo info, float delay = 0f, IEnumerator callback = null, Action beforeTransition = null)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			((MonoBehaviour)this).StartCoroutine(DoTransition(info, delay, beforeTransition));
			GameManager.instance.OnFinishedEnteringScene += new EnterSceneEvent(Wrapper);
			void Wrapper()
			{
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0016: Expected O, but got Unknown
				GameManager.instance.OnFinishedEnteringScene -= new EnterSceneEvent(Wrapper);
				if (callback != null)
				{
					((MonoBehaviour)GameManager.instance).StartCoroutine(callback);
				}
				HeroController.instance.acceptingInput = true;
			}
		}

		private IEnumerator DoTransition(SceneLoadInfo info, float delay = 0f, Action beforeTransition = null)
		{
			yield return (object)new WaitForSeconds(delay);
			ScreenFaderUtils.Fade(ScreenFaderUtils.GetColour(), Color.black, 1.5f);
			yield return (object)new WaitForSeconds(1.5f);
			yield return (object)new WaitUntil((Func<bool>)(() => !GameManager.instance.IsInSceneTransition && !GameManager.instance.IsLoadingSceneTransition));
			HeroController.instance.acceptingInput = false;
			beforeTransition?.Invoke();
			GameManager.instance.BeginSceneTransition(info);
		}

		private void OnDestroy()
		{
			Instance = null;
		}

		public void Reset(bool patch = true)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Expected O, but got Unknown
			_encounterIndex = -1;
			_encounters = null;
			_isActive = false;
			FadeSceneInHook.Unload();
			if (patch)
			{
				RestorePlayerData();
				HeroController.instance.OnDeath -= OnHornetDeath;
				GameManager.instance.OnFinishedEnteringScene -= new EnterSceneEvent(OnNewEncounterLoad);
			}
		}
	}
	internal class BenchTransitionNotification : MonoBehaviour, IEncounterCompletedNotification
	{
		public string nextScene;

		public string nextGate;

		public event Action OnEncounterCompleted;

		private void Start()
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			TransitionPoint component = GameObject.Find("left1").GetComponent<TransitionPoint>();
			component.targetScene = nextScene;
			component.entryPoint = nextGate;
			component.OnBeforeTransition += (BeforeTransitionEvent)delegate
			{
				this.OnEncounterCompleted?.Invoke();
			};
		}
	}
	public class BossDeathNotification : BossEncounterCompleteNotification
	{
		private int _bossesLeft;

		private void Start()
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			HealthManager[] array = BossEncounterCompleteNotification.GetHealthManagers(bossPaths).ToArray();
			_bossesLeft = array.Length;
			HealthManager[] array2 = array;
			foreach (HealthManager val in array2)
			{
				val.OnDeath += (DeathEvent)delegate
				{
					_bossesLeft--;
					PopLogger.Log("Boss death event received....");
					if (_bossesLeft == 0)
					{
						BossDead();
					}
				};
				PopLogger.Log($"Added received death hook for {val}");
			}
		}
	}
	public class BossEncounterCompleteNotification : MonoBehaviour, IEncounterCompletedNotification
	{
		public string[] bossPaths;

		public event Action OnEncounterCompleted;

		private static IEnumerable<HealthManager> FindBossesAutomatic()
		{
			IGrouping<int, HealthManager> grouping = (from x in Object.FindObjectsByType<HealthManager>((FindObjectsSortMode)0)
				orderby x.hp descending
				group x by x.hp).FirstOrDefault();
			if (grouping == null)
			{
				PopLogger.LogError("Could not automatically find boss, set the boss path.");
				return Array.Empty<HealthManager>();
			}
			PopLogger.Log("Found boss automatically: " + string.Join(",", grouping.Select((HealthManager x) => ((Object)x).name)));
			return grouping;
		}

		public static IEnumerable<HealthManager> GetHealthManagers(string[] bossPaths)
		{
			if (bossPaths.Length == 0)
			{
				PopLogger.Log("Boss paths were empty, trying to find automatically...");
				return FindBossesAutomatic();
			}
			return bossPaths.GetComponenFromPaths<HealthManager>();
		}

		protected void BossDead()
		{
			PopLogger.Log("called BossDead()");
			this.OnEncounterCompleted?.Invoke();
		}
	}
	public class BossZeroHPNotification : BossEncounterCompleteNotification
	{
		private HealthManager[] _bosses;

		private bool _triggerd;

		private void Start()
		{
			_bosses = BossEncounterCompleteNotification.GetHealthManagers(bossPaths).ToArray();
		}

		private void Update()
		{
			if (_triggerd)
			{
				return;
			}
			bool flag = true;
			HealthManager[] bosses = _bosses;
			for (int i = 0; i < bosses.Length; i++)
			{
				if (bosses[i].hp > 0)
				{
					flag = false;
					break;
				}
			}
			if (flag)
			{
				_triggerd = true;
				PopLogger.Log("Bosses reached zero hp....");
				BossDead();
			}
		}
	}
	internal class BelleaterDeadNotification : BossEncounterCompleteNotification
	{
		private void Start()
		{
			GameObject obj = GameObjectUtil.FindGameObjectFromScene("Boss Scene/Centipede Control");
			PlayMakerFSM val = ((obj != null) ? FSMUtility.LocateMyFSM(obj, "Control") : null);
			if (val == null)
			{
				PopLogger.LogError("Could not find cetipede control");
				return;
			}
			val.GetState("Bell Best Appear").InsertMethod(0, base.BossDead);
			PopLogger.Log("Patched bellwater");
		}
	}
	internal class CloverDancersDeadNotification : BossEncounterCompleteNotification
	{
		private void Start()
		{
			GameObject obj = GameObjectUtil.FindGameObjectFromScene("Boss Scene/Dancer Control/Dancer A/Corpse Green Prince(Clone)");
			PlayMakerFSM obj2 = ((obj != null) ? FSMUtility.LocateMyFSM(obj, "Death") : null);
			if (obj2 == null)
			{
				PopLogger.Log("could not find corpse control for clover dancers");
			}
			FsmState state = ((RunFSMAction)obj2.GetState("Heart Death").GetAction<RunFSM>()).runFsm.GetState("Return");
			state.RemoveAction<BeginSceneTransition>();
			state.AddMethod(base.BossDead);
		}
	}
	internal class CogworkDancersDeadNotification : BossEncounterCompleteNotification
	{
		private void Start()
		{
			GameObject obj = GameObjectUtil.FindGameObjectFromScene("Dancer Control");
			PlayMakerFSM val = ((obj != null) ? FSMUtility.LocateMyFSM(obj, "Control") : null);
			if (val == null)
			{
				PopLogger.LogError("Could not find last judge corpse fsm");
				return;
			}
			val.GetState("End").InsertMethod(0, base.BossDead);
			PopLogger.Log("patched cogwork dancers");
		}
	}
	internal class ConchflyDeadNotification : BossEncounterCompleteNotification
	{
		private void Start()
		{
			GameObject obj = GameObject.Find("Boss Scene");
			PlayMakerFSM val = ((obj != null) ? FSMUtility.LocateMyFSM(obj, "Control") : null);
			if (val == null)
			{
				PopLogger.Log("Could not find control for conchfly boss scene");
				return;
			}
			val.GetState("Battle End S").InsertMethod(0, base.BossDead);
			val.GetState("Battle End").InsertMethod(0, base.BossDead);
			PopLogger.Log("Patch conchflies");
		}
	}
	internal class FatherDeadNotification : BossEncounterCompleteNotification
	{
		private void Start()
		{
			GameObject obj = GameObject.Find("Boss Scene/Wisp Pyre Effigy");
			PlayMakerFSM val = ((obj != null) ? FSMUtility.LocateMyFSM(obj, "Summon Control") : null);
			if (val == null)
			{
				PopLogger.Log("could not find father");
				return;
			}
			val.GetState("End").InsertMethod(0, base.BossDead);
			PopLogger.Log("patched father");
		}
	}
	internal class FirstSinnerDeadNotification : BossEncounterCompleteNotification
	{
		private void Start()
		{
			GameObject obj = GameObjectUtil.FindGameObjectFromScene("Boss Scene/Shrine First Weaver NPC");
			PlayMakerFSM val = ((obj != null) ? FSMUtility.LocateMyFSM(obj, "Inspection") : null);
			if (val == null)
			{
				PopLogger.LogError("could not finnd first sinner npc");
				return;
			}
			FsmState state = val.GetState("To First Sinner Memory");
			state.Actions = Array.Empty<FsmStateAction>();
			state.InsertMethod(0, base.BossDead);
			PopLogger.Log("patched weaver fsm");
		}
	}
	internal class GrandmotherDeadNotification : BossEncounterCompleteNotification
	{
		private void Start()
		{
			GameObject obj = GameObject.Find("Boss Scene/Death Sequence");
			PlayMakerFSM val = ((obj != null) ? FSMUtility.LocateMyFSM(obj, "Control") : null);
			GameObject obj2 = GameObject.Find("Boss Scene/Death Sequence Cursed");
			PlayMakerFSM val2 = ((obj2 != null) ? FSMUtility.LocateMyFSM(obj2, "Contorl") : null);
			if (val == null || val2 == null)
			{
				PopLogger.LogError("could not find a eath sequence control");
				return;
			}
			val.CreateState("Custom Boss Dead").InsertMethod(0, base.BossDead);
			FsmState state = val.GetState("Idle");
			state.Transitions = Array.Empty<FsmTransition>();
			state.AddTransition("DEATH START", "Custom Boss Dead");
			PopLogger.Log("patched grandmother silk 3");
		}
	}
	internal class LastJudgeDeadNotification : BossEncounterCompleteNotification
	{
		private void Start()
		{
			GameObject obj = GameObjectUtil.FindGameObjectFromScene("Boss Scene/Last Judge/Corpse Last Judge(Clone)");
			PlayMakerFSM val = ((obj != null) ? FSMUtility.LocateMyFSM(obj, "Control") : null);
			if (val == null)
			{
				PopLogger.LogError("Could not find last judge corpse fsm");
				return;
			}
			val.GetState("Break 4").InsertMethod(0, base.BossDead);
			PopLogger.Log("patched last judge");
		}
	}
	internal class LostLaceDeadNotification : BossEncounterCompleteNotification
	{
		private void Start()
		{
			GameObject obj = GameObject.Find("Boss Control/Superjump Sequence");
			PlayMakerFSM fsm = ((obj != null) ? FSMUtility.LocateMyFSM(obj, "Control") : null);
			fsm.CreateState("Custom Boss Dead").InsertMethod(0, base.BossDead);
			FsmState state = fsm.GetState("Crash");
			state.Transitions = Array.Empty<FsmTransition>();
			state.AddTransition("FINISHED", "Custom Boss Dead");
			PopLogger.Log("patched lost lace");
		}
	}
	internal class PhantomDeadNotification : BossEncounterCompleteNotification
	{
		private void Start()
		{
			GameObject obj = GameObject.Find("Boss Scene/Phantom");
			PlayMakerFSM val = ((obj != null) ? FSMUtility.LocateMyFSM(obj, "Control") : null);
			if (val == null)
			{
				PopLogger.LogError("could not finnd phantom");
				return;
			}
			FsmState state = val.GetState("Fade To Black");
			state.GetAction<Wait>().time = FsmFloat.op_Implicit(0f);
			val.CreateState("Custom Boss Dead").InsertMethod(0, base.BossDead);
			state.Transitions = Array.Empty<FsmTransition>();
			state.AddTransition("FINISHED", "Custom Boss Dead");
			PopLogger.Log("patched fsm");
		}
	}
	internal class ShakraDeadNotification : BossEncounterCompleteNotification
	{
		private void Start()
		{
			GameObject obj = GameObjectUtil.FindGameObjectFromScene("Mapper Spar NPC");
			PlayMakerFSM val = ((obj != null) ? FSMUtility.LocateMyFSM(obj, "Dialogue") : null);
			if (val == null)
			{
				PopLogger.LogError("couldnt find dialouge fsm for shakra");
				return;
			}
			FsmState state = val.GetState("Away");
			state.InsertMethod(state.Actions.Length - 1, base.BossDead);
			PopLogger.Log("Patched Unravelled");
		}
	}
	internal class UnravelledDeadNotification : BossEncounterCompleteNotification
	{
		private void Start()
		{
			GameObject obj = GameObject.Find("Boss Scene/Conductor Boss");
			PlayMakerFSM val = ((obj != null) ? FSMUtility.LocateMyFSM(obj, "Control") : null);
			if (val == null)
			{
				PopLogger.LogError("Could not find control for Unravelled");
				return;
			}
			FsmState state = val.GetState("Death Blow");
			state.InsertMethod(state.Actions.Length - 1, base.BossDead);
			PopLogger.Log("Patched Unravelled");
		}
	}
	internal class WidowDeadNotification : BossEncounterCompleteNotification
	{
		private void Start()
		{
			GameObject obj = GameObject.Find("Boss Scene/Spinner Boss");
			PlayMakerFSM val = ((obj != null) ? FSMUtility.LocateMyFSM(obj, "Control") : null);
			if (val == null)
			{
				PopLogger.LogError("could not finnd window");
				return;
			}
			FsmState state = val.GetState("Fade To Black");
			state.GetAction<Wait>(6).time = FsmFloat.op_Implicit(0f);
			val.GetState("Fade").GetAction<Wait>().time = FsmFloat.op_Implicit(0f);
			val.CreateState("Custom Boss Dead").InsertMethod(0, base.BossDead);
			state.Transitions = Array.Empty<FsmTransition>();
			state.AddTransition("FINISHED", "Custom Boss Dead");
			PopLogger.Log("patched fssm");
		}
	}
	public static class EncounterCompletionRegistry
	{
		private static readonly Dictionary<string, Type> _customNotifications = new Dictionary<string, Type>
		{
			{
				"Widow",
				typeof(WidowDeadNotification)
			},
			{
				"Phantom",
				typeof(PhantomDeadNotification)
			},
			{
				"Last Judge",
				typeof(LastJudgeDeadNotification)
			},
			{
				"Cogwork Dancers",
				typeof(CogworkDancersDeadNotification)
			},
			{
				"Double Conchfly",
				typeof(ConchflyDeadNotification)
			},
			{
				"Unravelled",
				typeof(UnravelledDeadNotification)
			},
			{
				"First Sinner",
				typeof(FirstSinnerDeadNotification)
			},
			{
				"Grandmother",
				typeof(GrandmotherDeadNotification)
			},
			{
				"Father of Flame",
				typeof(FatherDeadNotification)
			},
			{
				"Bell Eater",
				typeof(BelleaterDeadNotification)
			},
			{
				"Clover Dancer",
				typeof(CloverDancersDeadNotification)
			},
			{
				"Lost Lace",
				typeof(LostLaceDeadNotification)
			},
			{
				"Bench",
				typeof(BenchTransitionNotification)
			},
			{
				"Shakra",
				typeof(ShakraDeadNotification)
			}
		};

		public static IEncounterCompletedNotification AddEncounterCompletion(GameObject root, Encounter encounter)
		{
			IEncounterCompletedNotification encounterCompletedNotification = null;
			if (_customNotifications.TryGetValue(encounter.Name, out var value))
			{
				return root.AddComponent(value) as IEncounterCompletedNotification;
			}
			if (encounter.SpecialDeath)
			{
				BossZeroHPNotification bossZeroHPNotification = root.AddComponent<BossZeroHPNotification>();
				bossZeroHPNotification.bossPaths = encounter.BossPathFromRoot;
				return bossZeroHPNotification;
			}
			BossDeathNotification bossDeathNotification = root.AddComponent<BossDeathNotification>();
			bossDeathNotification.bossPaths = encounter.BossPathFromRoot;
			return bossDeathNotification;
		}
	}
	public interface IEncounterCompletedNotification
	{
		event Action OnEncounterCompleted;
	}
	public static class BossLists
	{
		private static readonly string BossListsDir = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "boss_list");

		private static readonly string[] _defaultPharloomBosses = new string[13]
		{
			"Moss Mother", "Skull Tyrant", "Bell Beast", "Savage Beastfly", "Fourth Chorus", "Fire Lace", "Bench", "Double Conchfly", "Moorwing", "Sister Splinter",
			"Widow", "Phantom", "Last Judge"
		};

		private static readonly string[] _defaultCitadelBosses = new string[20]
		{
			"Garmond and Zaza", "Cogwork Dancers", "Trobbio", "Chef Lugoli", "Broodmother", "Groal", "Bench", "Moss Mother 2", "Single Conchfly", "Zango",
			"Voltvyrm", "Savage Beastfly 2", "Shakra", "Bench", "Father of Flame", "Signis & Gron", "Second Sentinel", "Unravelled", "Flower Lace", "First Sinner"
		};

		private static readonly string[] _defaultAbyssBosses = new string[17]
		{
			"Bell Eater", "Crawfather", "Gurr", "Lost Garmond", "Pinstress", "Watcher", "Tormented Trobbio", "Bench", "Palestag", "Clover Dancer",
			"Seth", "Nyleth", "Khann", "Kramelita", "Bench", "Grandmother", "Lost Lace"
		};

		private static string[] PharloomBosses;

		private static string[] CitadelBosses;

		private static string[] AbyssBosses;

		private static string[] SilksongBosses;

		public static Encounter[] PharloomEncounters => PharloomBosses.Select((string x) => BossRegistry.EncounterByName[x]).ToArray();

		public static Encounter[] CitadelEncounters => CitadelBosses.Select((string x) => BossRegistry.EncounterByName[x]).ToArray();

		public static Encounter[] AbyssEncounters => AbyssBosses.Select((string x) => BossRegistry.EncounterByName[x]).ToArray();

		public static Encounter[] SilksongEncounters => SilksongBosses.Select((string x) => BossRegistry.EncounterByName[x]).ToArray();

		public static void Initialize()
		{
			PharloomBosses = LoadBossList("act1.txt", _defaultPharloomBosses);
			CitadelBosses = LoadBossList("act2.txt", _defaultCitadelBosses);
			AbyssBosses = LoadBossList("act3.txt", _defaultAbyssBosses);
			SilksongBosses = PharloomBosses.Concat(new string[1] { "Bench" }).Concat(CitadelBosses).Concat(new string[1] { "Bench" })
				.Concat(AbyssBosses)
				.ToArray();
		}

		private static string[] LoadBossList(string fileName, string[] fallback)
		{
			string text = Path.Combine(BossListsDir, fileName);
			PopLogger.Log("trying to find file path: " + text);
			if (!File.Exists(text))
			{
				return fallback;
			}
			try
			{
				string[] array = (from l in File.ReadAllLines(text)
					select l.Trim() into l
					where !string.IsNullOrEmpty(l) && !l.StartsWith("#")
					select l).ToArray();
				return (array.Length != 0) ? array : fallback;
			}
			catch
			{
				return fallback;
			}
		}
	}
	public struct Encounter
	{
		public string Name { get; init; }

		public SceneLoadInfo SceneInfo { get; init; }

		public Action BeforeEnter { get; init; }

		public Action AfterEnter { get; init; }

		public Action OnExit { get; init; }

		public Action AfterExit { get; init; }

		public bool IsSafe { get; init; }

		public string[] BossPathFromRoot { get; init; }

		public bool SpecialDeath { get; init; }

		public float TransitionDelay { get; init; }

		public Vector2? CustomSpawnPoint { get; init; }

		public bool SkipTeleport { get; init; }

		public Action<HealthManager> ScaleHealth { get; init; }

		public Encounter()
		{
			Name = null;
			SceneInfo = null;
			BeforeEnter = null;
			AfterEnter = null;
			OnExit = null;
			AfterExit = null;
			IsSafe = false;
			CustomSpawnPoint = null;
			ScaleHealth = null;
			BossPathFromRoot = new string[0];
			SpecialDeath = false;
			TransitionDelay = 5f;
			SkipTeleport = false;
		}
	}
	public struct BossInfo
	{
		public string Name { get; init; }

		public string JournalRecordName { get; init; }

		public List<Encounter> Encounters { get; init; }
	}
	public static class BossRegistry
	{
		private enum NailType
		{
			Old,
			Sharpened,
			Shining,
			Hivesteel,
			Palesteel
		}

		private static Action<HealthManager> ScaleToOldNail = delegate(HealthManager hm)
		{
			ScaleToNail(hm, NailType.Old);
		};

		private static Action<HealthManager> ScaleToSharpenedNail = delegate(HealthManager hm)
		{
			ScaleToNail(hm, NailType.Sharpened);
		};

		private static Action<HealthManager> ScaleToShiningNail = delegate(HealthManager hm)
		{
			ScaleToNail(hm, NailType.Shining);
		};

		private static Action<HealthManager> ScaleToHivesteelNail = delegate(HealthManager hm)
		{
			ScaleToNail(hm, NailType.Hivesteel);
		};

		public static List<BossInfo> BossInfos = new List<BossInfo>
		{
			new BossInfo
			{
				Name = "Mossbone Mother",
				JournalRecordName = "Mossbone Mother",
				Encounters = new List<Encounter>
				{
					new Encounter
					{
						Name = "Moss Mother",
						SceneInfo = new SceneLoadInfo
						{
							SceneName = "Tut_03",
							EntryGateName = "right1",
							Visualization = (SceneLoadVisualizations)2,
							PreventCameraFadeOut = false
						},
						BeforeEnter = delegate
						{
							PlayerData.instance.defeatedMossMother = false;
							PlayerData.instance.encounteredMossMother = false;
						},
						AfterEnter = delegate
						{
							GameObject obj5 = GameObjectUtil.FindGameObjectFromScene("Black Thread States/Normal World/Battle Scene/Wave 1");
							if (obj5 != null)
							{
								GameObject gameObject2 = obj5.gameObject;
								if (gameObject2 != null)
								{
									gameObject2.SetActive(true);
								}
							}
						},
						OnExit = delegate
						{
							PlayerData.instance.encounteredMossMother = true;
							PlayerData.instance.defeatedMossMother = true;
						},
						BossPathFromRoot = new string[1] { "Black Thread States/Normal World/Battle Scene/Wave 1/Mossbone Mother" },
						ScaleHealth = ScaleToOldNail
					},
					new Encounter
					{
						Name = "Moss Mother 2",
						SceneInfo = new SceneLoadInfo
						{
							SceneName = "Weave_03",
							EntryGateName = "right1"
						},
						BeforeEnter = delegate
						{
							if (((PersistentItemDataCollection<bool, SerializableBoolData>)(object)SceneData.instance.persistentBools).scenes["Weave_03"].TryGetValue("Boss Scene", out var value5))
							{
								value5.Value = false;
							}
						},
						CustomSpawnPoint = new Vector2(15f, 21f),
						ScaleHealth = ScaleToSharpenedNail
					}
				}
			},
			new BossInfo
			{
				Name = "Skull King",
				JournalRecordName = "Skull King",
				Encounters = new List<Encounter>
				{
					new Encounter
					{
						Name = "Skull Tyrant",
						SceneInfo = new SceneLoadInfo
						{
							SceneName = "Bone_15",
							EntryGateName = "left1"
						},
						BeforeEnter = delegate
						{
						},
						OnExit = delegate
						{
						},
						BossPathFromRoot = new string[1] { "Boss Scene/Skull King" },
						ScaleHealth = ScaleToShiningNail
					}
				}
			},
			new BossInfo
			{
				Name = "Bone Flyer Giant",
				JournalRecordName = "Bone Flyer Giant",
				Encounters = new List<Encounter>
				{
					new Encounter
					{
						Name = "Savage Beastfly",
						SceneInfo = new SceneLoadInfo
						{
							SceneName = "Ant_19",
							EntryGateName = "left1",
							Visualization = (SceneLoadVisualizations)0,
							PreventCameraFadeOut = false
						},
						BeforeEnter = delegate
						{
							PlayerData.instance.defeatedBoneFlyerGiant = false;
						},
						OnExit = delegate
						{
							PlayerData.instance.defeatedBoneFlyerGiant = true;
						},
						BossPathFromRoot = new string[1] { "Boss Control/Boss Scene/Bone Flyer Giant" },
						CustomSpawnPoint = new Vector2(63f, 34.6f),
						ScaleHealth = ScaleToSharpenedNail
					},
					new Encounter
					{
						Name = "Savage Beastfly 2",
						SceneInfo = new SceneLoadInfo
						{
							SceneName = "Bone_East_08",
							EntryGateName = "right1"
						},
						BeforeEnter = delegate
						{
							//IL_000f: Unknown result type (might be due to invalid IL or missing references)
							((SerializableNamedList<Completion, NamedCompletion>)(object)PlayerData.instance.QuestCompletionData).SetData("Beastfly Hunt", QuestCompletionData.Accepted);
							CacheUtils.CachePlayerDataBools("defeatedBoneFlyerGiantGolemScene", "defeatedSongGolem");
							PlayerData.instance.defeatedBoneFlyerGiantGolemScene = false;
							PlayerData.instance.defeatedSongGolem = true;
						},
						OnExit = delegate
						{
							CacheUtils.Restore();
						},
						BossPathFromRoot = new string[1] { "Boss Scene Beastfly/Beastfly States/Active/Bone Flyer Giant" },
						CustomSpawnPoint = new Vector2(82f, 8f),
						ScaleHealth = ScaleToShiningNail
					}
				}
			},
			new BossInfo
			{
				Name = "Bone Beast",
				JournalRecordName = "Bone Beast",
				Encounters = new List<Encounter>
				{
					new Encounter
					{
						Name = "Bell Beast",
						SceneInfo = new SceneLoadInfo
						{
							SceneName = "Bone_05",
							EntryGateName = "left1",
							Visualization = (SceneLoadVisualizations)2,
							PreventCameraFadeOut = false
						},
						BeforeEnter = delegate
						{
							PlayerData.instance.defeatedBellBeast = false;
							PlayerData.instance.encounteredBellBeast = true;
						},
						OnExit = delegate
						{
							PlayerData.instance.defeatedBellBeast = true;
						},
						BossPathFromRoot = new string[1] { "Boss Scene/Bone Beast" },
						CustomSpawnPoint = new Vector2(83f, 4f),
						ScaleHealth = ScaleToOldNail
					}
				}
			},
			new BossInfo
			{
				Name = "Dock Guard Thrower",
				JournalRecordName = "Dock Guard Thrower",
				Encounters = new List<Encounter>
				{
					new Encounter
					{
						Name = "Signis & Gron",
						SceneInfo = new SceneLoadInfo
						{
							SceneName = "Dock_09",
							EntryGateName = "right1"
						},
						BeforeEnter = delegate
						{
						},
						OnExit = delegate
						{
						},
						BossPathFromRoot = new string[2] { "Boss Scene/Dock Guard Slasher", "Boss Scene/Dock Guard Thrower" },
						SpecialDeath = true,
						CustomSpawnPoint = new Vector2(40f, 8f),
						ScaleHealth = ScaleToHivesteelNail
					}
				}
			},
			new BossInfo
			{
				Name = "Song Golem",
				JournalRecordName = "Song Golem",
				Encounters = new List<Encounter>
				{
					new Encounter
					{
						Name = "Fourth Chorus",
						SceneInfo = new SceneLoadInfo
						{
							SceneName = "Bone_East_08",
							EntryGateName = "right1"
						},
						BeforeEnter = delegate
						{
						},
						OnExit = delegate
						{
						},
						BossPathFromRoot = new string[1] { "Boss Scene/song_golem/Song_Butt/SG_waist/Torso/SG_head" },
						SpecialDeath = true,
						ScaleHealth = ScaleToOldNail
					}
				}
			},
			new BossInfo
			{
				Name = "Bone Hunter Trapper",
				JournalRecordName = "Bone Hunter Trapper",
				Encounters = new List<Encounter>
				{
					new Encounter
					{
						Name = "Gurr",
						SceneInfo = new SceneLoadInfo
						{
							SceneName = "Bone_East_18b",
							EntryGateName = "top1"
						},
						BeforeEnter = delegate
						{
							PlayerData.instance.encounteredAntTrapper = true;
						},
						OnExit = delegate
						{
						}
					}
				}
			},
			new BossInfo
			{
				Name = "Hunter Queen",
				JournalRecordName = "Hunter Queen",
				Encounters = new List<Encounter>
				{
					new Encounter
					{
						Name = "Kramelita",
						SceneInfo = new SceneLoadInfo
						{
							SceneName = "Memory_Ant_Queen",
							EntryGateName = "door_wakeInMemory",
							Visualization = (SceneLoadVisualizations)2,
							PreventCameraFadeOut = false
						},
						BeforeEnter = delegate
						{
							PlayerData.instance.defeatedAntQueen = false;
						},
						OnExit = delegate
						{
							PlayerData.instance.defeatedAntQueen = true;
						}
					}
				}
			},
			new BossInfo
			{
				Name = "Vampire Gnat",
				JournalRecordName = "Vampire Gnat",
				Encounters = new List<Encounter>
				{
					new Encounter
					{
						Name = "Moorwing",
						SceneInfo = new SceneLoadInfo
						{
							SceneName = "Greymoor_08",
							EntryGateName = "top1",
							Visualization = (SceneLoadVisualizations)0,
							PreventCameraFadeOut = true
						},
						BeforeEnter = delegate
						{
							PlayerData.instance.defeatedVampireGnatBoss = false;
						},
						OnExit = delegate
						{
							PlayerData.instance.defeatedVampireGnatBoss = true;
						},
						BossPathFromRoot = new string[1] { "Vampire Gnat Scene/Vampire Gnat" },
						ScaleHealth = ScaleToOldNail
					}
				}
			},
			new BossInfo
			{
				Name = "Wisp Pyre Effigy",
				JournalRecordName = "Wisp Pyre Effigy",
				Encounters = new List<Encounter>
				{
					new Encounter
					{
						Name = "Father of Flame",
						SceneInfo = new SceneLoadInfo
						{
							SceneName = "Belltown_08",
							EntryGateName = "right1"
						},
						BeforeEnter = delegate
						{
						},
						OnExit = delegate
						{
						},
						TransitionDelay = 0f,
						CustomSpawnPoint = new Vector2(67f, 12f)
					}
				}
			},
			new BossInfo
			{
				Name = "Crawfather",
				JournalRecordName = "Crawfather",
				Encounters = new List<Encounter>
				{
					new Encounter
					{
						Name = "Crawfather",
						SceneInfo = new SceneLoadInfo
						{
							SceneName = "Room_CrowCourt_02",
							EntryGateName = "top1"
						},
						BeforeEnter = delegate
						{
							PlayerData.instance.encounteredCrowCourt = true;
						},
						OnExit = delegate
						{
						}
					}
				}
			},
			new BossInfo
			{
				Name = "Roachkeeper Chef",
				JournalRecordName = "Roachkeeper Chef",
				Encounters = new List<Encounter>
				{
					new Encounter
					{
						Name = "Chef Lugoli",
						SceneInfo = new SceneLoadInfo
						{
							SceneName = "Dust_Chef",
							EntryGateName = "left1"
						},
						BeforeEnter = delegate
						{
						},
						OnExit = delegate
						{
						},
						ScaleHealth = ScaleToShiningNail
					}
				}
			},
			new BossInfo
			{
				Name = "Swamp Shaman",
				JournalRecordName = "Swamp Shaman",
				Encounters = new List<Encounter>
				{
					new Encounter
					{
						Name = "Groal",
						SceneInfo = new SceneLoadInfo
						{
							SceneName = "Shadow_18",
							EntryGateName = "right1"
						},
						BeforeEnter = delegate
						{
						},
						OnExit = delegate
						{
						},
						SpecialDeath = true,
						CustomSpawnPoint = new Vector2(55f, 12f)
					}
				}
			},
			new BossInfo
			{
				Name = "Splinter Queen",
				JournalRecordName = "Splinter Queen",
				Encounters = new List<Encounter>
				{
					new Encounter
					{
						Name = "Sister Splinter",
						SceneInfo = new SceneLoadInfo
						{
							SceneName = "Shellwood_18",
							EntryGateName = "right1"
						},
						BeforeEnter = delegate
						{
						},
						OnExit = delegate
						{
						},
						BossPathFromRoot = new string[1] { "Boss Scene Parent/Boss Scene/Splinter Queen" },
						ScaleHealth = ScaleToOldNail
					}
				}
			},
			new BossInfo
			{
				Name = "Seth",
				JournalRecordName = "Seth",
				Encounters = new List<Encounter>
				{
					new Encounter
					{
						Name = "Seth",
						SceneInfo = new SceneLoadInfo
						{
							SceneName = "Shellwood_22",
							EntryGateName = "right1"
						},
						BeforeEnter = delegate
						{
						},
						OnExit = delegate
						{
						}
					}
				}
			},
			new BossInfo
			{
				Name = "Flower Queen",
				JournalRecordName = "Flower Queen",
				Encounters = new List<Encounter>
				{
					new Encounter
					{
						Name = "Nyleth",
						SceneInfo = new SceneLoadInfo
						{
							SceneName = "Shellwood_11b_Memory",
							EntryGateName = "door_wakeInMemory"
						},
						BeforeEnter = delegate
						{
						},
						OnExit = delegate
						{
						},
						CustomSpawnPoint = new Vector2(18f, 110f)
					}
				}
			},
			new BossInfo
			{
				Name = "Last Judge",
				JournalRecordName = "Last Judge",
				Encounters = new List<Encounter>
				{
					new Encounter
					{
						Name = "Last Judge",
						SceneInfo = new SceneLoadInfo
						{
							SceneName = "Coral_Judge_Arena",
							EntryGateName = "left1"
						},
						BeforeEnter = delegate
						{
							GameManager.instance.playerData.bellShrineBellhart = true;
							GameManager.instance.playerData.bellShrineEnclave = true;
							GameManager.instance.playerData.bellShrineGreymoor = true;
							GameManager.instance.playerData.bellShrineShellwood = true;
							GameManager.instance.playerData.bellShrineWilds = true;
							GameManager.instance.playerData.bellShrineBoneForest = true;
							GameManager.instance.playerData.encounteredLastJudge = true;
							GameManager.instance.playerData.defeatedLastJudge = false;
							if (((PersistentItemDataCollection<bool, SerializableBoolData>)(object)SceneData.instance.persistentBools).scenes["Coral_Judge_Arena"].TryGetValue("Last Judge", out var value4))
							{
								value4.Value = false;
							}
						},
						OnExit = delegate
						{
						},
						BossPathFromRoot = new string[1] { "Boss Scene/Last Judge" },
						TransitionDelay = 0f,
						CustomSpawnPoint = new Vector2(25f, 25f),
						ScaleHealth = ScaleToSharpenedNail
					}
				}
			},
			new BossInfo
			{
				Name = "Coral Conch Driller Giant",
				JournalRecordName = "Coral Conch Driller Giant",
				Encounters = new List<Encounter>
				{
					new Encounter
					{
						Name = "Single Conchfly",
						SceneInfo = new SceneLoadInfo
						{
							SceneName = "Coral_27",
							EntryGateName = "left1"
						},
						BeforeEnter = delegate
						{
						},
						OnExit = delegate
						{
						},
						CustomSpawnPoint = new Vector2(20f, 34f)
					},
					new Encounter
					{
						Name = "Double Conchfly",
						SceneInfo = new SceneLoadInfo
						{
							SceneName = "Coral_11",
							EntryGateName = "left1"
						},
						BeforeEnter = delegate
						{
						},
						OnExit = delegate
						{
						},
						TransitionDelay = 0f,
						CustomSpawnPoint = new Vector2(60f, 15f),
						ScaleHealth = ScaleToSharpenedNail
					}
				}
			},
			new BossInfo
			{
				Name = "Coral Warrior Grey",
				JournalRecordName = "Coral Warrior Grey",
				Encounters = new List<Encounter>
				{
					new Encounter
					{
						Name = "Watcher",
						SceneInfo = new SceneLoadInfo
						{
							SceneName = "Coral_39",
							EntryGateName = "right1"
						},
						BeforeEnter = delegate
						{
						},
						OnExit = delegate
						{
						}
					}
				}
			},
			new BossInfo
			{
				Name = "Coral King",
				JournalRecordName = "Coral King",
				Encounters = new List<Encounter>
				{
					new Encounter
					{
						Name = "Khann",
						SceneInfo = new SceneLoadInfo
						{
							SceneName = "Memory_Coral_Tower",
							EntryGateName = "door_wakeInMemory"
						},
						BeforeEnter = delegate
						{
						},
						OnExit = delegate
						{
						},
						SpecialDeath = true
					}
				}
			},
			new BossInfo
			{
				Name = "Song Knight",
				JournalRecordName = "Song Knight",
				Encounters = new List<Encounter>
				{
					new Encounter
					{
						Name = "Second Sentinel",
						SceneInfo = new SceneLoadInfo
						{
							SceneName = "Hang_17b",
							EntryGateName = "left1"
						},
						BeforeEnter = delegate
						{
						},
						OnExit = delegate
						{
						},
						CustomSpawnPoint = new Vector2(32f, 5f),
						ScaleHealth = ScaleToShiningNail
					}
				}
			},
			new BossInfo
			{
				Name = "Conductor Boss",
				JournalRecordName = "Conductor Boss",
				Encounters = new List<Encounter>
				{
					new Encounter
					{
						Name = "Unravelled",
						SceneInfo = new SceneLoadInfo
						{
							SceneName = "Ward_02",
							EntryGateName = "right1"
						},
						BeforeEnter = delegate
						{
							GameManager.instance.playerData.collectedWardBossKey = true;
						},
						OnExit = delegate
						{
						},
						TransitionDelay = 0f
					}
				}
			},
			new BossInfo
			{
				Name = "Clockwork Dancer",
				JournalRecordName = "Clockwork Dancer",
				Encounters = new List<Encounter>
				{
					new Encounter
					{
						Name = "Cogwork Dancers",
						SceneInfo = new SceneLoadInfo
						{
							SceneName = "Cog_Dancers",
							EntryGateName = "left1"
						},
						BeforeEnter = delegate
						{
						},
						OnExit = delegate
						{
						},
						TransitionDelay = 0f,
						ScaleHealth = ScaleToSharpenedNail
					}
				}
			},
			new BossInfo
			{
				Name = "Trobbio",
				JournalRecordName = "Trobbio",
				Encounters = new List<Encounter>
				{
					new Encounter
					{
						Name = "Trobbio",
						SceneInfo = new SceneLoadInfo
						{
							SceneName = "Library_13",
							EntryGateName = "left1"
						},
						BeforeEnter = delegate
						{
							PlayerData.instance.encounteredTrobbio = true;
						},
						OnExit = delegate
						{
						},
						BossPathFromRoot = new string[1] { "Grand Stage Scene/Boss Scene Trobbio/Trobbio" },
						SpecialDeath = true,
						ScaleHealth = ScaleToShiningNail
					}
				}
			},
			new BossInfo
			{
				Name = "Tormented Trobbio",
				JournalRecordName = "Tormented Trobbio",
				Encounters = new List<Encounter>
				{
					new Encounter
					{
						Name = "Tormented Trobbio",
						SceneInfo = new SceneLoadInfo
						{
							SceneName = "Library_13",
							EntryGateName = "left1"
						},
						BeforeEnter = delegate
						{
							PlayerData.instance.blackThreadWorld = true;
							PlayerData.instance.encounteredTormentedTrobbio = true;
						},
						AfterEnter = delegate
						{
							GameObject obj4 = GameObjectUtil.FindGameObjectFromScene("Grand Stage Scene/Boss Scene TormentedTrobbio");
							if (obj4 != null)
							{
								obj4.SetActive(true);
							}
						},
						OnExit = delegate
						{
						},
						BossPathFromRoot = new string[1] { "Grand Stage Scene/Boss Scene TormentedTrobbio/Tormented Trobbio" },
						CustomSpawnPoint = new Vector2(64f, 15f)
					}
				}
			},
			new BossInfo
			{
				Name = "Slab Fly Broodmother",
				JournalRecordName = "Slab Fly Broodmother",
				Encounters = new List<Encounter>
				{
					new Encounter
					{
						Name = "Broodmother",
						SceneInfo = new SceneLoadInfo
						{
							SceneName = "Slab_16b",
							EntryGateName = "left1"
						},
						BeforeEnter = delegate
						{
						},
						OnExit = delegate
						{
						},
						CustomSpawnPoint = new Vector2(60f, 6f)
					}
				}
			},
			new BossInfo
			{
				Name = "Cloverstag White",
				JournalRecordName = "Cloverstag White",
				Encounters = new List<Encounter>
				{
					new Encounter
					{
						Name = "Palestag",
						SceneInfo = new SceneLoadInfo
						{
							SceneName = "Clover_19",
							EntryGateName = "left1"
						},
						BeforeEnter = delegate
						{
						},
						OnExit = delegate
						{
						}
					}
				}
			},
			new BossInfo
			{
				Name = "Clover Dancer",
				JournalRecordName = "Clover Dancer",
				Encounters = new List<Encounter>
				{
					new Encounter
					{
						Name = "Clover Dancer",
						SceneInfo = new SceneLoadInfo
						{
							SceneName = "Clover_10",
							EntryGateName = "left1"
						},
						BeforeEnter = delegate
						{
							if (((PersistentItemDataCollection<bool, SerializableBoolData>)(object)SceneData.instance.persistentBools).scenes["Clover_10"].TryGetValue("Dancer A", out var value3))
							{
								value3.Value = false;
							}
						},
						OnExit = delegate
						{
						},
						TransitionDelay = 0f,
						BossPathFromRoot = new string[1] { "Boss Scene/Dancer Control/Dancer A" },
						CustomSpawnPoint = new Vector2(93f, 38f)
					}
				}
			},
			new BossInfo
			{
				Name = "Giant Centipede",
				JournalRecordName = "Giant Centipede",
				Encounters = new List<Encounter>
				{
					new Encounter
					{
						Name = "Bell Eater",
						SceneInfo = new SceneLoadInfo
						{
							SceneName = "Bellway_Centipede_Arena",
							EntryGateName = "top1"
						},
						BeforeEnter = delegate
						{
						},
						OnExit = delegate
						{
						},
						BossPathFromRoot = new string[2] { "Boss Scene/Giant Centipede Butt", "Boss Scene/Giant Centipede Head" },
						TransitionDelay = 0f
					}
				}
			},
			new BossInfo
			{
				Name = "Pinstress Boss",
				JournalRecordName = "Pinstress Boss",
				Encounters = new List<Encounter>
				{
					new Encounter
					{
						Name = "Pinstress",
						SceneInfo = new SceneLoadInfo
						{
							SceneName = "Peak_07",
							EntryGateName = "top2"
						},
						BeforeEnter = delegate
						{
							//IL_000f: Unknown result type (might be due to invalid IL or missing references)
							((SerializableNamedList<Completion, NamedCompletion>)(object)PlayerData.instance.QuestCompletionData).SetData("Pinstress Battle", QuestCompletionData.Accepted);
							CacheUtils.CachePlayerDataBools("blackThreadWorld");
							PlayerData.instance.blackThreadWorld = true;
						},
						AfterEnter = delegate
						{
							GameObject obj3 = GameObjectUtil.FindGameObjectFromScene("Pinstress Control/Pinstress Scene/Pinstress Boss/NPC");
							FsmState state = ((obj3 != null) ? FSMUtility.LocateMyFSM(obj3, "NPC Control") : null).GetState("Wake 3");
							state.Transitions = Array.Empty<FsmTransition>();
							state.AddTransition("FINISHED", "Battle Start");
						},
						OnExit = delegate
						{
							CacheUtils.Restore();
						},
						SpecialDeath = true,
						TransitionDelay = 2f
					}
				}
			},
			new BossInfo
			{
				Name = "Spinner Boss",
				JournalRecordName = "Spinner Boss",
				Encounters = new List<Encounter>
				{
					new Encounter
					{
						Name = "Widow",
						SceneInfo = new SceneLoadInfo
						{
							SceneName = "Belltown_Shrine",
							EntryGateName = "top1"
						},
						BeforeEnter = delegate
						{
							PlayerData.instance.encounteredSpinner = true;
							PlayerData.instance.bellShrineBellhart = false;
							if (((PersistentItemDataCollection<int, SerializableIntData>)(object)SceneData.instance.persistentInts).scenes["Belltown_Shrine"].TryGetValue("Bellshrine Sequence Bellhart", out var value2))
							{
								value2.Value = 0;
							}
						},
						AfterEnter = delegate
						{
						},
						OnExit = delegate
						{
						},
						BossPathFromRoot = new string[1] { "Black Thread States Thread Only Variant/Normal World/Boss Scene/Spinner Boss" },
						TransitionDelay = 0f,
						CustomSpawnPoint = new Vector2(49f, 28f),
						ScaleHealth = ScaleToOldNail
					}
				}
			},
			new BossInfo
			{
				Name = "First Weaver",
				JournalRecordName = "First Weaver",
				Encounters = new List<Encounter>
				{
					new Encounter
					{
						Name = "First Sinner",
						SceneInfo = new SceneLoadInfo
						{
							SceneName = "Slab_10b",
							EntryGateName = "left1"
						},
						BeforeEnter = delegate
						{
						},
						OnExit = delegate
						{
						},
						CustomSpawnPoint = new Vector2(38f, 10f),
						TransitionDelay = 0f,
						ScaleHealth = ScaleToShiningNail
					}
				}
			},
			new BossInfo
			{
				Name = "Phantom",
				JournalRecordName = "Phantom",
				Encounters = new List<Encounter>
				{
					new Encounter
					{
						Name = "Phantom",
						SceneInfo = new SceneLoadInfo
						{
							SceneName = "Organ_01",
							EntryGateName = "left1"
						},
						BeforeEnter = delegate
						{
							PlayerData.instance.encounteredPhantom = true;
						},
						OnExit = delegate
						{
							PopLogger.Log("repatched time scale");
						},
						BossPathFromRoot = new string[1] { "Boss Scene/Phantom" },
						TransitionDelay = 0f,
						ScaleHealth = ScaleToSharpenedNail
					}
				}
			},
			new BossInfo
			{
				Name = "Lace",
				JournalRecordName = "Lace",
				Encounters = new List<Encounter>
				{
					new Encounter
					{
						Name = "Fire Lace",
						SceneInfo = new SceneLoadInfo
						{
							SceneName = "Bone_East_12",
							EntryGateName = "bot1",
							Visualization = (SceneLoadVisualizations)2,
							PreventCameraFadeOut = false
						},
						BeforeEnter = delegate
						{
							PlayerData.instance.defeatedLace1 = false;
							PlayerData.instance.encounteredLace1 = true;
							PlayerData.instance.encounteredLace1Grotto = false;
							PlayerData.instance.encounteredLaceBlastedBridge = false;
						},
						OnExit = delegate
						{
							PlayerData.instance.defeatedLace1 = true;
						},
						BossPathFromRoot = new string[1] { "Boss Scene/Lace Boss1" },
						CustomSpawnPoint = new Vector2(86f, 8f),
						ScaleHealth = ScaleToOldNail
					},
					new Encounter
					{
						Name = "Flower Lace",
						SceneInfo = new SceneLoadInfo
						{
							SceneName = "Song_Tower_01",
							EntryGateName = "door_cutsceneEndLaceTower"
						},
						BeforeEnter = delegate
						{
							PlayerData.instance.encounteredLaceTower = true;
						},
						OnExit = delegate
						{
						},
						SkipTeleport = true,
						ScaleHealth = ScaleToShiningNail
					}
				}
			},
			new BossInfo
			{
				Name = "Silk Boss",
				JournalRecordName = "Silk Boss",
				Encounters = new List<Encounter>
				{
					new Encounter
					{
						Name = "Grandmother",
						SceneInfo = new SceneLoadInfo
						{
							SceneName = "Cradle_03",
							EntryGateName = "right2"
						},
						BeforeEnter = delegate
						{
						},
						OnExit = delegate
						{
							//IL_000a: Unknown result type (might be due to invalid IL or missing references)
							HeroController.instance.rb2d.linearVelocity = Vector2.zero;
						},
						AfterExit = delegate
						{
							FSMUtility.LocateMyFSM(((Component)((Component)GameCameras.instance.hudCamera).transform.Find("In-game/Anchor TL/Hud Canvas Offset/Hud Canvas")).gameObject, "Slide Out").SendEvent("IN");
							PlayerData.instance.isInvincible = false;
							PopLogger.Log("did grandmother changes");
						},
						TransitionDelay = 0f,
						CustomSpawnPoint = new Vector2(38f, 134f),
						ScaleHealth = ScaleToShiningNail
					}
				}
			},
			new BossInfo
			{
				Name = "Lost Lace",
				JournalRecordName = "Lost Lace",
				Encounters = new List<Encounter>
				{
					new Encounter
					{
						Name = "Lost Lace",
						SceneInfo = new SceneLoadInfo
						{
							SceneName = "Abyss_Cocoon",
							EntryGateName = "door_entry",
							Visualization = (SceneLoadVisualizations)0,
							PreventCameraFadeOut = true
						},
						BeforeEnter = delegate
						{
							PlayerData.instance.EncounteredLostLace = true;
						},
						OnExit = delegate
						{
							Transform obj2 = HeroController.instance.transform.Find("Hornet Dummy");
							if (obj2 != null)
							{
								GameObject gameObject = ((Component)obj2).gameObject;
								if (gameObject != null)
								{
									gameObject.SetActive(false);
								}
							}
						},
						TransitionDelay = 0f
					}
				}
			},
			new BossInfo
			{
				Name = "Shakra",
				JournalRecordName = "Shakra",
				Encounters = new List<Encounter>
				{
					new Encounter
					{
						Name = "Shakra",
						SceneInfo = new SceneLoadInfo
						{
							SceneName = "Greymoor_08",
							EntryGateName = "left2"
						},
						BeforeEnter = delegate
						{
							PlayerData.instance.mapperMentorConvo = true;
							PlayerData.instance.mapperSparIntro = true;
						},
						AfterEnter = delegate
						{
							EventRegister.SendEvent("MAPPER CALL", (GameObject)null);
							GameObject obj = GameObjectUtil.FindGameObjectFromScene("Mapper Spar NPC");
							PlayMakerFSM fsm = ((obj != null) ? FSMUtility.LocateMyFSM(obj, "Dialogue") : null);
							if (fsm == null)
							{
								PopLogger.Log("start was null");
							}
							else
							{
								((MonoBehaviour)GameManager.instance).StartCoroutine(WaitForState());
							}
							IEnumerator WaitForState()
							{
								PopLogger.Log("waiting for state....");
								yield return (object)new WaitUntil((Func<bool>)(() => fsm.ActiveStateName == "Idle"));
								yield return (object)new WaitForEndOfFrame();
								fsm.SetState("Start Battle");
							}
						},
						SpecialDeath = true,
						TransitionDelay = 0f,
						ScaleHealth = ScaleToShiningNail
					}
				}
			},
			new BossInfo
			{
				Name = "Zap Core Enemy",
				JournalRecordName = "Zap Core Enemy",
				Encounters = new List<Encounter>
				{
					new Encounter
					{
						Name = "Voltvyrm",
						SceneInfo = new SceneLoadInfo
						{
							SceneName = "Coral_29",
							EntryGateName = "left1"
						},
						SpecialDeath = true,
						ScaleHealth = ScaleToHivesteelNail
					}
				}
			},
			new BossInfo
			{
				Name = "Garmond",
				JournalRecordName = "Garmond",
				Encounters = new List<Encounter>
				{
					new Encounter
					{
						Name = "Garmond and Zaza",
						SceneInfo = new SceneLoadInfo
						{
							SceneName = "Library_09",
							EntryGateName = "left1"
						},
						AfterEnter = delegate
						{
							((MonoBehaviour)GameManager.instance).StartCoroutine(Wait());
							static IEnumerator Wait()
							{
								GameObject go = GameObjectUtil.FindGameObjectFromScene("Black Thread States/Normal World/Scene Control/Garmond Scene/Garmond Fighter/Citadel Library NPC");
								if (go == null)
								{
									PopLogger.Log("garmond go was null");
								}
								else
								{
									yield return (object)new WaitUntil((Func<bool>)(() => go.activeSelf));
									FSMUtility.LocateMyFSM(go, "Dialogue").SetState("Battle Start");
									PopLogger.Log("set fsm to start battle");
								}
							}
						},
						BeforeEnter = delegate
						{
							GameManager.instance.playerData.garmondInLibrary = true;
						},
						SpecialDeath = true,
						TransitionDelay = 2f,
						ScaleHealth = ScaleToShiningNail
					},
					new Encounter
					{
						Name = "Lost Garmond",
						SceneInfo = new SceneLoadInfo
						{
							SceneName = "Coral_33",
							EntryGateName = "right1"
						},
						BeforeEnter = delegate
						{
							CacheUtils.CachePlayerDataBools("blackThreadWorld");
							PlayerData.instance.blackThreadWorld = true;
						},
						OnExit = delegate
						{
							CacheUtils.Restore();
						},
						CustomSpawnPoint = new Vector2(41f, 62f)
					}
				}
			},
			new BossInfo
			{
				Name = "Bench",
				JournalRecordName = "Bench",
				Encounters = new List<Encounter>
				{
					new Encounter
					{
						Name = "Bench",
						SceneInfo = new SceneLoadInfo
						{
							SceneName = "Belltown_Room_Spare",
							EntryGateName = "left1"
						},
						BeforeEnter = delegate
						{
							PlayerData.instance.BelltownFurnishingDesk = true;
							PlayerData.instance.BelltownFurnishingFairyLights = true;
							PlayerData.instance.BelltownFurnishingGramaphone = true;
							PlayerData.instance.BelltownFurnishingSpa = true;
							PlayerData.instance.BelltownFurnishingSpaAvailable = true;
						},
						TransitionDelay = 0f
					}
				}
			},
			new BossInfo
			{
				Name = "Blue Assistant",
				JournalRecordName = "Blue Assistant",
				Encounters = new List<Encounter>
				{
					new Encounter
					{
						Name = "Zango",
						SceneInfo = new SceneLoadInfo
						{
							SceneName = "Crawl_10",
							EntryGateName = "right1"
						},
						BeforeEnter = delegate
						{
							CacheUtils.CachePlayerDataBools("BlueScientistDead", "blackThreadWorld");
							PlayerData.instance.blackThreadWorld = true;
							if (((PersistentItemDataCollection<bool, SerializableBoolData>)(object)SceneData.instance.persistentBools).scenes["Crawl_10"].TryGetValue("Blue Assistant", out var value))
							{
								value.Value = false;
							}
						},
						OnExit = delegate
						{
							CacheUtils.Restore();
						},
						TransitionDelay = 3f
					}
				}
			}
		};

		public static Dictionary<string, BossInfo> BossInfoByName = BossInfos.ToDictionary((BossInfo x) => x.Name, (BossInfo x) => x);

		public static Dictionary<string, Encounter> EncounterByName = AllEncounter.ToDictionary((Encounter x) => x.Name, (Encounter x) => x);

		public static HashSet<string> ValidRecords => BossInfos.Select((BossInfo x) => x.JournalRecordName).ToHashSet();

		public static List<Encounter> AllEncounter => BossInfos.SelectMany((BossInfo x) => x.Encounters).ToList();

		private static int GetNailDamage(NailType type)
		{
			return type switch
			{
				NailType.Old => 5, 
				NailType.Sharpened => 9, 
				NailType.Shining => 13, 
				NailType.Hivesteel => 17, 
				NailType.Palesteel => 21, 
				_ => throw new NotImplementedException(), 
			};
		}

		private static void ScaleToNail(HealthManager hm, NailType type)
		{
			hm.hp *= Math.Max(1, Mathf.CeilToInt((float)(GetNailDamage(NailType.Palesteel) / GetNailDamage(type))) - 1);
		}

		internal static bool HasSecondEncounter(string name)
		{
			return name switch
			{
				"Mossbone Mother" => true, 
				"Lace" => true, 
				"Coral Conch Driller Giant" => true, 
				"Garmond" => true, 
				"Bone Flyer Giant" => true, 
				_ => false, 
			};
		}

		internal static (bool, bool) GetMultipleEncounterInfo(string name)
		{
			if (PlayerData.instance == null)
			{
				PopLogger.LogError("player data instance was null while looking up " + name);
				return (false, false);
			}
			return name switch
			{
				"Mossbone Mother" => (PlayerData.instance.defeatedMossMother, true), 
				"Lace" => (PlayerData.instance.defeatedLace1, PlayerData.instance.defeatedLaceTower), 
				"Coral Conch Driller Giant" => (PlayerData.instance.defeatedCoralDrillerSolo, PlayerData.instance.defeatedCoralDrillers), 
				"Garmond" => (true, PlayerData.instance.garmondBlackThreadDefeated), 
				"Bone Flyer Giant" => (PlayerData.instance.defeatedBoneFlyerGiant, PlayerData.instance.defeatedBoneFlyerGiantGolemScene), 
				_ => (false, false), 
			};
		}
	}
	public class Fireworks : MonoBehaviour
	{
		public float Size = 1f;

		public Color Color = Color.white;

		private ParticleSystem ps;

		public static GameObject CreateFirework(Vector3 position, float size, Color color, Transform parent = null)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("CodeFirework");
			if ((Object)(object)parent != (Object)null)
			{
				val.transform.SetParent(parent, true);
			}
			val.transform.position = position;
			Fireworks fireworks = val.AddComponent<Fireworks>();
			fireworks.Size = Mathf.Max(0.01f, size);
			fireworks.Color = color;
			return val;
		}

		private void Awake()
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: 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_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: 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_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Expected O, but got Unknown
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0237: Unknown result type (might be due to invalid IL or missing references)
			//IL_0247: Unknown result type (might be due to invalid IL or missing references)
			//IL_024c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0278: Unknown result type (might be due to invalid IL or missing references)
			//IL_029c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02db: Expected O, but got Unknown
			//IL_02f4: Unknown result type (might be due to invalid IL or missing references)
			ps = ((Component)this).gameObject.AddComponent<ParticleSystem>();
			ParticleSystemRenderer component = ((Component)this).gameObject.GetComponent<ParticleSystemRenderer>();
			component.renderMode = (ParticleSystemRenderMode)0;
			component.alignment = (ParticleSystemRenderSpace)1;
			component.sortMode = (ParticleSystemSortMode)2;
			MainModule main = ps.main;
			((MainModule)(ref main)).loop = false;
			((MainModule)(ref main)).duration = 1.2f;
			((MainModule)(ref main)).startLifetime = new MinMaxCurve(0.8f, 1.6f);
			((MainModule)(ref main)).startSpeed = new MinMaxCurve(4f * Size, 8f * Size);
			((MainModule)(ref main)).startSize = new MinMaxCurve(0.06f * Size, 0.18f * Size);
			((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(Color);
			((MainModule)(ref main)).gravityModifier = MinMaxCurve.op_Implicit(0f);
			((MainModule)(ref main)).simulationSpace = (ParticleSystemSimulationSpace)1;
			((MainModule)(ref main)).maxParticles = 1000;
			EmissionModule emission = ps.emission;
			((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(0f);
			((EmissionModule)(ref emission)).SetBursts((Burst[])(object)new Burst[1]
			{
				new Burst(0f, (short)(60f * Size), (short)(120f * Size), 1, 0f)
			});
			ShapeModule shape = ps.shape;
			((ShapeModule)(ref shape)).shapeType = (ParticleSystemShapeType)0;
			((ShapeModule)(ref shape)).radius = 0.1f * Size;
			ColorOverLifetimeModule colorOverLifetime = ps.colorOverLifetime;
			((ColorOverLifetimeModule)(ref colorOverLifetime)).enabled = true;
			Gradient val = new Gradient();
			val.SetKeys((GradientColorKey[])(object)new GradientColorKey[2]
			{
				new GradientColorKey(Color, 0f),
				new GradientColorKey(Color, 1f)
			}, (GradientAlphaKey[])(object)new GradientAlphaKey[2]
			{
				new GradientAlphaKey(1f, 0f),
				new GradientAlphaKey(0f, 1f)
			});
			((ColorOverLifetimeModule)(ref colorOverLifetime)).color = new MinMaxGradient(val);
			TrailModule trails = ps.trails;
			((TrailModule)(ref trails)).enabled = true;
			((TrailModule)(ref trails)).mode = (ParticleSystemTrailMode)1;
			((TrailModule)(ref trails)).ratio = 1f;
			((TrailModule)(ref trails)).lifetime = MinMaxCurve.op_Implicit(0.35f * Size);
			VelocityOverLifetimeModule velocityOverLifetime = ps.velocityOverLifetime;
			((VelocityOverLifetimeModule)(ref velocityOverLifetime)).enabled = true;
			((VelocityOverLifetimeModule)(ref velocityOverLifetime)).space = (ParticleSystemSimulationSpace)0;
			((VelocityOverLifetimeModule)(ref velocityOverLifetime)).x = new MinMaxCurve(-2f * Size, 2f * Size);
			((VelocityOverLifetimeModule)(ref velocityOverLifetime)).y = new MinMaxCurve(-2f * Size, 2f * Size);
			((VelocityOverLifetimeModule)(ref velocityOverLifetime)).z = new MinMaxCurve(-2f * Size, 2f * Size);
			try
			{
				Material val2 = new Material(Shader.Find("Sprites/Default"));
				val2.SetFloat("_Mode", 0f);
				val2.SetColor("_TintColor", Color);
				((Renderer)component).material = val2;
			}
			catch
			{
			}
		}

		private IEnumerator Start()
		{
			yield return null;
			if (!((Object)(object)ps == (Object)null))
			{
				MainModule main = ps.main;
				((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(Color);
				ps.Play();
				while ((Object)(object)ps != (Object)null && ps.IsAlive(true))
				{
					yield return null;
				}
				Object.Destroy((Object)(object)((Component)this).gameObject);
			}
		}

		public static Color ParseColor(string htmlColor, Color fallback)
		{
			//IL_0008: 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_0014: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrEmpty(htmlColor))
			{
				return fallback;
			}
			Color result = default(Color);
			if (ColorUtility.TryParseHtmlString(htmlColor, ref result))
			{
				return result;
			}
			return fallback;
		}
	}
	public static class PopLogger
	{
		public static void Log(object message)
		{
		}

		public static void LogWarning(object message)
		{
		}

		public static void LogError(object message)
		{
		}
	}
	[BepInPlugin("momochi003.pop", "Pantheon of Pharloom", "1.2.0")]
	public sealed class PantheonOfPharloom : BaseUnityPlugin
	{
		[HarmonyPatch(typeof(JournalItemManager), "GetItems")]
		internal static class Patch_GetItems
		{
			[HarmonyPrefix]
			private static bool Prefix(JournalItemManager __instance, ref List<EnemyJournalRecord> __result)
			{
				if (((Object)((Component)__instance).gameObject).name == "Bosses")
				{
					__result = (from x in EnemyJournalManager.GetAllEnemies()
						where BossRegistry.ValidRecords.Contains(((Object)x).name)
						select x).ToList();
					return false;
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(InventoryItemCollectableManager), "GetItems")]
		internal static class PatchInventory_GetItems
		{
			[HarmonyPrefix]
			private static bool Prefix(InventoryItemCollectableManager __instance, ref List<CollectableItem> __result)
			{
				if (((Object)((Component)__instance).gameObject).name == "BossRush")
				{
					__result = new List<CollectableItem>();
					return false;
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(JournalItemManager), "SetDisplay", new Type[] { typeof(InventoryItemSelectable) })]
		internal static class Patch_SetDisplay
		{
			[HarmonyPrefix]
			private static bool Prefix(JournalItemManager __instance, InventoryItemSelectable selectable)
			{
				if ((Object)(object)__instance == (Object)null || (Object)(object)selectable == (Object)null)
				{
					return true;
				}
				if ((Object)(object)((Component)__instance).gameObject == (Object)null)
				{
					return true;
				}
				if (((Object)((Component)__instance).gameObject).name == "Bosses")
				{
					PopLogger.Log(selectable);
					((Component)__instance).gameObject.GetComponent<BossesUIController>().BossItemSelected?.Invoke(selectable);
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(GameManager), "ReadyForRespawn", new Type[] { typeof(bool) })]
		internal static class Patch_ReadyForRespawn
		{
			[HarmonyPostfix]
			private static void Postfix(bool isFirstLevelForPlayer)
			{
				if (isFirstLevelForPlayer)
				{
					PopLogger.Log("called game loaded....");
					Instance.GameLoaded();
				}
			}
		}

		[HarmonyPatch(typeof(GameManager), "SaveGame", new Type[]
		{
			typeof(int),
			typeof(Action<bool>),
			typeof(bool),
			typeof(AutoSaveName)
		})]
		internal static class Patch_SaveGame
		{
			private static bool Prefix(int saveSlot, Action<bool> ogCallback, bool withAutoSave, AutoSaveName autoSaveName)
			{
				ogCallback?.Invoke(obj: true);
				return false;
			}
		}

		private static bool _initializingMenu = false;

		private static bool _initialized = false;

		public bool CusorEnabled { get; set; }

		public static PantheonOfPharloom Instance { get; private set; }

		public static Dictionary<string, GameObject> PreloadedObjects { get; } = new Dictionary<string, GameObject>();


		public event Action GameLoaded;

		private GameObject CreatePrefab(GameObject original)
		{
			GameObject val = Object.Instantiate<GameObject>(original);
			Object.DontDestroyOnLoad((Object)(object)val);
			val.SetActive(false);
			PopLogger.Log($"Created new game object: {val}");
			return val;
		}

		private void Awake()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			new Harmony("patcher").PatchAll();
			Instance = this;
			SceneManager.activeSceneChanged += delegate(Scene from, Scene to)
			{
				//IL_0075: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
				if (((Scene)(ref to)).name == "Menu_Title" && !_initialized)
				{
					new Hook((MethodBase)typeof(Language).GetMethod("Get", BindingFlags.Static | BindingFlags.Public, null, new Type[2]
					{
						typeof(string),
						typeof(string)
					}, null), (Delegate)(Func<Func<string, string, string>, string, string, string>)((Func<string, string, string> orig, string key, string sheetTitle) => (key == "Hacky") ? sheetTitle : orig(key, sheetTitle))).Apply();
					new Hook((MethodBase)typeof(Language).GetMethod("Has", BindingFlags.Static | BindingFlags.Public, null, new Type[2]
					{
						typeof(string),
						typeof(string)
					}, null), (Delegate)(Func<Func<string, string, bool>, string, string, bool>)((Func<string, string, bool> orig, string key, string sheetTitle) => key == "Hacky" || orig(key, sheetTitle))).Apply();
					_initialized = true;
				}
			};
			GameLoaded += delegate
			{
				if (!_initializingMenu)
				{
					PopLogger.Log("trying to initialize menu....");
					if (BossRushController.Instance == null)
					{
						((Component)GameManager.instance).gameObject.AddComponent<BossRushController>();
					}
					BossRushController.Instance.Reset(patch: false);
					_initializingMenu = true;
					((MonoBehaviour)this).StartCoroutine(InitializeMenu());
				}
			};
			BossLists.Initialize();
		}

		private GameObject CreateVerticalButtonGroup(string name)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			GameObject val = new GameObject(name);
			val.AddComponent<ChildArranger>().spacing = 2.5f;
			return val;
		}

		public static void PatchInventoryProxy(InventoryUIController controller, PlayMakerFSM fsm)
		{
			FsmState state = fsm.GetState("Move Pane L");
			PopLogger.Log(state.Actions.Length);
			state.InsertAction(0, (FsmStateAction)(object)new InventoryToggleAction(controller, InventoryToggleAction.MoveDirection.Left));
			PopLogger.Log(state.Actions.Length);
			FsmState state2 = fsm.GetState("Move Pane R");
			PopLogger.Log(state2.Actions.Length);
			state2.InsertAction(0, (FsmStateAction)(object)new InventoryToggleAction(controller, InventoryToggleAction.MoveDirection.Right));
			PopLogger.Log(state2.Actions.Length);
			PopLogger.Log("Patched Inventory Proxy");
		}

		private GameObject CreateButtonFromQuest(GameObject quest_template, string name, string topText, string bottomText, Transform parent, Color? color = null, string overrideQuestName = null)
		{
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Object.Instantiate<GameObject>(quest_template, parent);
			((Object)val).name = name;
			Object.Destroy((Object)(object)val.GetComponent<InventoryItemMainQuest>());
			Object.Destroy((Object)(object)val.GetComponent<InventoryItemExtraDescription>());
			Object.Destroy((Object)(object)((Component)val.transform.Find("Sub Quests Layout")).gameObject);
			((Component)val.transform.Find("Main Quest/Group/Amount Icons")).gameObject.SetActive(false);
			((Component)val.transform.Find("Main Quest/Group/New Item Orb")).gameObject.SetActive(false);
			((TMP_Text)((Component)val.transform.Find("Main Quest/Group/Text Type")).gameObject.GetComponent<TextMeshPro>()).text = topText;
			if (color.HasValue)
			{
				((Graphic)((Component)val.transform.Find("Main Quest/Group/Text Type")).gameObject.GetComponent<TextMeshPro>()).color = color.Value;
			}
			if (overrideQuestName != null)
			{
				Sprite icon = ((BasicQuestBase)QuestManager.GetQuest(overrideQuestName)).QuestType.Icon;
				((Component)val.transform.Find("Main Quest/Group/Icon")).GetComponent<SpriteRenderer>().sprite = icon;
			}
			((TMP_Text)((Component)val.transform.Find("Main Quest/Group/Text Name")).gameObject.GetComponent<TextMeshPro>()).text = bottomText;
			return val;
		}

		private void CloneMemoryUseMsg(GameObject memory_use, GameObject parent)
		{
			GameObject obj = Object.Instantiate<GameObject>(memory_use, parent.transform);
			Transform val = obj.transform.Find("Text");
			((Object)obj).name = "Disabled Overlay";
			Object.Destroy((Object)(object)((Component)val).GetComponent<SetTextMeshProGameText>());
			((TMP_Text)((Component)val).GetComponent<TextMeshPro>()).text = "Cannot use this menu when boss rush is active.";
		}

		private IEnumerator InitializeMenu()
		{
			_initializingMenu = true;
			yield return (object)new WaitForEndOfFrame();
			yield return (object)new WaitForEndOfFrame();
			GameObject inv = GameObject.Find("_GameCameras/HudCamera/In-game/Inventory");
			GameObject val = GameObject.Find("_GameCameras/HudCamera/In-game/Inventory/Journal");
			GameObject obj = GameObject.Find("_GameCameras/HudCamera/In-game/Inventory/Inv");
			GameObject obj2 = GameObject.Find("_GameCameras/HudCamera/In-game/Inventory/Border");
			GameObject quest_template = GameObject.Find("_GameCameras/HudCamera/In-game/Inventory/Quests/Quest List/Main Quests Layout/Template Main Quest Item");
			GameObject val2 = Object.Instantiate<GameObject>(obj2, inv.transform);
			GameObject val3 = Object.Instantiate<GameObject>(val, inv.transform);
			GameObject val4 = Object.Instantiate<GameObject>(obj, inv.transform);
			Transform val5 = val3.transform.Find("Notes Desc");
			GameObject val6 = Object.Instantiate<GameObject>(CreateVerticalButtonGroup("Challenge Buttons"), ((Component)val5).transform.position, Quaternion.identity, val3.transform);
			GameObject item = CreateButtonFromQuest(quest_template, "Challenge Button 1", "CHALLENGE", "", val6.transform);
			GameObject item2 = CreateButtonFromQuest(quest_template, "Challenge Button 2", "CHALLENGE", "", val6.transform);
			SelectableButtonList selectableButtonList = val6.AddComponent<SelectableButtonList>();
			selectableButtonList.Buttons = new List<GameObject> { item, item2 };
			((Behaviour)selectableButtonList).enabled = false;
			val6.GetComponent<ChildArranger>().ArrangeChildrenVertical();
			PopLogger.Log("GOT EHRE>....");
			Object.Destroy((Object)(object)((Component)val5).gameObject);
			((Component)val3.transform.Find("Text Completion")).gameObject.SetActive(false);
			Object.Destroy((Object)(object)((Component)val2.transform.Find("PaneListDisplay")).gameObject);
			GameObject val7 = Object.Instantiate<GameObject>(CreateVerticalButtonGroup("Act Buttons"), val4.transform.position + new Vector3(4f, -2.5f, 0f), Quaternion.identity, val4.transform);
			GameObject val8 = CreateButtonFromQuest(quest_template, "Act 1", "SYMPHONY NO.I", "Judge", val7.transform, Colors.Pharloom, "Grand Gate Bellshrines");
			GameObject val9 = CreateButtonFromQuest(quest_template, "Act 2", "SYMPHONY NO.II", "Sinner", val7.transform, Colors.Citadel, "Citadel Investigate");
			GameObject val10 = CreateButtonFromQuest(quest_template, "Act 3", "SYMPHONY NO.III", "Void", val7.transform, Colors.Abyss, "Black Thread Pt6 Flower");
			GameObject obj3 = CreateButtonFromQuest(quest_template, "Pharloom", "FINAL SYMPHONY", "Silk & Song", val7.transform, Colors.Final, "Save the Fleas");
			InventoryItemParent component = ((Component)val4.transform.Find("Inv_Items/Needle Shift/Spool Group")).gameObject.GetComponent<InventoryItemParent>();
			InventoryItemSpoolPieces component2 = ((Component)val4.transform.Find("Inv_Items/Needle Shift/Spool Pieces")).gameObject.GetComponent<InventoryItemSpoolPieces>();
			InventorySeletableWithName inventorySeletableWithName = val8.AddComponent<InventorySeletableWithName>();
			inventorySeletableWithName.displayName = "Symphony of the Judge";
			inventorySeletableWithName.description = "Face the Judge's harsh trial";
			inventorySeletableWithName.cursorGlow = Colors.Pharloom;
			InventorySeletableWithName inventorySeletableWithName2 = val9.AddComponent<InventorySeletableWithName>();
			inventorySeletableWithName2.displayName = "Symphony of the Sinner";
			inventorySeletableWithName2.description = "Walk the path of a Sinner";
			inventorySeletableWithName2.cursorGlow = Colors.Citadel;
			InventorySeletableWithName inventorySeletableWithName3 = val10.AddComponent<InventorySeletableWithName>();
			inventorySeletableWithName3.displayName = "Symphony of the Void";
			inventorySeletableWithName3.description = "Face what the Void has claimed";
			inventorySeletableWithName3.cursorGlow = Colors.Abyss;
			InventorySeletableWithName inventorySeletableWithName4 = obj3.AddComponent<InventorySeletableWithName>();
			inventorySeletableWithName4.displayName = "Symphony of Silk & Song";
			inventorySeletableWithName4.description = "The final trial. Sounds of every battle wovenn into one";
			inventorySeletableWithName4.cursorGlow = Colors.Final;
			((InventoryItemSelectableDirectional)inventorySeletableWithName).Selectables = (InventoryItemSelectable[])(object)new InventoryItemSelectable[4]
			{
				default(InventoryItemSelectable),
				(InventoryItemSelectable)inventorySeletableWithName2,
				(InventoryItemSelectable)component2,
				default(InventoryItemSelectable)
			};
			((InventoryItemSelectableDirectional)inventorySeletableWithName2).Selectables = (InventoryItemSelectable[])(object)new InventoryItemSelectable[4]
			{
				(InventoryItemSelectable)inventorySeletableWithName,
				(InventoryItemSelectable)inventorySeletableWithName3,
				(InventoryItemSelectable)component2,
				default(InventoryItemSelectable)
			};
			((InventoryItemSelectableDirectional)inventorySeletableWithName3).Selectables = (InventoryItemSelectable[])(object)new InventoryItemSelectable[4]
			{
				(InventoryItemSelectable)inventorySeletableWithName2,
				(InventoryItemSelectable)inventorySeletableWithName4,
				(InventoryItemSelectable)component,
				default(InventoryItemSelectable)
			};
			((InventoryItemSelectableDirectional)inventorySeletableWithName4).Selectables = (InventoryItemSelectable[])(object)new InventoryItemSelectable[4]
			{
				(InventoryItemSelectable)inventorySeletableWithName3,
				default(InventoryItemSelectable),
				(InventoryItemSelectable)component,
				default(InventoryItemSelectable)
			};
			SelectableList val11 = new SelectableList
			{
				Selectables = new List<InventoryItemSelectable>()
			};
			((InventoryItemSelectableDirectional)inventorySeletableWithName).FallbackSelectables = (SelectableList[])(object)new SelectableList[4] { val11, val11, val11, val11 };
			((InventoryItemSelectableDirectional)inventorySeletableWithName2).FallbackSelectables = (SelectableList[])(object)new SelectableList[4] { val11, val11, val11, val11 };
			((InventoryItemSelectableDirectional)inventorySeletableWithName3).FallbackSelectables = (SelectableList[])(object)new SelectableList[4] { val11, val11, val11, val11 };
			((InventoryItemSelectableDirectional)inventorySeletableWithName4).FallbackSelectables = (SelectableList[])(object)new SelectableList[4] { val11, val11, val11, val11 };
			((InventoryItemSelectableDirectional)component).Selectables[3] = (InventoryItemSelectable)(object)inventorySeletableWithName;
			((InventoryItemSelectableDirectional)component2).Selectables[3] = (InventoryItemSelectable)(object)inventorySeletableWithName;
			((InventoryItemManager)val4.GetComponent<InventoryItemCollectableManager>()).rightMostSelectables[0] = (InventoryItemSelectable)(object)inventorySeletableWithName4;
			GameObject gameObject = ((Component)val4.transform.Find("Memory Use Msg")).gameObject;
			CloneMemoryUseMsg(gameObject, val4);
			CloneMemoryUseMsg(gameObject, val3);
			val4.AddComponent<BossRushUIController>();
			val4.AddComponent<DisableInventory>();
			((Object)val4).name = "BossRush";
			val3.AddComponent<BossesUIController>();
			val3.AddComponent<DisableInventory>();
			((Object)val3).name = "Bosses";
			InventoryUIController inventoryUIController = inv.AddComponent<InventoryUIController>();
			val3.SetActive(false);
			val4.SetActive(false);
			inventoryUIController.Border = val2;
			Activator activator = inv.AddComponent<Activator>();
			inventoryUIController.ScreenPlane = ((Component)val2.transform.Find("Inventory ScreenPlane")).gameObject;
			inventoryUIController.RegisterEntry(InventoryType.BossRush, val4, setActive: true);
			inventoryUIController.RegisterEntry(InventoryType.Bosses, val3);
			PopLogger.Log($"done new {inv}, {val}, {val3}, {val2}, {inventoryUIController.ScreenPlane}, {val6}");
			activator.OnActivate = delegate
			{
				inv.GetComponent<InventoryUIController>().EnableUI();
			};
			activator.OnDeactivate = delegate
			{
				inv.GetComponent<InventoryUIController>().DisableUI();
			};
			_initializingMenu = false;
		}
	}
	internal class Activator : MonoBehaviour
	{
		private PlayerAction _action;

		private bool _activated;

		public GameObject Target { get; set; }

		public Action<GameObject> OnActivate { get; set; }

		public Action<GameObject> OnDeactivate { get; set; }

		private void Start()
		{
			HeroActions inputActions = GameManager.instance.inputHandler.inputActions;
			_action = ((PlayerActionSet)inputActions).CreatePlayerAction("Bosses");
			_action.AddDefaultBinding((Key[])(object)new Key[1] { (Key)37 });
		}

		private void Update()
		{
			if ((!PlayerData.instance.isInventoryOpen || _activated) && !PlayerData.instance.disableInventory && !GameManager.instance.isPaused && GameManager.instance.hasFinishedEnteringScene && ((OneAxisInputControl)((PlayerActionSet)GameManager.instance.inputHandler.inputActions).GetPlayerActionByName("Bosses")).WasPressed)
			{
				if (!Target.activeInHierarchy)
				{
					OnActivate(Target);
					_activated = true;
				}
				else
				{
					OnDeactivate(Target);
					_activated = false;
				}
			}
		}
	}
	internal class AbilityToggleAction : ToggleAction
	{
		public string abilityBoolName;

		private SpriteRenderer _sprite;

		public override IEnumerator Toggle()
		{
			bool enabled = !PlayerData.instance.GetBool(abilityBoolName);
			PlayerData.instance.SetBool(abilityBoolName, enabled);
			PopLogger.Log($"toggled {abilityBoolName} from {enabled} to {!enabled}");
			float num = 0.1f;
			_ = ((Component)this).transform.localPosition;
			iTween.ShakePosition(((Component)this).gameObject, iTween.Hash(new object[6]
			{
				"amount",
				(object)new Vector3(0.1f, 0f, 0f),
				"time",
				num,
				"ignoretimescale",
				true
			}));
			yield return (object)new WaitForSecondsRealtime(num);
			_sprite.color = (enabled ? new Color(1f, 1f, 1f) : new Color(0.5f, 0.5f, 0.5f, 1f));
			PopLogger.Log("returning hjere");
		}

		private void ResetShakePosition(Vector3 originalPos)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			((Component)this).transform.localPosition = originalPos;
		}

		private void Awake()
		{
			if (_sprite == null)
			{
				_sprite = ((Component)this).gameObject.GetComponent<SpriteRenderer>();
			}
		}
	}
	internal class ChangeNeedleToggleAction : ToggleAction
	{
		private const int TOTAL_NAILS = 5;

		private InventoryItemNail inventoryItemNail;

		private InventoryItemCollectableManager manager;

		public override IEnumerator Toggle()
		{
			int nailUpgrades = PlayerData.instance.nailUpgrades;
			int num = (nailUpgrades + 1) % 5;
			PlayerData.instance.nailUpgrades = num;
			DisplayState[] displayStates = inventoryItemNail.displayStates;
			GameObject displayObject = displayStates[nailUpgrades].DisplayObject;
			GameObject displayObject2 = displayStates[num].DisplayObject;
			yield return AnimationUtil.TweenHorizontal(displayObject, displayObject2, toRight: true, 0.2f, 1f);
			inventoryItemNail.UpdateState();
		}

		public override IEnumerator Extra()
		{
			yield return null;
		}

		private void InfiniteNailDamage()
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			new Hook((MethodBase)AccessTools.DeclaredPropertyGetter(typeof(PlayerData), "nailDamage"), (Delegate)new Func<PlayerData, int>(OverrideNailDamange)).Apply();
			static int OverrideNailDamange(PlayerData self)
			{
				return 99999;
			}
		}

		private void Awake()
		{
			if ((Object)(object)inventoryItemNail == (Object)null)
			{
				PopLogger.Log("trying to find nail");
				inventoryItemNail = ((Component)this).gameObject.GetComponent<InventoryItemNail>();
				PopLogger.Log($"{inventoryItemNail} to find nail");
			}
			if ((Object)(object)manager == (Object)null)
			{
				manager = ((Component)this).gameObject.GetComponentInParent<InventoryItemCollectableManager>();
			}
		}
	}
	internal class DisableInventory : MonoBehaviour
	{
		private GameObject _msg;

		private TextMeshPro _displayText;

		private PlayMakerFSM _inventoryProxy;

		private void Awake()
		{
			_msg = ((Component)((Component)this).transform.Find("Disabled Overlay")).gameObject;
			_displayText = ((Component)_msg.transform.Find("Text")).GetComponent<TextMeshPro>();
			_inventoryProxy = FSMUtility.LocateMyFSM(((Component)this).gameObject, "Inventory Proxy");
		}

		private void OnEnable()
		{
			if (!BossRushController.Instance.AllowUI)
			{
				_msg.SetActive(true);
				((Behaviour)_inventoryProxy).enabled = false;
			}
		}

		private void OnDisable()
		{
			((Behaviour)_inventoryProxy).enabled = true;
			_msg.SetActive(false);
		}
	}
	internal enum PantheonType
	{
		Pharloom,
		Citadel,
		Abyss,
		Silksong
	}
	internal class PantheonChallengeAction : ToggleAction
	{
		public PantheonType pantheonType;

		public override bool CloseUI => true;

		public override IEnumerator Toggle()
		{
			switch (pantheonType)
			{
			case PantheonType.Pharloom:
				BossRushController.SetupNewSequence(BossLists.PharloomEncounters.ToList(), transition: true);
				break;
			case PantheonType.Citadel:
				BossRushController.SetupNewSequence(BossLists.CitadelEncounters.ToList(), transition: true);
				break;
			case PantheonType.Abyss:
				BossRushController.SetupNewSequence(BossLists.AbyssEncounters.ToList(), transition: true);
				break;
			case PantheonType.Silksong:
				BossRushController.SetupNewSequence(BossLists.SilksongEncounters.ToList(), transition: true);
				break;
			}
			yield return null;
		}
	}
	public class SelectableButtonList : MonoBehaviour
	{
		public InventoryCursor InventoryCursor;

		public List<GameObject> Buttons = new List<GameObject>();

		public int SelectedIndex { get; private set; } = -1;


		public int ButtonCount => Buttons.Count;

		public GameObject SelectedButton
		{
			get
			{
				if (SelectedIndex < 0 || SelectedIndex >= Buttons.Count)
				{
					return null;
				}
				return Buttons[SelectedIndex];
			}
		}

		private void Update()
		{
			if (((OneAxisInputControl)GameManager.instance.inputHandler.inputActions.Down).WasPressed)
			{
				Next();
			}
			if (((OneAxisInputControl)GameManager.instance.inputHandler.inputActions.Up).WasPressed)
			{
				Previous();
			}
		}

		public void Select()
		{
			for (int i = 0; i < Buttons.Count; i++)
			{
				if (Buttons[i].activeInHierarchy)
				{
					Select(i);
					break;
				}
			}
		}

		public void Select(int index)
		{
			if (index >= 0 && index < Buttons.Count)
			{
				SelectedIndex = index;
				InventoryCursor.ResetClampedPos();
				InventoryCursor.SetTarget(Buttons[SelectedIndex].transform);
			}
		}

		public void Next()
		{
			if (Buttons.Count != 0)
			{
				int selectedIndex = SelectedIndex;
				int num = (SelectedIndex + 1) % Buttons.Count;
				while (num != selectedIndex && !Buttons[num].activeInHierarchy)
				{
					num = (num + 1) % Buttons.Count;
				}
				if (num != selectedIndex)
				{
					Select(num);
				}
			}
		}

		public void Previous()
		{
			if (Buttons.Count != 0)
			{
				int selectedIndex = SelectedIndex;
				int num = (SelectedIndex - 1 + Buttons.Count) % Buttons.Count;
				while (num != selectedIndex && !Buttons[num].activeInHierarchy)
				{
					num = (num - 1 + Buttons.Count) % Buttons.Count;
				}
				if (num != selectedIndex)
				{
					Select(num);
				}
			}
		}
	}
	internal abstract class ToggleAction : MonoBehaviour
	{
		public virtual bool CloseUI { get; set; }

		public abstract IEnumerator Toggle();

		public virtual IEnumerator Extra()
		{
			yield return null;
		}
	}
	public class ChildArranger : MonoBehaviour
	{
		[SerializeField]
		public float spacing = 1f;

		[SerializeField]
		public bool arrangeOnStart = true;

		public void ArrangeChildrenVertical()
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			float num = 0f;
			for (int i = 0; i < ((Component)this).transform.childCount; i++)
			{
				((Component)this).transform.GetChild(i).localPosition = new Vector3(0f, 0f - num, 0f);
				num += spacing;
			}
		}

		public void ArrangeChildrenHorizontal()
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			float num = 0f;
			for (int i = 0; i < ((Component)this).transform.childCount; i++)
			{
				((Component)this).transform.GetChild(i).localPosition = new Vector3(num, 0f, 0f);
				num -= spacing;
			}
		}

		private void Start()
		{
			if (arrangeOnStart)
			{
				ArrangeChildrenVertical();
			}
		}
	}
	public enum InventoryType
	{
		Bosses,
		BossRush
	}
	public class InventoryUIController : MonoBehaviour
	{
		public class InventoryEntry
		{
			private string ProxyFSMName = "Inventory Proxy";

			public InventoryType Type { get; }

			public GameObject Root { get; }

			private string ControlFSMName
			{
				get
				{
					if (Type != 0)
					{
						return "UI Inventory";
					}
					return "UI Journal";
				}
			}

			public InventoryEntry(InventoryType type, GameObject root)
			{
				Type = type;
				Root = root;
			}

			public void SetupFSMEnable(SelectedActionType select = 3)
			{
				//IL_0038: Unknown result type (might be due to invalid IL or missing references)
				//IL_003a: Invalid comparison between Unknown and I4
				//IL_0051