Decompiled source of Pantheon Of Pharloom v1.3.2

PantheonOfPharloom.dll

Decompiled 3 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 GlobalSettings;
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+b3d1a911a7e4c2c15f63eddf66dc13c6e87c03af")]
[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 BossRushSequence _sequence;

		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 => _sequence.Current();

		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)
			{
				if (!(text == "visitedGreymoor") && !(text == "visitedCoral"))
				{
					_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.respawnScene + ", " + PlayerData.instance.respawnMarkerName + ", " + PlayerData.instance.tempRespawnScene + ", " + PlayerData.instance.tempRespawnMarker);
		}

		private void AfterDeathOrCompletion()
		{
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			if (_sequence == null)
			{
				PopLogger.LogError("Sequence was null here should never happen");
			}
			_sequence.Cleanup?.Invoke();
			Reset();
			PlayerData.instance.respawnScene = _userState.Scene;
			PlayerData.instance.respawnMarkerName = _userState.Marker;
			PopLogger.Log("Setting after death or completion: " + PlayerData.instance.respawnScene + ", " + PlayerData.instance.respawnMarkerName);
			HeroItemsState items = _userState.Items;
			((HeroItemsState)(ref items)).Apply(HeroController.instance);
		}

		private void OnHornetDeath()
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Expected O, but got Unknown
			if (_userState != null)
			{
				RestoreSpawnScene();
			}
			CurrentEncounter.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, Action beforeEncounter = null, Action cleanup = null)
		{
			//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._sequence = new BossRushSequence(encounters, beforeEncounter, null, cleanup);
			Instance._isActive = true;
			PatchPlayerData();
			FadeSceneInHook.Init();
			FadeSceneInHook.SetEnabled(enabled: true);
			if (transition)
			{
				Instance.NextBoss();
			}
		}

		private void BeginBossRushCompletion(float delay)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Expected O, but got Unknown
			PopLogger.Log("end reached");
			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, SceneAfterFinish(), delegate
			{
				GameManager.instance.RespawningHero = true;
			});
			IEnumerator SceneAfterFinish()
			{
				_sequence.Previous().AfterExit?.Invoke();
				AfterDeathOrCompletion();
				yield return null;
				PopLogger.Log("created fireworks");
			}
		}

		private void NextBoss()
		{
			if (!_sequence.TryGetNext(out var next))
			{
				BeginBossRushCompletion(_sequence.Previous().TransitionDelay);
				return;
			}
			PopLogger.Log("calling NextBoss.");
			if (!_sequence.IsFirstInSequence)
			{
				_sequence.Previous().OnExit?.Invoke();
				_sequence.AfterEncounter?.Invoke();
			}
			_sequence.BeforeEncounter?.Invoke();
			next.BeforeEnter?.Invoke();
			PopLogger.Log($"Starting next boss scene: {next.SceneInfo}");
			StartTransitionWithCallback(next.SceneInfo, _sequence.IsFirstInSequence ? 0f : _sequence.Previous().TransitionDelay, OnNewEncounterLoad, doTransition: true, delegate
			{
				//IL_0013: Unknown result type (might be due to invalid IL or missing references)
				//IL_0018: Unknown result type (might be due to invalid IL or missing references)
				string sceneName = CurrentEncounter.SceneInfo.SceneName;
				Scene activeScene = SceneManager.GetActiveScene();
				return sceneName == ((Scene)(ref activeScene)).name;
			});
		}

		private void TransitionFromBench()
		{
			if (!_sequence.TryGetNext(out var next))
			{
				BeginBossRushCompletion(_sequence.Previous().TransitionDelay);
				return;
			}
			if (!_sequence.IsFirstInSequence)
			{
				_sequence.Previous().OnExit?.Invoke();
			}
			next.BeforeEnter?.Invoke();
			StartTransitionWithCallback(next.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_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expected O, but got Unknown
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: 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 (!_sequence.IsFirstInSequence)
			{
				_sequence.Previous().AfterExit?.Invoke();
			}
			CurrentEncounter.AfterEnter?.Invoke();
			PatchBadStates();
			IEncounterCompletedNotification encounterCompletedNotification = EncounterCompletionRegistry.AddEncounterCompletion(Object.Instantiate<GameObject>(new GameObject("BossRushController")), CurrentEncounter);
			if (encounterCompletedNotification is BenchTransitionNotification benchTransitionNotification)
			{
				if (_sequence.TryPeekNext(out var next))
				{
					benchTransitionNotification.nextScene = next.SceneInfo.SceneName;
					benchTransitionNotification.nextGate = next.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, Func<bool> predicate = null)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			if (doTransition)
			{
				((MonoBehaviour)this).StartCoroutine(DoTransition(info, delay));
			}
			GameManager.instance.OnFinishedEnteringScene += new EnterSceneEvent(Wrapper);
			void Wrapper()
			{
				//IL_002c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0036: Expected O, but got Unknown
				if (predicate != null && !predicate())
				{
					PopLogger.Log("did not satisfy condition....");
				}
				else
				{
					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_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Expected O, but got Unknown
			_sequence = null;
			_isActive = false;
			FadeSceneInHook.Unload();
			if (patch)
			{
				RestorePlayerData();
				HeroController.instance.OnDeath -= OnHornetDeath;
				GameManager.instance.OnFinishedEnteringScene -= new EnterSceneEvent(OnNewEncounterLoad);
			}
		}
	}
	public class BossRushSequence
	{
		private List<Encounter> _encounters = new List<Encounter>(encounters);

		public readonly Action BeforeEncounter;

		public readonly Action AfterEncounter;

		public readonly Action Cleanup;

		private int _encounterIndex;

		public bool IsFirstInSequence => _encounterIndex == 0;

		public BossRushSequence(IEnumerable<Encounter> encounters, Action beforeEncounter = null, Action afterEncounter = null, Action cleanup = null)
		{
			BeforeEncounter = beforeEncounter;
			AfterEncounter = afterEncounter;
			Cleanup = cleanup;
			_encounterIndex = -1;
			base..ctor();
		}

		public bool TryGetNext([MaybeNullWhen(false)] out Encounter next)
		{
			_encounterIndex++;
			if (_encounterIndex == _encounters.Count)
			{
				next = default(Encounter);
				return false;
			}
			next = _encounters[_encounterIndex];
			return true;
		}

		public bool TryPeekNext([MaybeNullWhen(false)] out Encounter next)
		{
			if (_encounterIndex + 1 >= _encounters.Count)
			{
				next = default(Encounter);
				return false;
			}
			next = _encounters[_encounterIndex + 1];
			return true;
		}

		public Encounter Previous()
		{
			return _encounters[_encounterIndex - 1];
		}

		public Encounter Current()
		{
			return _encounters[_encounterIndex];
		}
	}
	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 SingleConchflyDeadNotification : BossEncounterCompleteNotification
	{
		private void Start()
		{
			GameObject obj = GameObjectUtil.FindGameObjectFromScene("Battle Scene/Wave 1/Coral Conch Driller Giant Solo/Corpse Coral Conch Driller Giant Solo(Clone)");
			PlayMakerFSM val = ((obj != null) ? FSMUtility.LocateMyFSM(obj, "Death") : null);
			if (val == null)
			{
				PopLogger.LogError("Could not find conch corpse fsm");
				return;
			}
			val.GetState("Stagger").InsertMethod(0, base.BossDead);
			PopLogger.Log("patched single conchfly");
		}
	}
	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)
			},
			{
				"Single Conchfly",
				typeof(SingleConchflyDeadNotification)
			},
			{
				"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 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 Encounter GetEncounterByName(string name, bool is_void)
		{
			if (is_void && BossRegistry.EncounterByName.TryGetValue(name + " (Void)", out var value))
			{
				return value;
			}
			return BossRegistry.EncounterByName[name];
		}

		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 static Encounter[] PharloomEncounters(bool is_void)
		{
			return PharloomBosses.Select((string x) => GetEncounterByName(x, is_void)).ToArray();
		}

		public static Encounter[] CitadelEncounters(bool is_void)
		{
			return CitadelBosses.Select((string x) => GetEncounterByName(x, is_void)).ToArray();
		}

		public static Encounter[] AbyssEncounters(bool is_void)
		{
			return AbyssBosses.Select((string x) => GetEncounterByName(x, is_void)).ToArray();
		}

		public static Encounter[] SilksongEncounters(bool is_void)
		{
			return SilksongBosses.Select((string x) => GetEncounterByName(x, is_void)).ToArray();
		}
	}
	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 obj7 = GameObjectUtil.FindGameObjectFromScene("Black Thread States/Normal World/Battle Scene/Wave 1");
							if (obj7 != null)
							{
								GameObject gameObject = obj7.gameObject;
								if (gameObject != null)
								{
									gameObject.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.TryGetValue("Weave_03", out var value9) && value9.TryGetValue("Boss Scene", out var value10))
							{
								value10.Value = false;
							}
						},
						AfterEnter = delegate
						{
							ScaleTransitionHP("Mossbone Mother A", "Control", NailType.Sharpened, "HP P2", "HP Call Buddy", "HP Half");
						},
						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 = ScaleToHivesteelNail
					},
					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 = ScaleToHivesteelNail
					},
					new Encounter
					{
						Name = "Savage Beastfly (Void)",
						SceneInfo = new SceneLoadInfo
						{
							SceneName = "Ant_19",
							EntryGateName = "left1",
							Visualization = (SceneLoadVisualizations)0,
							PreventCameraFadeOut = false
						},
						BeforeEnter = delegate
						{
							CacheUtils.CachePlayerDataBools("blackThreadWorld");
							PlayerData.instance.defeatedBoneFlyerGiant = false;
							PlayerData.instance.blackThreadWorld = true;
						},
						OnExit = delegate
						{
							CacheUtils.Restore();
							PlayerData.instance.defeatedBoneFlyerGiant = true;
						},
						BossPathFromRoot = new string[1] { "Boss Control/Boss Scene/Bone Flyer Giant" },
						CustomSpawnPoint = new Vector2(63f, 34.6f)
					},
					new Encounter
					{
						Name = "Savage Beastfly 2 (Void)",
						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", "blackThreadWorld");
							PlayerData.instance.defeatedBoneFlyerGiantGolemScene = false;
							PlayerData.instance.defeatedSongGolem = true;
							PlayerData.instance.blackThreadWorld = 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
						},
						AfterEnter = delegate
						{
							ScaleTransitionHP("Boss Scene/Bone Beast", "Control", NailType.Sharpened, "P2 HP");
						},
						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 = ScaleToSharpenedNail
					}
				}
			},
			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
						{
						},
						AfterEnter = delegate
						{
							if (GameObjectUtil.FindGameObjectFromScene("Boss Scene/Dock Guard Slasher") != null)
							{
								ScaleTransitionHP("Boss Scene/Dock Guard Slasher", "Control", NailType.Hivesteel, "P2 HP", "P3 HP", "P4 HP");
							}
						},
						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
					}
				}
			},
			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;
						},
						AfterEnter = delegate
						{
							ScaleTransitionHP("Vampire Gnat Scene/Vampire Gnat", "Control", NailType.Sharpened, "P2 HP");
						},
						OnExit = delegate
						{
							PlayerData.instance.defeatedVampireGnatBoss = true;
						},
						BossPathFromRoot = new string[1] { "Vampire Gnat Scene/Vampire Gnat" },
						ScaleHealth = ScaleToSharpenedNail
					}
				}
			},
			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
						{
						},
						AfterEnter = delegate
						{
							ScaleTransitionHP("Boss Scene Parent/Boss Scene/Splinter Queen", "Control", NailType.Sharpened, "HP", "P2 HP", "P3 HP");
						},
						OnExit = delegate
						{
						},
						BossPathFromRoot = new string[1] { "Boss Scene Parent/Boss Scene/Splinter Queen" },
						ScaleHealth = ScaleToSharpenedNail
					}
				}
			},
			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
						{
						},
						CustomSpawnPoint = new Vector2(121f, 7f)
					}
				}
			},
			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"
						},
						AfterEnter = delegate
						{
							ScaleTransitionHP("Boss Scene/Last Judge", "Control", NailType.Shining, "HP", "HP P2", "HP P3");
						},
						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.TryGetValue("Coral_Judge_Arena", out var value7) && value7.TryGetValue("Last Judge", out var value8))
							{
								value8.Value = false;
							}
						},
						OnExit = delegate
						{
						},
						BossPathFromRoot = new string[1] { "Boss Scene/Last Judge" },
						TransitionDelay = 0f,
						CustomSpawnPoint = new Vector2(25f, 25f),
						ScaleHealth = ScaleToShiningNail
					}
				}
			},
			new BossInfo
			{
				Name = "Coral Conch Driller Giant",
				JournalRecordName = "Coral Conch Driller Giant",
				Encounters = new List<Encounter>
				{
					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 = ScaleToShiningNail
					},
					new Encounter
					{
						Name = "Single Conchfly",
						SceneInfo = new SceneLoadInfo
						{
							SceneName = "Coral_27",
							EntryGateName = "left1"
						},
						BeforeEnter = delegate
						{
						},
						OnExit = delegate
						{
						},
						CustomSpawnPoint = new Vector2(20f, 34f)
					}
				}
			},
			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,
						CustomSpawnPoint = new Vector2(35f, 360f)
					}
				}
			},
			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
						{
						},
						AfterEnter = delegate
						{
							ScaleTransitionHP("Dancer Control", "Control", NailType.Sharpened, "Phase 1 HP", "Phase 2 HP", "Phase 3 HP", "Phase 4 HP");
						},
						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"
						},
						AfterEnter = delegate
						{
							ScaleTransitionHP("Grand Stage Scene/Boss Scene Trobbio/Trobbio", "Control", NailType.Shining, "P2 HP");
						},
						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 obj6 = GameObjectUtil.FindGameObjectFromScene("Grand Stage Scene/Boss Scene TormentedTrobbio");
							if (obj6 != null)
							{
								obj6.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.TryGetValue("Clover_10", out var value5) && value5.TryGetValue("Dancer A", out var value6))
							{
								value6.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 obj5 = GameObjectUtil.FindGameObjectFromScene("Pinstress Control/Pinstress Scene/Pinstress Boss/NPC");
							FsmState state = ((obj5 != null) ? FSMUtility.LocateMyFSM(obj5, "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.TryGetValue("Belltown_Shrine", out var value3) && value3.TryGetValue("Bellshrine Sequence Bellhart", out var value4))
							{
								value4.Value = 0;
							}
						},
						AfterEnter = delegate
						{
							string boss_path = "Black Thread States Thread Only Variant/Normal World/Boss Scene/Spinner Boss";
							ScaleTransitionHP(boss_path, "Control", NailType.Old, "P2 HP", "P3 HP");
							ScaleTransitionHP(boss_path, "Fake Death", NailType.Old, "P3 HP");
						},
						AfterExit = delegate
						{
							((MonoBehaviour)GameManager.instance).StartCoroutine(HeroController.instance.Respawn(HeroController.instance.transform));
						},
						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
						{
						},
						AfterEnter = delegate
						{
							ScaleTransitionHP("Boss Scene/First Weaver", "Control", NailType.Shining, "HP", "Can Bind HP", "P2 HP", "Max HP");
						},
						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");
						},
						AfterExit = delegate
						{
							((MonoBehaviour)GameManager.instance).StartCoroutine(HeroController.instance.Respawn(HeroController.instance.transform));
						},
						BossPathFromRoot = new string[1] { "Boss Scene/Phantom" },
						TransitionDelay = 0f,
						ScaleHealth = ScaleToShiningNail
					}
				}
			},
			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;
						},
						AfterEnter = delegate
						{
							ScaleTransitionHP("Boss Scene/Lace Boss1", "Control", NailType.Old, "Rage HP");
						},
						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"
						},
						AfterEnter = delegate
						{
							ScaleTransitionHP("Boss Scene/Lace Boss2 New", "Control", NailType.Shining, "P2 HP", "P3 HP");
							GameObject obj4 = GameObject.Find("Boss Scene/Lace Boss2 New");
							PlayMakerFSM val2 = ((obj4 != null) ? FSMUtility.LocateMyFSM(obj4, "Control") : null);
							if (val2 != null)
							{
								val2.SendEvent("BATTLE START REFIGHT");
							}
						},
						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
						{
						},
						AfterEnter = delegate
						{
							ScaleTransitionHP("Silk Boss", "Phase Control", NailType.Shining, "P1 HP", "P2 HP", "P3 HP", "P4 HP", "P5 HP", "P6 HP");
						},
						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
						{
							GameObject obj3 = GameObject.Find("Hornet Dummy");
							if (obj3 != null)
							{
								obj3.SetActive(false);
							}
						},
						AfterExit = delegate
						{
							CoroutineUtil.WaitAndExecute(0.1f, delegate
							{
								GameObject obj2 = GameObject.Find("Hornet Dummy");
								if (obj2 != null)
								{
									obj2.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
						{
							//IL_0025: Unknown result type (might be due to invalid IL or missing references)
							//IL_002a: Unknown result type (might be due to invalid IL or missing references)
							//IL_0033: Unknown result type (might be due to invalid IL or missing references)
							//IL_0034: Unknown result type (might be due to invalid IL or missing references)
							//IL_004d: Unknown result type (might be due to invalid IL or missing references)
							PlayerData.instance.mapperMentorConvo = true;
							PlayerData.instance.mapperSparIntro = true;
							Completion data = ((SerializableNamedList<Completion, NamedCompletion>)(object)PlayerData.instance.QuestCompletionData).GetData("Shakra Final Quest");
							CacheStack<Completion>.Cache(data);
							((SerializableNamedList<Completion, NamedCompletion>)(object)PlayerData.instance.QuestCompletionData).SetData("Shakra Final Quest", QuestCompletionData.Completed);
						},
						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");
							}
						},
						OnExit = delegate
						{
							//IL_0000: Unknown result type (might be due to invalid IL or missing references)
							//IL_0005: Unknown result type (might be due to invalid IL or missing references)
							//IL_0015: Unknown result type (might be due to invalid IL or missing references)
							Completion val = CacheStack<Completion>.Get();
							((SerializableNamedList<Completion, NamedCompletion>)(object)PlayerData.instance.QuestCompletionData).SetData("Shakra Final Quest", val);
						},
						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.TryGetValue("Crawl_10", out var value) && value.TryGetValue("Blue Assistant", out var value2))
							{
								value2.Value = false;
							}
						},
						OnExit = delegate
						{
							CacheUtils.Restore();
						},
						TransitionDelay = 3f,
						CustomSpawnPoint = new Vector2(32f, 8f)
					}
				}
			}
		};

		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 float GetNailDamage(NailType type)
		{
			return type switch
			{
				NailType.Old => 5f, 
				NailType.Sharpened => 9f, 
				NailType.Shining => 13f, 
				NailType.Hivesteel => 17f, 
				NailType.Palesteel => 21f, 
				_ => throw new NotImplementedException(), 
			};
		}

		private static float GetMultiplier(NailType type)
		{
			float num = GetNailDamage(NailType.Palesteel) / GetNailDamage(type);
			return Mathf.Max(1f, num);
		}

		private static void ScaleToNail(HealthManager hm, NailType type)
		{
			hm.hp = Mathf.CeilToInt(GetMultiplier(type) * (float)hm.hp);
			hm.initHp = hm.hp;
			PopLogger.Log($"Scaled health for {((Component)hm).gameObject} to {hm.hp}");
		}

		private static void ScaleTransitionHP(string boss_path, string fsm_name, NailType type, params string[] variables)
		{
			GameObject val = GameObject.Find(boss_path) ?? GameObjectUtil.FindGameObjectFromScene(boss_path);
			if (val == null)
			{
				PopLogger.Log("Could not find boss to scale HP");
				return;
			}
			PlayMakerFSM val2 = FSMUtility.LocateMyFSM(val, fsm_name);
			if (val2 == null)
			{
				PopLogger.Log("could not find fsm for scaling");
				return;
			}
			foreach (string text in variables)
			{
				FsmInt fsmInt = val2.FsmVariables.GetFsmInt(text);
				if (fsmInt == null)
				{
					PopLogger.Log("Could not find fsm int: " + text);
					continue;
				}
				fsmInt.Value = Mathf.CeilToInt((float)fsmInt.Value * GetMultiplier(type));
				PopLogger.Log($"Setting {text} to {fsmInt.Value}");
			}
			PopLogger.Log($"Patched transition hps for {val}");
		}

		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 interface IBindings
	{
		void ApplyBindings();

		void RestoreBindings();
	}
	public class HealthBindings : IBindings
	{
		[CompilerGenerated]
		private int <boundMax>P;

		private List<GameObject> _overlays;

		private List<GameObject> _modifiedHealthDisplays;

		private int _prevMaxHealth;

		public bool Active { get; private set; }

		public HealthBindings(int boundMax)
		{
			<boundMax>P = boundMax;
			_overlays = new List<GameObject>();
			_modifiedHealthDisplays = new List<GameObject>();
			base..ctor();
		}

		public void ApplyUI()
		{
			_overlays.Clear();
			Transform hudCanvas = Bindings.HudCanvas;
			GameObject health = ((Component)hudCanvas.Find("Health")).gameObject;
			PopLogger.Log($"Found health {health}");
			foreach (PlayMakerFSM item in from i in Enumerable.Range(0, health.transform.childCount)
				select FSMUtility.LocateMyFSM(((Component)health.transform.GetChild(i)).gameObject, "health_display"))
			{
				if (item != null)
				{
					FsmInt fsmInt = item.FsmVariables.GetFsmInt("Health Number");
					int? num = ((fsmInt != null) ? new int?(fsmInt.Value) : null);
					if (num.HasValue && num.Value > <boundMax>P && num.Value <= 10 && num.Value <= _prevMaxHealth)
					{
						((Behaviour)item).enabled = false;
						GameObject gameObject = ((Component)item).gameObject;
						PopLogger.Log($"Found health display for health number {num.Value} at {gameObject}");
						GameObject gameObject2 = ((Component)((Component)gameObject.transform.Find("Idle")).gameObject.transform.parent).gameObject;
						gameObject2.SetActive(false);
						_modifiedHealthDisplays.Add(gameObject2);
					}
				}
			}
			EventRegister.SendEvent(EventRegisterEvents.HealthUpdate, (GameObject)null);
			EventRegister.SendEvent(EventRegisterEvents.HeroHealed, (GameObject)null);
			EventRegister.SendEvent(EventRegisterEvents.HeroHealedToMax, (GameObject)null);
		}

		public void RestoreUI()
		{
			foreach (GameObject overlay in _overlays)
			{
				if (overlay != null)
				{
					overlay.SetActive(false);
				}
			}
			_overlays.Clear();
			foreach (GameObject modifiedHealthDisplay in _modifiedHealthDisplays)
			{
				if (modifiedHealthDisplay != null)
				{
					modifiedHealthDisplay.SetActive(true);
				}
			}
			EventRegister.SendEvent(EventRegisterEvents.HealthUpdate, (GameObject)null);
			EventRegister.SendEvent(EventRegisterEvents.HeroHealed, (GameObject)null);
		}

		public void ApplyBindings()
		{
			Active = true;
			_prevMaxHealth = PlayerData.instance.maxHealth;
			PlayerData.instance.maxHealth = <boundMax>P;
			PlayerData.instance.maxHealthBase = <boundMax>P;
			PlayerData.instance.health = Mathf.Min(<boundMax>P, PlayerData.instance.health);
			ApplyUI();
		}

		public void RestoreBindings()
		{
			Active = false;
			PlayerData.instance.maxHealth = _prevMaxHealth;
			PlayerData.instance.health = _prevMaxHealth;
			PlayerData.instance.maxHealthBase = _prevMaxHealth;
			RestoreUI();
		}
	}
	public class SilkBindings : IBindings
	{
		[CompilerGenerated]
		private int <maxSilk>P;

		private int _prevSilk;

		public bool Active { get; private set; }

		public SilkBindings(int maxSilk)
		{
			<maxSilk>P = maxSilk;
			base..ctor();
		}

		private void ApplyUI()
		{
			EventRegister.SendEvent(EventRegisterEvents.RegeneratedSilkChunk, (GameObject)null);
		}

		private void RestoreUI()
		{
			EventRegister.SendEvent(EventRegisterEvents.RegeneratedSilkChunk, (GameObject)null);
		}

		public void ApplyBindings()
		{
			_prevSilk = PlayerData.instance.silkMax;
			PlayerData.instance.silkMax = <maxSilk>P;
			PlayerData.instance.silk = Mathf.Min(<maxSilk>P, PlayerData.instance.silk);
			ApplyUI();
			Active = true;
		}

		public void RestoreBindings()
		{
			PlayerData.instance.silkMax = _prevSilk;
			Active = false;
			RestoreUI();
		}
	}
	public class NailBindings : IBindings
	{
		[CompilerGenerated]
		private float <multiplier>P;

		public float Multiplier => <multiplier>P;

		public bool Active { get; private set; }

		public NailBindings(float multiplier)
		{
			<multiplier>P = multiplier;
			base..ctor();
		}

		public void ApplyBindings()
		{
			Hooks.EnableBoundNail();
			Active = true;
		}

		public void RestoreBindings()
		{
			Hooks.DisableBoundNail();
			Active = false;
		}
	}
	public class SkillBindings : IBindings
	{
		private Dictionary<string, List<string>> _removedTools = new Dictionary<string, List<string>>();

		public bool Active { get; private set; }

		public void ApplyBindings()
		{
			Active = true;
			_removedTools = CrestUtil.RemoveAllTools((ToolItemType x) => (int)x != 3);
			Hooks.EnablePreventToolUse();
		}

		public void RestoreBindings()
		{
			Active = false;
			CrestUtil.RestoreAllTools(_removedTools, (ToolItemType x) => (int)x != 3);
			Hooks.DisablePreventToolUse();
		}
	}
	public class ToolBindings : IBindings
	{
		private Dictionary<string, List<string>> _removedTools = new Dictionary<string, List<string>>();

		public bool Active { get; private set; }

		public void ApplyBindings()
		{
			Active = true;
			_removedTools = CrestUtil.RemoveAllTools((ToolItemType x) => (int)x == 3);
			Hooks.EnablePreventToolUse();
		}

		public void RestoreBindings()
		{
			Active = false;
			CrestUtil.RestoreAllTools(_removedTools, (ToolItemType x) => (int)x == 3);
			Hooks.DisablePreventToolUse();
		}
	}
	public static class Bindings
	{
		public static HealthBindings HealthBindings = new HealthBindings(4);

		public static SilkBindings SilkBindings = new SilkBindings(9);

		public static NailBindings NailBindings = new NailBindings(0.6f);

		public static SkillBindings SkillBindings = new SkillBindings();

		public static ToolBindings ToolBindings = new ToolBindings();

		public static Transform HudCanvas => ((Component)GameCameras.instance.hudCamera).transform.Find("In-game/Anchor TL/Hud Canvas Offset/Hud Canvas");

		private static void Reset()
		{
			HealthBindings = new HealthBindings(4);
			SilkBindings = new SilkBindings(9);
			NailBindings = new NailBindings(0.6f);
			SkillBindings = new SkillBindings();
			ToolBindings = new ToolBindings();
		}
	}
	public class Hooks
	{
		public enum HookBehavior
		{
			DoubleDamage,
			InfiniteDamage,
			BoundNail,
			PreventToolUse
		}

		private static readonly Dictionary<HookBehavior, ToggleableHook> _hooks = new Dictionary<HookBehavior, ToggleableHook>();

		private static Action<Action<PlayerData, int, bool, bool>, PlayerData, int, bool, bool> CreateDamageHook(int multiplier, bool absolute)
		{
			return delegate(Action<PlayerData, int, bool, bool> orig, PlayerData self, int amount, bool blue, bool mask)
			{
				PopLogger.Log($"calling orig with damage: {multiplier * amount}");
				orig(self, multiplier * amount, blue, !absolute && mask);
			};
		}

		private static void BindNailDamageHook(Action<HealthManager, HitInstance> orig, HealthManager self, HitInstance hit)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Invalid comparison between Unknown and I4
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: 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)
			//IL_0019: Invalid comparison between Unknown and I4
			if ((int)hit.AttackType == 0 || (int)hit.AttackType == 7 || (int)hit.AttackType == 16)
			{
				hit.DamageDealt = Math.Min(hit.DamageDealt, Mathf.CeilToInt((float)PlayerData.instance.nailDamage * Bindings.NailBindings.Multiplier));
			}
			orig(self, hit);
		}

		private static bool InventoryToolSlotHook(Func<InventoryItemTool, bool> orig, InventoryItemTool self)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			if ((int)self.ToolType == 3)
			{
				if (Bindings.SkillBindings.Active)
				{
					PopLogger.Log("Preventing tool use for " + ((Object)self).name);
					return false;
				}
			}
			else if (Bindings.ToolBindings.Active)
			{
				PopLogger.Log("Preventing tool use for " + ((Object)self).name);
				return false;
			}
			return orig(self);
		}

		public static void Initialize()
		{
			_hooks[HookBehavior.DoubleDamage] = new ToggleableHook(AccessTools.DeclaredMethod(typeof(PlayerData), "TakeHealth", (Type[])null, (Type[])null), CreateDamageHook(2, absolute: false));
			_hooks[HookBehavior.InfiniteDamage] = new ToggleableHook(AccessTools.DeclaredMethod(typeof(PlayerData), "TakeHealth", (Type[])null, (Type[])null), CreateDamageHook(56, absolute: true));
			_hooks[HookBehavior.BoundNail] = new ToggleableHook(AccessTools.DeclaredMethod(typeof(HealthManager), "TakeDamage", (Type[])null, (Type[])null), new Action<Action<HealthManager, HitInstance>, HealthManager, HitInstance>(BindNailDamageHook));
			_hooks[HookBehavior.PreventToolUse] = new ToggleableHook(AccessTools.DeclaredMethod(typeof(InventoryItemTool), "Submit", (Type[])null, (Type[])null), new Func<Func<InventoryItemTool, bool>, InventoryItemTool, bool>(InventoryToolSlotHook));
		}

		public static void EnableDoubleDamage()
		{
			PopLogger.Log("enabling double damage");
			_hooks[HookBehavior.DoubleDamage].Enable();
		}

		public static void DisableDoubleDamage()
		{
			PopLogger.Log("disabling double damage");
			_hooks[HookBehavior.DoubleDamage].Disable();
		}

		public static void EnableInfiniteDamage()
		{
			_hooks[HookBehavior.InfiniteDamage].Enable();
		}

		public static void DisableInfiniteDamage()
		{
			_hooks[HookBehavior.InfiniteDamage].Disable();
		}

		public static void EnableBoundNail()
		{
			_hooks[HookBehavior.BoundNail].Enable();
		}

		public static void DisableBoundNail()
		{
			_hooks[HookBehavior.BoundNail].Disable();
		}

		public static void EnablePreventToolUse()
		{
			_hooks[HookBehavior.PreventToolUse].Enable();
		}

		public static void DisablePreventToolUse()
		{
			if (!Bindings.SkillBindings.Active && !Bindings.ToolBindings.Active)
			{
				_hooks[HookBehavior.PreventToolUse].Disable();
			}
		}
	}
	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.3.2")]
	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")
				{
					List<EnemyJournalRecord> list = new List<EnemyJournalRecord>();
					foreach (EnemyJournalRecord item in from x in EnemyJournalManager.GetAllEnemies()
						where BossRegistry.ValidRecords.Contains(((Object)x).name)
						select x)
					{
						if ((((Object)item).name == "Shakra" || ((Object)item).name == "Blue Assistant") && PlayerData.instance.blackThreadWorld)
						{
							item.isAlwaysUnlocked = true;
						}
						list.Add(item);
					}
					__result = list;
					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();
			Hooks.Initialize();
			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)
				{