Decompiled source of ReincarnationDisplay v1.0.1

plugins/ReincarnationDisplay/ReincarnationDisplay.dll

Decompiled 4 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HG;
using Microsoft.CodeAnalysis;
using RiskOfOptions;
using RiskOfOptions.OptionConfigs;
using RiskOfOptions.Options;
using RoR2;
using RoR2.EntityLogic;
using RoR2.UI;
using TMPro;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.Rendering;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("RoR2")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("ReincarnationDisplay")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1+6f3ba661d519d343e5ffd10432c3ac7892369056")]
[assembly: AssemblyProduct("ReincarnationDisplay")]
[assembly: AssemblyTitle("ReincarnationDisplay")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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;
		}
	}
}
namespace ReincarnationDisplay
{
	internal sealed class PluginConfig
	{
		public readonly ConfigEntry<bool> ShowPanel;

		public readonly ConfigEntry<bool> ShowZoneIndicator;

		public readonly ConfigEntry<float> PanelOffsetY;

		public readonly ConfigEntry<float> PanelScale;

		public readonly ConfigEntry<bool> ShowWorldRings;

		public readonly ConfigEntry<float> RingMaxDistance;

		public readonly ConfigEntry<float> StageStartWindowSeconds;

		public readonly ConfigEntry<bool> HideStageStartZoneAfterWindow;

		public readonly ConfigEntry<bool> DebugLogging;

		public readonly ConfigEntry<bool> DebugAlwaysShow;

		public readonly ConfigEntry<KeyboardShortcut> DumpZonesKey;

		public PluginConfig(ConfigFile config)
		{
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			ShowPanel = config.Bind<bool>("Panel", "ShowPanel", true, "Show the panel above the N'tormat icon while standing in a valid sacrifice zone.");
			ShowZoneIndicator = config.Bind<bool>("Panel", "ShowZoneIndicator", true, "When not standing in a zone, show a one-line hint above the N'tormat icon if the stage has a sacrifice zone. The stage-start reroll zone doesn't count.");
			PanelOffsetY = config.Bind<float>("Panel", "PanelOffsetY", -6f, "Vertical gap, in UI pixels, between the panel and whatever sits above the N'tormat icon (such as the page selector).");
			PanelScale = config.Bind<float>("Panel", "PanelScale", 1f, "Scale multiplier for the panel.");
			ShowWorldRings = config.Bind<bool>("World", "ShowWorldRings", true, "Draw rings on the ground marking the edge of each valid sacrifice zone.");
			RingMaxDistance = config.Bind<float>("World", "RingMaxDistance", 300f, "Rings further than this many meters away are hidden.");
			StageStartWindowSeconds = config.Bind<float>("Timing", "StageStartWindowSeconds", 30f, "Fallback length of the stage-start reroll window, used only if the zone has no timer of its own.");
			HideStageStartZoneAfterWindow = config.Bind<bool>("Timing", "HideStageStartZoneAfterWindow", true, "Stop treating the stage-start zone as valid once the window has elapsed.");
			DebugLogging = config.Bind<bool>("Debug", "DebugLogging", false, "Log every sacrifice zone as it appears, and enable the zone dump key.");
			DebugAlwaysShow = config.Bind<bool>("Debug", "DebugAlwaysShow", false, "Show the panel and zone rings even without a Reincarnation page, for testing.");
			DumpZonesKey = config.Bind<KeyboardShortcut>("Debug", "DumpZonesKey", new KeyboardShortcut((KeyCode)289, Array.Empty<KeyCode>()), "With DebugLogging on, press to log every sacrifice zone in the current stage.");
		}
	}
	internal sealed class ReincarnationDisplayController : MonoBehaviour
	{
		private const float BuffMismatchGrace = 0.5f;

		private readonly List<ZoneInfo> zones = new List<ZoneInfo>();

		private HUD hud;

		private ZoneHudPanel panel;

		private ZoneWorldRings rings;

		private GameObject cachedBodyObject;

		private CharacterBody cachedBody;

		private float buffMismatchTime;

		private bool reportedBuffMismatch;

		private void Awake()
		{
			hud = ((Component)this).GetComponent<HUD>();
			rings = ZoneWorldRings.Create();
		}

		private void OnDestroy()
		{
			if (Object.op_Implicit((Object)(object)rings))
			{
				Object.Destroy((Object)(object)((Component)rings).gameObject);
			}
		}

		private void Update()
		{
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			PluginConfig settings = ReincarnationDisplayPlugin.Settings;
			CharacterBody targetBody = GetTargetBody();
			zones.Clear();
			int num = -1;
			PageState pageState = ZoneScanner.GetPageState(targetBody);
			PageState pageState2 = pageState;
			if (pageState2 == PageState.None && settings.DebugAlwaysShow.Value && Object.op_Implicit((Object)(object)targetBody))
			{
				pageState2 = PageState.Usable;
			}
			bool num2 = pageState2 != PageState.None;
			if (num2)
			{
				num = ZoneScanner.Scan(targetBody, zones);
			}
			if (settings.DebugLogging.Value)
			{
				ZoneDebugDump.LogNewZones();
				ReportBuffMismatch(targetBody, pageState == PageState.Usable, num >= 0);
			}
			if (!Object.op_Implicit((Object)(object)panel) && Object.op_Implicit((Object)(object)hud.keyItemIcon))
			{
				panel = ZoneHudPanel.Create(hud.keyItemIcon);
			}
			if (Object.op_Implicit((Object)(object)panel))
			{
				int num3 = CountIndicatorZones();
				if (settings.ShowPanel.Value && num >= 0)
				{
					string disabledCause = ((pageState2 == PageState.Disabled) ? ZoneScanner.DescribeDisabledCause(targetBody) : null);
					panel.Show(zones[num], disabledCause);
				}
				else if (settings.ShowZoneIndicator.Value && num3 > 0)
				{
					panel.ShowIndicator(num3, pageState2 == PageState.Disabled);
				}
				else
				{
					panel.Hide();
				}
			}
			if (!Object.op_Implicit((Object)(object)rings))
			{
				rings = ZoneWorldRings.Create();
			}
			if (num2 && settings.ShowWorldRings.Value)
			{
				rings.UpdateRings(zones, targetBody.corePosition, settings.RingMaxDistance.Value);
			}
			else
			{
				rings.Clear();
			}
		}

		private int CountIndicatorZones()
		{
			int num = 0;
			foreach (ZoneInfo zone in zones)
			{
				if (!zone.IsStageStart)
				{
					num++;
				}
			}
			return num;
		}

		private CharacterBody GetTargetBody()
		{
			GameObject targetBodyObject = hud.targetBodyObject;
			if ((Object)(object)targetBodyObject != (Object)(object)cachedBodyObject)
			{
				cachedBodyObject = targetBodyObject;
				cachedBody = (Object.op_Implicit((Object)(object)targetBodyObject) ? targetBodyObject.GetComponent<CharacterBody>() : null);
			}
			return cachedBody;
		}

		private void ReportBuffMismatch(CharacterBody body, bool usable, bool inZone)
		{
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			bool flag = usable && ZoneScanner.HasReadyBuff(body);
			if (!usable || flag == inZone)
			{
				buffMismatchTime = 0f;
				reportedBuffMismatch = false;
				return;
			}
			buffMismatchTime += Time.deltaTime;
			if (buffMismatchTime >= 0.5f && !reportedBuffMismatch)
			{
				reportedBuffMismatch = true;
				ReincarnationDisplayPlugin.Log.LogWarning((object)$"In-zone mismatch: local check says {inZone}, server buff says {flag} at {body.corePosition}");
			}
		}
	}
	[BepInPlugin("sevenstack.ReincarnationDisplay", "ReincarnationDisplay", "1.0.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class ReincarnationDisplayPlugin : BaseUnityPlugin
	{
		public const string PluginGUID = "sevenstack.ReincarnationDisplay";

		public const string PluginName = "ReincarnationDisplay";

		public const string PluginVersion = "1.0.1";

		internal static ManualLogSource Log;

		internal static PluginConfig Settings;

		private void Awake()
		{
			Log = ((BaseUnityPlugin)this).Logger;
			Settings = new PluginConfig(((BaseUnityPlugin)this).Config);
			if (RiskOfOptionsCompat.Enabled)
			{
				RiskOfOptionsCompat.Register(Settings);
			}
			HUD.onHudTargetChangedGlobal += OnHudTargetChanged;
		}

		private void OnDestroy()
		{
			HUD.onHudTargetChangedGlobal -= OnHudTargetChanged;
		}

		private void Update()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			if (Settings.DebugLogging.Value)
			{
				KeyboardShortcut value = Settings.DumpZonesKey.Value;
				if (((KeyboardShortcut)(ref value)).IsDown())
				{
					ZoneDebugDump.DumpAll();
				}
			}
		}

		private static void OnHudTargetChanged(HUD hud)
		{
			if (Object.op_Implicit((Object)(object)hud) && !Object.op_Implicit((Object)(object)((Component)hud).GetComponent<ReincarnationDisplayController>()))
			{
				((Component)hud).gameObject.AddComponent<ReincarnationDisplayController>();
			}
		}
	}
	internal static class RiskOfOptionsCompat
	{
		public const string GUID = "com.rune580.riskofoptions";

		private const string IconResource = "ReincarnationDisplay.icon.png";

		public static bool Enabled => Chainloader.PluginInfos.ContainsKey("com.rune580.riskofoptions");

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		public static void Register(PluginConfig settings)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected O, but got Unknown
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Expected O, but got Unknown
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Expected O, but got Unknown
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Expected O, but got Unknown
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Expected O, but got Unknown
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Expected O, but got Unknown
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Expected O, but got Unknown
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Expected O, but got Unknown
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Expected O, but got Unknown
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Expected O, but got Unknown
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Expected O, but got Unknown
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Expected O, but got Unknown
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Expected O, but got Unknown
			ModSettingsManager.SetModDescription("Shows the Reincarnation page's sacrifice zones, where a sacrifice will send you, and the stage-start window.");
			Sprite val = LoadIcon();
			if (Object.op_Implicit((Object)(object)val))
			{
				ModSettingsManager.SetModIcon(val);
			}
			ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(settings.ShowPanel));
			ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(settings.ShowZoneIndicator));
			ModSettingsManager.AddOption((BaseOption)new StepSliderOption(settings.PanelOffsetY, new StepSliderConfig
			{
				min = -50f,
				max = 200f,
				increment = 1f,
				FormatString = "{0:0}px"
			}));
			ModSettingsManager.AddOption((BaseOption)new StepSliderOption(settings.PanelScale, new StepSliderConfig
			{
				min = 0.5f,
				max = 2f,
				increment = 0.05f,
				FormatString = "{0:0.00}x"
			}));
			ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(settings.ShowWorldRings));
			ModSettingsManager.AddOption((BaseOption)new StepSliderOption(settings.RingMaxDistance, new StepSliderConfig
			{
				min = 25f,
				max = 1000f,
				increment = 25f,
				FormatString = "{0:0}m"
			}));
			ModSettingsManager.AddOption((BaseOption)new StepSliderOption(settings.StageStartWindowSeconds, new StepSliderConfig
			{
				min = 5f,
				max = 120f,
				increment = 1f,
				FormatString = "{0:0}s"
			}));
			ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(settings.HideStageStartZoneAfterWindow));
			ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(settings.DebugLogging));
			ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(settings.DebugAlwaysShow));
		}

		private static Sprite LoadIcon()
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			using Stream stream = typeof(RiskOfOptionsCompat).Assembly.GetManifestResourceStream("ReincarnationDisplay.icon.png");
			if (stream == null)
			{
				return null;
			}
			using MemoryStream memoryStream = new MemoryStream();
			stream.CopyTo(memoryStream);
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
			if (!ImageConversion.LoadImage(val, memoryStream.ToArray()))
			{
				return null;
			}
			return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f));
		}
	}
	internal static class ZoneDebugDump
	{
		private static readonly HashSet<int> loggedZoneIds = new HashSet<int>();

		private static readonly List<SceneDef> candidates = new List<SceneDef>();

		public static void LogNewZones()
		{
			foreach (CursedBookSacrificeZone instance in CursedBookSacrificeZone.instanceList)
			{
				if (Object.op_Implicit((Object)(object)instance) && loggedZoneIds.Add(((Object)instance).GetInstanceID()))
				{
					LogZone(instance, "New sacrifice zone");
				}
			}
		}

		public static void DumpAll()
		{
			//IL_0018: 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)
			float num;
			if (!Object.op_Implicit((Object)(object)Stage.instance))
			{
				num = -1f;
			}
			else
			{
				FixedTimeStamp entryTime = Stage.instance.entryTime;
				num = ((FixedTimeStamp)(ref entryTime)).timeSince;
			}
			float num2 = num;
			ManualLogSource log = ReincarnationDisplayPlugin.Log;
			SceneDef mostRecentSceneDef = SceneCatalog.mostRecentSceneDef;
			log.LogInfo((object)($"=== Sacrifice zone dump: scene={((mostRecentSceneDef != null) ? mostRecentSceneDef.cachedName : null)} stageAge={num2:0.00}s " + $"zones={CursedBookSacrificeZone.instanceList.Count} ==="));
			foreach (CursedBookSacrificeZone instance2 in CursedBookSacrificeZone.instanceList)
			{
				if (Object.op_Implicit((Object)(object)instance2))
				{
					LogZone(instance2, "Sacrifice zone");
				}
			}
			DLC4SacrificeZoneSpawner instance = DLC4SacrificeZoneSpawner.instance;
			GameObject val = ((Object.op_Implicit((Object)(object)instance) && Object.op_Implicit((Object)(object)instance.reincarnateCard)) ? instance.reincarnateCard.prefab : null);
			if (Object.op_Implicit((Object)(object)val))
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("Stage-start spawn card prefab '" + ((Object)val).name + "':");
				AppendComponents(stringBuilder, val);
				ReincarnationDisplayPlugin.Log.LogInfo((object)stringBuilder.ToString());
			}
			else
			{
				ReincarnationDisplayPlugin.Log.LogInfo((object)"No DLC4SacrificeZoneSpawner in this scene.");
			}
		}

		private static void LogZone(CursedBookSacrificeZone zone, string title)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a0: Unknown result type (might be due to invalid IL or missing references)
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine($"{title} '{GetPath(((Component)zone).transform)}' active={((Component)zone).gameObject.activeInHierarchy} position={((Component)zone).transform.position}");
			stringBuilder.AppendLine($"  behaviour={zone.behaviour} isDisabled={zone.isDisabled} " + $"runFlag={zone.runFlagCondition}:'{zone.runFlagName}'={zone.runFlagConditionResult} pageRequirement={zone.pageRequirement}");
			string[] obj = new string[7]
			{
				$"  reroll={zone.useRerollSceneInstead} next={zone.useNextSceneInstead} explicit={zone.useExplicitSceneInstead} ",
				"explicitScene=",
				null,
				null,
				null,
				null,
				null
			};
			SceneDef explicitScene = zone.explicitScene;
			obj[2] = ((explicitScene != null) ? explicitScene.cachedName : null);
			obj[3] = " sceneCollection=";
			SceneCollection sceneCollection = zone.sceneCollection;
			obj[4] = ((sceneCollection != null) ? ((Object)sceneCollection).name : null);
			obj[5] = " ";
			SceneTierCollection sceneTierCollection = zone.sceneTierCollection;
			obj[6] = $"sceneTierCollection={((sceneTierCollection != null) ? ((Object)sceneTierCollection).name : null)} doNotIncrementStageNumber={zone.doNotIncrementStageNumber}";
			stringBuilder.AppendLine(string.Concat(obj));
			stringBuilder.AppendLine("  shape=" + DescribeShape(zone.zone));
			Timer component = ((Component)zone).GetComponent<Timer>();
			if (Object.op_Implicit((Object)(object)component))
			{
				float num;
				if (!Object.op_Implicit((Object)(object)Stage.instance))
				{
					num = -1f;
				}
				else
				{
					FixedTimeStamp entryTime = Stage.instance.entryTime;
					num = ((FixedTimeStamp)(ref entryTime)).timeSince;
				}
				float num2 = num;
				stringBuilder.AppendLine($"  timer running={component.timerRunning} stopwatch={component.stopwatch:0.00}/{component.duration} stageAge={num2:0.00}s");
			}
			if (Object.op_Implicit((Object)(object)Run.instance))
			{
				bool keepsStageCount;
				string arg = ZoneScanner.DescribeOutcome(zone, out keepsStageCount);
				stringBuilder.AppendLine($"  outcome='{arg}' keepsStageCount={keepsStageCount}");
				if (!zone.useExplicitSceneInstead && !zone.useNextSceneInstead && !zone.useRerollSceneInstead)
				{
					ZoneScanner.GetCollectionCandidates(zone, candidates);
					stringBuilder.Append("  candidates:");
					foreach (SceneDef candidate in candidates)
					{
						stringBuilder.Append($" {candidate.cachedName} ({ZoneScanner.SceneName(candidate)}, {candidate.sceneType})");
					}
					stringBuilder.AppendLine();
				}
			}
			AppendComponents(stringBuilder, ((Component)zone).gameObject);
			ReincarnationDisplayPlugin.Log.LogInfo((object)stringBuilder.ToString());
		}

		private static string DescribeShape(IZone zone)
		{
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			VerticalTubeZone val = (VerticalTubeZone)(object)((zone is VerticalTubeZone) ? zone : null);
			if (val == null)
			{
				SphereZone val2 = (SphereZone)(object)((zone is SphereZone) ? zone : null);
				if (val2 == null)
				{
					BoxZone val3 = (BoxZone)(object)((zone is BoxZone) ? zone : null);
					if (val3 == null)
					{
						if (zone == null)
						{
							return "none";
						}
						return ((object)zone).GetType().FullName;
					}
					return $"BoxZone halfExtents={((Component)val3).transform.lossyScale * 0.5f} inverted={val3.isInverted} enabled={((Behaviour)val3).enabled}";
				}
				return $"SphereZone radius={val2.radius} inverted={val2.isInverted} enabled={((Behaviour)val2).enabled}";
			}
			return $"VerticalTubeZone radius={val.radius} enabled={((Behaviour)val).enabled}";
		}

		private static void AppendComponents(StringBuilder builder, GameObject root)
		{
			Component[] componentsInChildren = root.GetComponentsInChildren<Component>(true);
			foreach (Component val in componentsInChildren)
			{
				if (!Object.op_Implicit((Object)(object)val))
				{
					continue;
				}
				Type type = ((object)val).GetType();
				builder.Append("  [" + GetPath(val.transform) + "] " + type.FullName);
				Behaviour val2 = (Behaviour)(object)((val is Behaviour) ? val : null);
				if (val2 != null)
				{
					builder.Append(val2.enabled ? "" : " (disabled)");
				}
				builder.AppendLine();
				if (type.Namespace != null && type.Namespace.StartsWith("UnityEngine"))
				{
					continue;
				}
				FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (FieldInfo fieldInfo in fields)
				{
					bool num = fieldInfo.IsPublic || fieldInfo.IsDefined(typeof(SerializeField), inherit: false);
					Type fieldType = fieldInfo.FieldType;
					if (num && (fieldType.IsPrimitive || fieldType.IsEnum || fieldType == typeof(string)))
					{
						builder.AppendLine($"      {fieldInfo.Name}={fieldInfo.GetValue(val)}");
					}
				}
			}
		}

		private static string GetPath(Transform transform)
		{
			string text = ((Object)transform).name;
			Transform parent = transform.parent;
			while (Object.op_Implicit((Object)(object)parent))
			{
				text = ((Object)parent).name + "/" + text;
				parent = parent.parent;
			}
			return text;
		}
	}
	internal sealed class ZoneHudPanel : MonoBehaviour
	{
		private enum Mode
		{
			Zone,
			Indicator
		}

		private const float PanelWidth = 260f;

		private const float FontSize = 15f;

		private const float FadeDuration = 0.15f;

		private const float ScreenEdgeMargin = 4f;

		private static readonly Color BackgroundColor = new Color(0.07f, 0.03f, 0.1f, 0.85f);

		private const string HeaderColor = "#C38BFF";

		private const string DisabledHeaderColor = "#FF5A5A";

		private const string NoteColor = "#A0A0A0";

		private const string WindowColor = "#E6D9FF";

		private const string WindowWarningColor = "#FFC24D";

		private const string WindowCriticalColor = "#FF5A5A";

		private RectTransform rectTransform;

		private RectTransform canvasRectTransform;

		private KeyItemIcon icon;

		private RectTransform iconRectTransform;

		private CanvasGroup canvasGroup;

		private ContentSizeFitter fitter;

		private TextMeshProUGUI label;

		private readonly Vector3[] corners = (Vector3[])(object)new Vector3[4];

		private readonly Vector3[] canvasCorners = (Vector3[])(object)new Vector3[4];

		private bool visible;

		private Mode mode;

		private bool textDirty = true;

		private int shownIndicatorCount;

		private bool shownIndicatorDisabled;

		private CursedBookSacrificeZone describedZone;

		private string outcome;

		private bool keepsStageCount;

		private int shownWindowTenths = int.MinValue;

		private string shownDisabledCause;

		public static ZoneHudPanel Create(KeyItemIcon icon)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: 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_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Expected O, but got Unknown
			//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_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Expected O, but got Unknown
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("ReincarnationZonePanel", new Type[1] { typeof(RectTransform) });
			val.layer = ((Component)icon).gameObject.layer;
			RectTransform val2 = (RectTransform)val.transform;
			((Transform)val2).SetParent(((Component)icon).transform, false);
			Vector2 val3 = default(Vector2);
			((Vector2)(ref val3))..ctor(0.5f, 1f);
			val2.anchorMax = val3;
			val2.anchorMin = val3;
			val2.pivot = new Vector2(0.5f, 0f);
			val2.sizeDelta = new Vector2(260f, 0f);
			val.AddComponent<LayoutElement>().ignoreLayout = true;
			Image obj = val.AddComponent<Image>();
			((Graphic)obj).color = BackgroundColor;
			((Graphic)obj).raycastTarget = false;
			VerticalLayoutGroup obj2 = val.AddComponent<VerticalLayoutGroup>();
			((LayoutGroup)obj2).padding = new RectOffset(8, 8, 6, 6);
			((HorizontalOrVerticalLayoutGroup)obj2).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)obj2).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandWidth = true;
			((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandHeight = false;
			ContentSizeFitter val4 = val.AddComponent<ContentSizeFitter>();
			val4.horizontalFit = (FitMode)0;
			val4.verticalFit = (FitMode)2;
			CanvasGroup val5 = val.AddComponent<CanvasGroup>();
			val5.alpha = 0f;
			val5.interactable = false;
			val5.blocksRaycasts = false;
			GameObject val6 = new GameObject("Text", new Type[1] { typeof(RectTransform) })
			{
				layer = val.layer
			};
			val6.transform.SetParent((Transform)(object)val2, false);
			HGTextMeshProUGUI val7 = val6.AddComponent<HGTextMeshProUGUI>();
			((TMP_Text)val7).fontSize = 15f;
			((TMP_Text)val7).richText = true;
			((TMP_Text)val7).enableWordWrapping = true;
			((TMP_Text)val7).alignment = (TextAlignmentOptions)257;
			((Graphic)val7).color = Color.white;
			((Graphic)val7).raycastTarget = false;
			ZoneHudPanel zoneHudPanel = val.AddComponent<ZoneHudPanel>();
			zoneHudPanel.rectTransform = val2;
			zoneHudPanel.canvasGroup = val5;
			zoneHudPanel.fitter = val4;
			zoneHudPanel.label = (TextMeshProUGUI)(object)val7;
			zoneHudPanel.icon = icon;
			zoneHudPanel.iconRectTransform = (RectTransform)((Component)icon).transform;
			Canvas componentInParent = ((Component)icon).GetComponentInParent<Canvas>();
			zoneHudPanel.canvasRectTransform = ((!Object.op_Implicit((Object)(object)componentInParent)) ? ((RectTransform)null) : ((RectTransform)((Component)componentInParent.rootCanvas).transform));
			return zoneHudPanel;
		}

		public void Hide()
		{
			visible = false;
		}

		public void Show(ZoneInfo zone, string disabledCause)
		{
			visible = true;
			SetMode(Mode.Zone);
			if ((Object)(object)zone.Zone != (Object)(object)describedZone)
			{
				describedZone = zone.Zone;
				outcome = ZoneScanner.DescribeOutcome(zone.Zone, out keepsStageCount);
				textDirty = true;
			}
			int num = (zone.IsStageStart ? Mathf.Max(0, Mathf.CeilToInt(zone.WindowRemaining * 10f)) : (-1));
			if (textDirty || num != shownWindowTenths || disabledCause != shownDisabledCause)
			{
				textDirty = false;
				shownWindowTenths = num;
				shownDisabledCause = disabledCause;
				((TMP_Text)label).text = BuildText(num, disabledCause);
			}
		}

		public void ShowIndicator(int zoneCount, bool pageDisabled)
		{
			visible = true;
			SetMode(Mode.Indicator);
			if (textDirty || zoneCount != shownIndicatorCount || pageDisabled != shownIndicatorDisabled)
			{
				textDirty = false;
				shownIndicatorCount = zoneCount;
				shownIndicatorDisabled = pageDisabled;
				string text = ((zoneCount == 1) ? "Sacrifice zone on this stage" : (zoneCount + " sacrifice zones on this stage"));
				((TMP_Text)label).text = "<size=90%><color=#C38BFF>" + text + "</color>" + (pageDisabled ? " <color=#FF5A5A>(page disabled)</color>" : "") + "</size>";
			}
		}

		private void SetMode(Mode newMode)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			if (newMode != mode)
			{
				mode = newMode;
				textDirty = true;
				if (mode == Mode.Zone)
				{
					fitter.horizontalFit = (FitMode)0;
					rectTransform.sizeDelta = new Vector2(260f, rectTransform.sizeDelta.y);
					((TMP_Text)label).enableWordWrapping = true;
				}
				else
				{
					fitter.horizontalFit = (FitMode)2;
					((TMP_Text)label).enableWordWrapping = false;
				}
			}
		}

		private string BuildText(int windowTenths, string disabledCause)
		{
			string text = ((disabledCause == null) ? "<color=#C38BFF><b>REINCARNATION READY</b></color>" : ("<color=#FF5A5A><b>REINCARNATION DISABLED</b></color>\n<color=#FF5A5A>" + disabledCause + "</color>"));
			text = text + "\n<b>" + outcome + "</b>";
			if (keepsStageCount)
			{
				text += "\n<size=85%><color=#A0A0A0>Stage count unchanged</color></size>";
			}
			if (windowTenths >= 0)
			{
				float num = (float)windowTenths / 10f;
				string text2 = ((num <= 5f) ? "#FF5A5A" : ((num <= 10f) ? "#FFC24D" : "#E6D9FF"));
				text = text + "\n<color=" + text2 + ">Window closes in " + num.ToString("0.0") + "s</color>";
			}
			return text;
		}

		private void LateUpdate()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			PluginConfig settings = ReincarnationDisplayPlugin.Settings;
			((Transform)rectTransform).localScale = Vector3.one * settings.PanelScale.Value;
			float num = (visible ? 1f : 0f);
			if (visible || canvasGroup.alpha > 0f)
			{
				float contentTop = GetContentTop();
				Rect rect = iconRectTransform.rect;
				float num2 = contentTop - ((Rect)(ref rect)).yMax;
				rectTransform.anchoredPosition = new Vector2(0f, num2 + settings.PanelOffsetY.Value);
				KeepOnScreen();
			}
			canvasGroup.alpha = Mathf.MoveTowards(canvasGroup.alpha, num, Time.unscaledDeltaTime / 0.15f);
		}

		private float GetContentTop()
		{
			//IL_0006: 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)
			Rect rect = iconRectTransform.rect;
			float num = Mathf.Max(((Rect)(ref rect)).yMax, MeasureTop((Transform)(object)iconRectTransform));
			Transform val = (Object.op_Implicit((Object)(object)icon) ? icon.extraDisplayHolder : null);
			if (Object.op_Implicit((Object)(object)val) && !val.IsChildOf((Transform)(object)iconRectTransform))
			{
				num = Mathf.Max(num, MeasureTop(val));
			}
			return num;
		}

		private float MeasureTop(Transform node)
		{
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			float num = float.NegativeInfinity;
			if ((Object)(object)node == (Object)(object)rectTransform || !((Component)node).gameObject.activeInHierarchy)
			{
				return num;
			}
			RectTransform val = (RectTransform)(object)((node is RectTransform) ? node : null);
			if (val != null)
			{
				bool num2 = Object.op_Implicit((Object)(object)((Component)val).GetComponent<RectMask2D>()) || Object.op_Implicit((Object)(object)((Component)val).GetComponent<Mask>());
				Graphic component = ((Component)val).GetComponent<Graphic>();
				if (num2 || (Object.op_Implicit((Object)(object)component) && ((Behaviour)component).enabled))
				{
					val.GetWorldCorners(corners);
					num = Mathf.Max(((Transform)iconRectTransform).InverseTransformPoint(corners[1]).y, ((Transform)iconRectTransform).InverseTransformPoint(corners[2]).y);
				}
				if (num2)
				{
					return num;
				}
			}
			for (int i = 0; i < node.childCount; i++)
			{
				num = Mathf.Max(num, MeasureTop(node.GetChild(i)));
			}
			return num;
		}

		private void KeepOnScreen()
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: 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)
			if (!Object.op_Implicit((Object)(object)canvasRectTransform))
			{
				return;
			}
			Transform parent = ((Transform)rectTransform).parent;
			RectTransform val = (RectTransform)(object)((parent is RectTransform) ? parent : null);
			if (val != null)
			{
				rectTransform.GetWorldCorners(corners);
				canvasRectTransform.GetWorldCorners(canvasCorners);
				float num = 4f * ((Transform)canvasRectTransform).lossyScale.x;
				float num2 = 0f;
				if (corners[2].x > canvasCorners[2].x - num)
				{
					num2 = canvasCorners[2].x - num - corners[2].x;
				}
				else if (corners[0].x < canvasCorners[0].x + num)
				{
					num2 = canvasCorners[0].x + num - corners[0].x;
				}
				if (num2 != 0f && ((Transform)val).lossyScale.x > 0f)
				{
					RectTransform obj = rectTransform;
					obj.anchoredPosition += new Vector2(num2 / ((Transform)val).lossyScale.x, 0f);
				}
			}
		}
	}
	internal enum PageState
	{
		None,
		Usable,
		Disabled
	}
	internal enum ZoneShape
	{
		Tube,
		Sphere,
		Box,
		Everywhere,
		Unknown
	}
	internal struct ZoneInfo
	{
		public CursedBookSacrificeZone Zone;

		public ZoneShape Shape;

		public Vector3 Center;

		public float Radius;

		public Vector3 HalfExtents;

		public bool PlayerInside;

		public bool IsStageStart;

		public float WindowRemaining;
	}
	internal static class ZoneScanner
	{
		private const int ChampRushPageRequirement = 3;

		private const int ProvidencePageRequirement = 6;

		private const float EverywhereRadius = 10000f;

		private static readonly List<SceneDef> rerollCandidates = new List<SceneDef>();

		private static SceneDef rerollCandidatesScene;

		private static Run rerollCandidatesRun;

		private static readonly List<SceneDef> sceneBuffer = new List<SceneDef>();

		public static PageState GetPageState(CharacterBody body)
		{
			ItemDef pageDie = Items.PageDie;
			if (!Object.op_Implicit((Object)(object)body) || !Object.op_Implicit((Object)(object)Run.instance) || !Object.op_Implicit((Object)(object)pageDie))
			{
				return PageState.None;
			}
			if (!Object.op_Implicit((Object)(object)body.healthComponent) || !body.healthComponent.alive)
			{
				return PageState.None;
			}
			Inventory inventory = body.inventory;
			if (!Object.op_Implicit((Object)(object)inventory) || inventory.GetItemCountTotal(pageDie) <= 0)
			{
				return PageState.None;
			}
			if (inventory.GetItemCountEffective(pageDie) <= 0)
			{
				return PageState.Disabled;
			}
			return PageState.Usable;
		}

		public static string DescribeDisabledCause(CharacterBody body)
		{
			ItemDef roamingItemDisable = Items.RoamingItemDisable;
			Inventory val = (Object.op_Implicit((Object)(object)body) ? body.inventory : null);
			if (Object.op_Implicit((Object)(object)roamingItemDisable) && Object.op_Implicit((Object)(object)val) && val.GetItemCountTotal(roamingItemDisable) > 0)
			{
				return "Disabled by " + Language.GetString(roamingItemDisable.nameToken);
			}
			return "Page is disabled";
		}

		public static bool HasReadyBuff(CharacterBody body)
		{
			BuffDef cursedBookReadyForSacrifice = Buffs.CursedBookReadyForSacrifice;
			if (Object.op_Implicit((Object)(object)cursedBookReadyForSacrifice) && Object.op_Implicit((Object)(object)body))
			{
				return body.HasBuff(cursedBookReadyForSacrifice);
			}
			return false;
		}

		public static int Scan(CharacterBody body, List<ZoneInfo> results)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			int totalPageCountFromTeam = Util.GetTotalPageCountFromTeam((TeamIndex)1, true, true);
			Vector3 corePosition = body.corePosition;
			int num = -1;
			foreach (CursedBookSacrificeZone instance in CursedBookSacrificeZone.instanceList)
			{
				if (!IsValid(instance, totalPageCountFromTeam))
				{
					continue;
				}
				ZoneInfo item = Describe(instance);
				if (!item.IsStageStart || !(item.WindowRemaining <= 0f) || !ReincarnationDisplayPlugin.Settings.HideStageStartZoneAfterWindow.Value)
				{
					item.PlayerInside = instance.zone.IsInBounds(corePosition);
					if (item.PlayerInside && num < 0)
					{
						num = results.Count;
					}
					results.Add(item);
				}
			}
			return num;
		}

		private static bool IsValid(CursedBookSacrificeZone zone, int teamPageCount)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)zone) || !((Component)zone).gameObject.activeInHierarchy)
			{
				return false;
			}
			if (zone.isDisabled || !zone.runFlagConditionResult)
			{
				return false;
			}
			IZone zone2 = zone.zone;
			Object val = (Object)(object)((zone2 is Object) ? zone2 : null);
			if (val == null || !Object.op_Implicit(val))
			{
				return false;
			}
			if ((int)zone.behaviour == 0 && !HasPossibleDestination(zone))
			{
				return false;
			}
			return teamPageCount >= RequiredPageCount(zone.pageRequirement);
		}

		private static int RequiredPageCount(PageRequirements requirement)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Invalid comparison between Unknown and I4
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Invalid comparison between Unknown and I4
			if ((int)requirement != 1)
			{
				if ((int)requirement == 2)
				{
					return Util.ScalePageRequirement(6);
				}
				return 0;
			}
			return Util.ScalePageRequirement(3);
		}

		private static bool HasPossibleDestination(CursedBookSacrificeZone zone)
		{
			if (zone.useRerollSceneInstead)
			{
				return GetRerollCandidates().Count > 0;
			}
			if (zone.useNextSceneInstead)
			{
				if (NetworkServer.active)
				{
					return Object.op_Implicit((Object)(object)Run.instance.nextStageScene);
				}
				return true;
			}
			if (!zone.useExplicitSceneInstead)
			{
				GetCollectionCandidates(zone, sceneBuffer);
				return sceneBuffer.Count > 0;
			}
			if (Object.op_Implicit((Object)(object)zone.explicitScene))
			{
				return CanPickStage(zone.explicitScene);
			}
			return false;
		}

		private static ZoneInfo Describe(CursedBookSacrificeZone zone)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			ZoneInfo result = new ZoneInfo
			{
				Zone = zone,
				Shape = ZoneShape.Unknown,
				Center = ((Component)zone).transform.position
			};
			IZone zone2 = zone.zone;
			VerticalTubeZone val = (VerticalTubeZone)(object)((zone2 is VerticalTubeZone) ? zone2 : null);
			if (val == null)
			{
				SphereZone val2 = (SphereZone)(object)((zone2 is SphereZone) ? zone2 : null);
				if (val2 == null)
				{
					BoxZone val3 = (BoxZone)(object)((zone2 is BoxZone) ? zone2 : null);
					if (val3 != null)
					{
						result.Shape = (val3.isInverted ? ZoneShape.Everywhere : ZoneShape.Box);
						result.Center = ((Component)val3).transform.position;
						result.HalfExtents = ((Component)val3).transform.lossyScale * 0.5f;
					}
				}
				else
				{
					result.Shape = ((!val2.isInverted && !(val2.radius >= 10000f)) ? ZoneShape.Sphere : ZoneShape.Everywhere);
					result.Center = ((Component)val2).transform.position;
					result.Radius = val2.radius;
				}
			}
			else
			{
				result.Shape = ((val.radius >= 10000f) ? ZoneShape.Everywhere : ZoneShape.Tube);
				result.Center = ((Component)val).transform.position;
				result.Radius = val.radius;
			}
			result.IsStageStart = IsStageStartZone(zone);
			if (result.IsStageStart)
			{
				result.WindowRemaining = GetWindowRemaining(zone);
			}
			return result;
		}

		private static float GetWindowRemaining(CursedBookSacrificeZone zone)
		{
			//IL_0018: 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)
			float num;
			if (!Object.op_Implicit((Object)(object)Stage.instance))
			{
				num = 0f;
			}
			else
			{
				FixedTimeStamp entryTime = Stage.instance.entryTime;
				num = ((FixedTimeStamp)(ref entryTime)).timeSince;
			}
			float num2 = num;
			Timer component = ((Component)zone).GetComponent<Timer>();
			if (!Object.op_Implicit((Object)(object)component))
			{
				return ReincarnationDisplayPlugin.Settings.StageStartWindowSeconds.Value - num2;
			}
			float num3 = (component.timerRunning ? (component.duration - component.stopwatch) : 0f);
			if (!NetworkServer.active && Object.op_Implicit((Object)(object)Stage.instance))
			{
				num3 = Mathf.Min(num3, component.duration - num2);
			}
			return num3;
		}

		private static bool IsStageStartZone(CursedBookSacrificeZone zone)
		{
			if (zone.useRerollSceneInstead)
			{
				return true;
			}
			DLC4SacrificeZoneSpawner instance = DLC4SacrificeZoneSpawner.instance;
			GameObject val = ((Object.op_Implicit((Object)(object)instance) && Object.op_Implicit((Object)(object)instance.reincarnateCard)) ? instance.reincarnateCard.prefab : null);
			if (Object.op_Implicit((Object)(object)val))
			{
				return ((Object)((Component)zone).gameObject).name.StartsWith(((Object)val).name);
			}
			return false;
		}

		public static string DescribeOutcome(CursedBookSacrificeZone zone, out bool keepsStageCount)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Invalid comparison between Unknown and I4
			keepsStageCount = zone.ShouldPreventStageCounterIncrement;
			if ((int)zone.behaviour == 1)
			{
				keepsStageCount = false;
				return "Opens the Veil of Memory";
			}
			if (zone.useRerollSceneInstead)
			{
				keepsStageCount = false;
				return "Reroll stage " + (Run.instance.stageClearCount + 1);
			}
			if (zone.useNextSceneInstead)
			{
				return "Continues to the next stage";
			}
			if (!zone.useExplicitSceneInstead)
			{
				GetCollectionCandidates(zone, sceneBuffer);
				if (sceneBuffer.Count == 1)
				{
					return "Destination: " + SceneName(sceneBuffer[0]);
				}
				if (Object.op_Implicit((Object)(object)zone.sceneTierCollection))
				{
					return "Continues to the next stage";
				}
				if (!Object.op_Implicit((Object)(object)zone.sceneCollection) || !((Object)zone.sceneCollection).name.Contains("Trial"))
				{
					return "Continues to a random stage";
				}
				return "Enters a random Winnowing trial";
			}
			if (!Object.op_Implicit((Object)(object)zone.explicitScene))
			{
				return "Unknown destination";
			}
			return "Destination: " + SceneName(zone.explicitScene);
		}

		private static List<SceneDef> GetRerollCandidates()
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			SceneDef mostRecentSceneDef = SceneCatalog.mostRecentSceneDef;
			if ((Object)(object)mostRecentSceneDef == (Object)(object)rerollCandidatesScene && (Object)(object)Run.instance == (Object)(object)rerollCandidatesRun)
			{
				return rerollCandidates;
			}
			rerollCandidates.Clear();
			rerollCandidatesScene = mostRecentSceneDef;
			rerollCandidatesRun = Run.instance;
			if (!Object.op_Implicit((Object)(object)mostRecentSceneDef))
			{
				return rerollCandidates;
			}
			Enumerator<SceneDef> enumerator = SceneCatalog.allSceneDefs.GetEnumerator();
			try
			{
				while (enumerator.MoveNext())
				{
					SceneDef current = enumerator.Current;
					if (Object.op_Implicit((Object)(object)current) && (Object)(object)current != (Object)(object)mostRecentSceneDef && current.stageOrder == mostRecentSceneDef.stageOrder && CanPickStage(current))
					{
						rerollCandidates.Add(current);
					}
				}
			}
			finally
			{
				((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
			}
			return rerollCandidates;
		}

		internal static void GetCollectionCandidates(CursedBookSacrificeZone zone, List<SceneDef> results)
		{
			//IL_003f: 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_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			results.Clear();
			Run instance = Run.instance;
			SceneCollection val = (Object.op_Implicit((Object)(object)zone.sceneTierCollection) ? zone.sceneTierCollection.GetSceneCollection(instance.stageClearCountInCurrentLoop + 1) : zone.sceneCollection);
			if (!Object.op_Implicit((Object)(object)val))
			{
				return;
			}
			Enumerator<SceneEntry> enumerator = val.sceneEntries.GetEnumerator();
			try
			{
				while (enumerator.MoveNext())
				{
					SceneEntry current = enumerator.Current;
					SceneDef val2 = current.sceneDef;
					if (!Object.op_Implicit((Object)(object)val2))
					{
						continue;
					}
					if (!CanPickStage(val2))
					{
						val2 = current.fallbackSceneDef;
						if (!Object.op_Implicit((Object)(object)val2))
						{
							continue;
						}
					}
					if (Object.op_Implicit((Object)(object)val2.loopedSceneDef) && instance.loopClearCount > 0)
					{
						val2 = val2.loopedSceneDef;
					}
					if (!results.Contains(val2))
					{
						results.Add(val2);
					}
				}
			}
			finally
			{
				((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
			}
		}

		private static bool CanPickStage(SceneDef def)
		{
			if (Object.op_Implicit((Object)(object)def.requiredExpansion))
			{
				return Run.instance.IsExpansionEnabled(def.requiredExpansion);
			}
			return true;
		}

		internal static string SceneName(SceneDef def)
		{
			string text = Language.GetString(def.nameToken);
			if (!string.IsNullOrEmpty(text) && !(text == def.nameToken))
			{
				return text;
			}
			return def.cachedName;
		}
	}
	internal sealed class ZoneWorldRings : MonoBehaviour
	{
		private sealed class Ring
		{
			public GameObject Root;

			public readonly List<LineRenderer> Lines = new List<LineRenderer>();

			public int ActiveLines;

			public ZoneShape Shape;

			public Vector3 Center;

			public float Radius;

			public Vector3 HalfExtents;

			public bool Built;

			public bool Seen;
		}

		private const float LineWidth = 0.25f;

		private const float InsideLineWidth = 0.4f;

		private const float GroundOffset = 0.2f;

		private const float RebuildTolerance = 0.05f;

		private const float SampleSpacing = 1f;

		private const int MinSamples = 32;

		private const int MaxSamples = 512;

		private const float RayAbove = 15f;

		private const float RayBelow = 30f;

		private const float MaxStepHeight = 0.75f;

		private const float MaxSlope = 1.2f;

		private const int MinPieceSamples = 3;

		private const float FloorSearchReach = 20f;

		private const float FloorSearchLift = 1f;

		private const float MinCrossSectionRadius = 0.5f;

		private static readonly Color RingColor = new Color(0.76f, 0.55f, 1f, 0.45f);

		private static readonly Color InsideRingColor = new Color(0.86f, 0.66f, 1f, 0.95f);

		private readonly Dictionary<CursedBookSacrificeZone, Ring> rings = new Dictionary<CursedBookSacrificeZone, Ring>();

		private readonly Stack<Ring> pool = new Stack<Ring>();

		private readonly List<CursedBookSacrificeZone> staleZones = new List<CursedBookSacrificeZone>();

		private readonly Vector3[] samples = (Vector3[])(object)new Vector3[512];

		private readonly bool[] sampleOnFloor = new bool[512];

		private readonly List<Vector3> piece = new List<Vector3>();

		private Material material;

		public static ZoneWorldRings Create()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			return new GameObject("ReincarnationZoneRings").AddComponent<ZoneWorldRings>();
		}

		private void Awake()
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			Material defaultSpriteMaterial = GetDefaultSpriteMaterial();
			if (!Object.op_Implicit((Object)(object)defaultSpriteMaterial))
			{
				ReincarnationDisplayPlugin.Log.LogError((object)"No usable line material found; world rings are disabled.");
			}
			else
			{
				material = new Material(defaultSpriteMaterial);
			}
		}

		private void OnDestroy()
		{
			if (Object.op_Implicit((Object)(object)material))
			{
				Object.Destroy((Object)(object)material);
			}
		}

		private static Material GetDefaultSpriteMaterial()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			GameObject val = new GameObject("ReincarnationMaterialProbe");
			try
			{
				return ((Renderer)val.AddComponent<SpriteRenderer>()).sharedMaterial;
			}
			finally
			{
				Object.DestroyImmediate((Object)(object)val);
			}
		}

		public void Clear()
		{
			if (rings.Count == 0)
			{
				return;
			}
			foreach (Ring value in rings.Values)
			{
				Release(value);
			}
			rings.Clear();
		}

		public void UpdateRings(List<ZoneInfo> zones, Vector3 viewer, float maxDistance)
		{
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)material))
			{
				return;
			}
			foreach (Ring value2 in rings.Values)
			{
				value2.Seen = false;
			}
			foreach (ZoneInfo zone in zones)
			{
				if ((zone.Shape == ZoneShape.Tube || zone.Shape == ZoneShape.Sphere || zone.Shape == ZoneShape.Box) && !(DistanceToEdge(zone, viewer) > maxDistance))
				{
					if (!rings.TryGetValue(zone.Zone, out var value))
					{
						value = Rent();
						rings.Add(zone.Zone, value);
					}
					value.Seen = true;
					if (NeedsRebuild(value, zone))
					{
						Rebuild(value, zone, viewer);
					}
					Color val = (zone.PlayerInside ? InsideRingColor : RingColor);
					float widthMultiplier = (zone.PlayerInside ? 0.4f : 0.25f);
					for (int i = 0; i < value.ActiveLines; i++)
					{
						LineRenderer obj = value.Lines[i];
						obj.startColor = val;
						obj.endColor = val;
						obj.widthMultiplier = widthMultiplier;
					}
				}
			}
			foreach (KeyValuePair<CursedBookSacrificeZone, Ring> ring in rings)
			{
				if (!ring.Value.Seen)
				{
					staleZones.Add(ring.Key);
				}
			}
			foreach (CursedBookSacrificeZone staleZone in staleZones)
			{
				Release(rings[staleZone]);
				rings.Remove(staleZone);
			}
			staleZones.Clear();
		}

		private static float DistanceToEdge(ZoneInfo zone, Vector3 viewer)
		{
			//IL_0002: 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_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(viewer.x - zone.Center.x, viewer.z - zone.Center.z);
			if (zone.Shape == ZoneShape.Box)
			{
				Vector2 val2 = default(Vector2);
				((Vector2)(ref val2))..ctor(Mathf.Max(0f, Mathf.Abs(val.x) - zone.HalfExtents.x), Mathf.Max(0f, Mathf.Abs(val.y) - zone.HalfExtents.z));
				return ((Vector2)(ref val2)).magnitude;
			}
			return Mathf.Max(0f, ((Vector2)(ref val)).magnitude - zone.Radius);
		}

		private static bool NeedsRebuild(Ring ring, ZoneInfo zone)
		{
			//IL_0017: 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_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			if (ring.Built && ring.Shape == zone.Shape)
			{
				Vector3 val = ring.Center - zone.Center;
				if (!(((Vector3)(ref val)).sqrMagnitude > 0.0025000002f) && !(Mathf.Abs(ring.Radius - zone.Radius) > 0.05f))
				{
					val = ring.HalfExtents - zone.HalfExtents;
					return ((Vector3)(ref val)).sqrMagnitude > 0.0025000002f;
				}
			}
			return true;
		}

		private void Rebuild(Ring ring, ZoneInfo zone, Vector3 viewer)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			ring.Built = true;
			ring.Shape = zone.Shape;
			ring.Center = zone.Center;
			ring.Radius = zone.Radius;
			ring.HalfExtents = zone.HalfExtents;
			int num = ((zone.Shape == ZoneShape.Box) ? SampleBox(zone) : SampleCircle(zone, viewer));
			ring.ActiveLines = 0;
			if (num > 0)
			{
				EmitPieces(ring, num);
			}
			for (int i = ring.ActiveLines; i < ring.Lines.Count; i++)
			{
				((Component)ring.Lines[i]).gameObject.SetActive(false);
			}
		}

		private int SampleCircle(ZoneInfo zone, Vector3 viewer)
		{
			//IL_006c: 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_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			float num = zone.Radius;
			float num2;
			if (zone.Shape == ZoneShape.Sphere)
			{
				num2 = (TryGetGroundY(zone.Center, Mathf.Max(num, 20f), out var groundY) ? groundY : zone.Center.y);
				float num3 = zone.Center.y - num2;
				num = Mathf.Sqrt(Mathf.Max(0f, num * num - num3 * num3));
				if (num < 0.5f)
				{
					return 0;
				}
			}
			else
			{
				num2 = (TryGetGroundY(zone.Center, 20f, out var groundY2) ? groundY2 : viewer.y);
			}
			int num4 = Mathf.Clamp(Mathf.CeilToInt(MathF.PI * 2f * num / 1f), 32, 512);
			for (int i = 0; i < num4; i++)
			{
				float num5 = (float)i * (MathF.PI * 2f / (float)num4);
				SampleAt(i, zone.Center.x + Mathf.Cos(num5) * num, zone.Center.z + Mathf.Sin(num5) * num, num2);
			}
			return num4;
		}

		private int SampleBox(ZoneInfo zone)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: 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_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: 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_0162: Unknown result type (might be due to invalid IL or missing references)
			Vector3 halfExtents = zone.HalfExtents;
			float groundY;
			float floorY = (TryGetGroundY(zone.Center, Mathf.Max(halfExtents.y, 20f), out groundY) ? groundY : zone.Center.y);
			Vector2[] array = (Vector2[])(object)new Vector2[4]
			{
				new Vector2(0f - halfExtents.x, 0f - halfExtents.z),
				new Vector2(halfExtents.x, 0f - halfExtents.z),
				new Vector2(halfExtents.x, halfExtents.z),
				new Vector2(0f - halfExtents.x, halfExtents.z)
			};
			float num = 4f * (halfExtents.x + halfExtents.z);
			int num2 = Mathf.Clamp(Mathf.CeilToInt(num / 1f), 32, 512);
			int num3 = 0;
			for (int i = 0; i < 4; i++)
			{
				Vector2 val = array[i];
				Vector2 val2 = array[(i + 1) % 4];
				int num4;
				if (i >= 3)
				{
					num4 = num2 - num3;
				}
				else
				{
					float num5 = num2;
					Vector2 val3 = val2 - val;
					num4 = Mathf.Max(1, Mathf.RoundToInt(num5 * ((Vector2)(ref val3)).magnitude / num));
				}
				int num6 = num4;
				for (int j = 0; j < num6; j++)
				{
					if (num3 >= num2)
					{
						break;
					}
					Vector2 val4 = Vector2.Lerp(val, val2, (float)j / (float)num6);
					SampleAt(num3++, zone.Center.x + val4.x, zone.Center.z + val4.y, floorY);
				}
			}
			return num3;
		}

		private void SampleAt(int index, float x, float z, float floorY)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = new Vector3(x, floorY + 15f, z);
			Vector3 down = Vector3.down;
			LayerIndex world = LayerIndex.world;
			RaycastHit val2 = default(RaycastHit);
			bool flag = Physics.Raycast(val, down, ref val2, 45f, LayerMask.op_Implicit(((LayerIndex)(ref world)).mask), (QueryTriggerInteraction)1);
			samples[index] = new Vector3(x, (flag ? ((RaycastHit)(ref val2)).point.y : floorY) + 0.2f, z);
			sampleOnFloor[index] = flag;
		}

		private void EmitPieces(Ring ring, int count)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			int num = -1;
			for (int i = 0; i < count; i++)
			{
				if (!Joined(i, (i + 1) % count))
				{
					num = i;
					break;
				}
			}
			if (num < 0)
			{
				piece.Clear();
				for (int j = 0; j < count; j++)
				{
					piece.Add(samples[j]);
				}
				AddLine(ring, closed: true);
				return;
			}
			piece.Clear();
			for (int k = 1; k <= count; k++)
			{
				int num2 = (num + k) % count;
				if (sampleOnFloor[num2])
				{
					piece.Add(samples[num2]);
				}
				if (!Joined(num2, (num2 + 1) % count))
				{
					if (piece.Count >= 3)
					{
						AddLine(ring, closed: false);
					}
					piece.Clear();
				}
			}
		}

		private bool Joined(int a, int b)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: 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_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: 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_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: 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)
			if (!sampleOnFloor[a] || !sampleOnFloor[b])
			{
				return false;
			}
			Vector3 val = samples[a];
			Vector3 val2 = samples[b];
			Vector2 val3 = new Vector2(val2.x - val.x, val2.z - val.z);
			float magnitude = ((Vector2)(ref val3)).magnitude;
			return Mathf.Abs(val2.y - val.y) <= 0.75f + magnitude * 1.2f;
		}

		private void AddLine(Ring ring, bool closed)
		{
			LineRenderer val;
			if (ring.ActiveLines < ring.Lines.Count)
			{
				val = ring.Lines[ring.ActiveLines];
			}
			else
			{
				val = CreateLine(ring.Root.transform);
				ring.Lines.Add(val);
			}
			ring.ActiveLines++;
			((Component)val).gameObject.SetActive(true);
			val.loop = closed;
			val.positionCount = piece.Count;
			val.SetPositions(piece.ToArray());
		}

		private static bool TryGetGroundY(Vector3 center, float reach, out float groundY)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: 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_003e: 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_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = center + Vector3.up * 1f;
			Vector3 down = Vector3.down;
			float num = reach + 1f;
			LayerIndex world = LayerIndex.world;
			RaycastHit val2 = default(RaycastHit);
			if (!Physics.Raycast(val, down, ref val2, num, LayerMask.op_Implicit(((LayerIndex)(ref world)).mask), (QueryTriggerInteraction)1))
			{
				Vector3 val3 = center + Vector3.up * reach;
				Vector3 down2 = Vector3.down;
				float num2 = reach - 1f;
				world = LayerIndex.world;
				if (!Physics.Raycast(val3, down2, ref val2, num2, LayerMask.op_Implicit(((LayerIndex)(ref world)).mask), (QueryTriggerInteraction)1))
				{
					groundY = center.y;
					return false;
				}
			}
			groundY = ((RaycastHit)(ref val2)).point.y;
			return true;
		}

		private Ring Rent()
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			if (pool.Count > 0)
			{
				Ring ring = pool.Pop();
				ring.Built = false;
				ring.Root.SetActive(true);
				return ring;
			}
			GameObject val = new GameObject("Ring");
			val.transform.SetParent(((Component)this).transform, false);
			return new Ring
			{
				Root = val
			};
		}

		private LineRenderer CreateLine(Transform parent)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("Piece");
			val.transform.SetParent(parent, false);
			LineRenderer obj = val.AddComponent<LineRenderer>();
			((Renderer)obj).sharedMaterial = material;
			obj.useWorldSpace = true;
			obj.numCornerVertices = 2;
			obj.numCapVertices = 2;
			obj.alignment = (LineAlignment)0;
			obj.textureMode = (LineTextureMode)0;
			((Renderer)obj).shadowCastingMode = (ShadowCastingMode)0;
			((Renderer)obj).receiveShadows = false;
			return obj;
		}

		private void Release(Ring ring)
		{
			ring.Root.SetActive(false);
			pool.Push(ring);
		}
	}
	internal static class PluginVersionInfo
	{
		public const string Version = "1.0.1";
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}