Decompiled source of OnTheLookout v1.8.5

plugins/codesycamore.OnTheLookout.dll

Decompiled 7 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using DG.Tweening;
using DG.Tweening.Core;
using DG.Tweening.Plugins.Options;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using OnTheLookout.Core;
using OnTheLookout.Freeze;
using OnTheLookout.Modules;
using OnTheLookout.UI;
using Peak;
using Peak.Afflictions;
using Photon.Pun;
using Photon.Realtime;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using Zorro.Core;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("codesycamore.OnTheLookout")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.8.5.0")]
[assembly: AssemblyInformationalVersion("1.8.5+5a94114d4b8e0253832f03d4ee64a8e955cef1e0")]
[assembly: AssemblyProduct("codesycamore.OnTheLookout")]
[assembly: AssemblyTitle("OnTheLookout")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/codesycamore/OnTheLookout")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.8.5.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 BepInEx
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	[Embedded]
	internal sealed class BepInAutoPluginAttribute : Attribute
	{
		public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace BepInEx.Preloader.Core.Patching
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	[Embedded]
	internal sealed class PatcherAutoPluginAttribute : Attribute
	{
		public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace Microsoft.CodeAnalysis
{
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace OnTheLookout
{
	[BepInPlugin("codesycamore.OnTheLookout", "OnTheLookout", "1.8.5")]
	public class Plugin : BaseUnityPlugin
	{
		private Harmony _harmony;

		public const string Id = "codesycamore.OnTheLookout";

		internal static ManualLogSource Log { get; private set; }

		internal static ModConfig ModConfig { get; private set; }

		public static string Name => "OnTheLookout";

		public static string Version => "1.8.5";

		private void Awake()
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Expected O, but got Unknown
			//IL_026d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0274: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			ModConfig = new ModConfig(((BaseUnityPlugin)this).Config);
			_harmony = new Harmony("codesycamore.OnTheLookout");
			ModConfig modConfig = ModConfig;
			GameObject val = new GameObject("OnTheLookout");
			Object.DontDestroyOnLoad((Object)(object)val);
			((Object)val).hideFlags = (HideFlags)61;
			val.AddComponent<ModNetwork>();
			bool flag = SafePatch.Postfix(_harmony, typeof(RunManager), "StartRun", typeof(Plugin), "StartRunPostfix", "Round");
			bool flag2 = SafePatch.Postfix(_harmony, typeof(CharacterInput), "Sample", typeof(FreezeInputPatch), "SamplePostfix", "Freeze");
			if (flag2)
			{
				val.AddComponent<FreezeSystem>();
				FreezeSystem.LookChecksEnabled = modConfig.EnableFreeze.Value;
				FreezeSuspendPatch.HooksAvailable = SafePatch.Prefix(_harmony, typeof(Bodypart), "Gravity", typeof(FreezeSuspendPatch), "GravityPrefix", "Freeze.Suspend") && SafePatch.Postfix(_harmony, typeof(CharacterMovement), "FixedUpdate", typeof(FreezeSuspendPatch), "FixedUpdatePostfix", "Freeze.Suspend");
				SafePatch.Prefix(_harmony, typeof(Character), "CanRegenStamina", typeof(FreezeSuspendPatch), "RegenPrefix", "Freeze.Suspend");
			}
			bool flag3 = SafeZoneSystem.Install(_harmony, modConfig.EnableSafeZones.Value);
			bool flag4 = modConfig.EnableTag.Value && TagSystem.Install(_harmony);
			bool flag5 = modConfig.EnableFog.Value && FogSystem.Install(_harmony);
			bool flag6 = modConfig.EnableItemRules.Value && ItemRules.Install(_harmony);
			bool flag7 = ChaserSpeed.Install(_harmony);
			bool flag8 = BlowgunSystem.Install(_harmony);
			bool flag9 = Tweaks.Install(_harmony);
			bool flag10 = ChaserResilience.Install(_harmony);
			bool flag11 = ShroomberryRules.Install(_harmony);
			bool flag12 = MilkRules.Install(_harmony);
			bool flag13 = ChaserKit.Install(_harmony);
			bool flag14 = MandrakeDrops.Install(_harmony);
			LegLoadout.Install();
			RoleSwap.Install();
			bool flag15 = RunnerDash.Install(_harmony);
			RewardSystem.Enabled = modConfig.EnableRewards.Value;
			GameObject val2 = new GameObject("OnTheLookout_UI");
			Object.DontDestroyOnLoad((Object)(object)val2);
			val2.AddComponent<Hud>();
			val2.AddComponent<GhostVisibility>();
			val2.AddComponent<ChaseEffects>();
			val2.AddComponent<HostMenu>();
			val2.AddComponent<ChaserOddsMenu>();
			val2.AddComponent<CaptureIndicator>();
			val2.AddComponent<SafeZoneWall>();
			HostMenu.Install(_harmony);
			bool flag16 = NameTags.Install(_harmony);
			val.AddComponent<AdminRestart>();
			val.AddComponent<ChaserClimbBoost>();
			SceneManager.sceneLoaded += delegate
			{
				ItemCatalog.OnSceneLoaded();
			};
			Log.LogInfo((object)($"[OTL] {Name} {Version} loaded. round={flag} freeze={flag2 && modConfig.EnableFreeze.Value} " + $"suspend={FreezeSuspendPatch.HooksAvailable} campfire={flag3} tag={flag4} fog={flag5} items={flag6} " + $"speed={flag7} blowgun={flag8} tweaks={flag9} resilience={flag10} shroomberry={flag11} milk={flag12} kit={flag13} gems={flag15} mandrakes={flag14} nameTags={flag16} rewards={RewardSystem.Enabled}"));
		}

		private static void StartRunPostfix()
		{
			if (Net.InRoom && Net.IsHost && ModConfig.AutoStartRound.Value)
			{
				ModNetwork? instance = ModNetwork.Instance;
				if (instance != null)
				{
					((MonoBehaviour)instance).StartCoroutine(RoundManager.HostStartWhenReady());
				}
			}
		}
	}
}
namespace OnTheLookout.UI
{
	internal sealed class BlowgunCooldownUI
	{
		private const float FontSize = 64f;

		private const float AboveSlot = 45f;

		private readonly RectTransform _overlay;

		private readonly RectTransform _root;

		private readonly TextMeshProUGUI _text;

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

		private int _lastShown = -1;

		private bool _logged;

		private readonly string _label;

		private readonly Func<bool> _onCooldown;

		private readonly Func<float> _secondsLeft;

		private readonly Func<Item, bool> _isItem;

		private readonly Func<Character, bool> _forRole;

		public bool IsValid
		{
			get
			{
				if ((Object)(object)_root != (Object)null)
				{
					return (Object)(object)_overlay != (Object)null;
				}
				return false;
			}
		}

		public BlowgunCooldownUI(Canvas overlay, TextMeshProUGUI fontStyle)
			: this(overlay, fontStyle, "Blowgun", () => BlowgunSystem.OnCooldown, () => BlowgunSystem.CooldownSecondsLeft, ItemCatalog.IsBlowgun, RoleManager.IsChaser)
		{
		}

		public BlowgunCooldownUI(Canvas overlay, TextMeshProUGUI fontStyle, string label, Func<bool> onCooldown, Func<float> secondsLeft, Func<Item, bool> isItem, Func<Character, bool> forRole)
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Expected O, but got Unknown
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Expected O, but got Unknown
			//IL_00c0: 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_00c7: 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_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			_label = label;
			_onCooldown = onCooldown;
			_secondsLeft = secondsLeft;
			_isItem = isItem;
			_forRole = forRole;
			_overlay = (RectTransform)((Component)overlay).transform;
			GameObject val = new GameObject("OTL_" + label + "Cooldown", new Type[1] { typeof(RectTransform) });
			_root = (RectTransform)val.transform;
			((Transform)_root).SetParent((Transform)(object)_overlay, false);
			RectTransform root = _root;
			RectTransform root2 = _root;
			RectTransform root3 = _root;
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(0.5f, 0.5f);
			root3.pivot = val2;
			root.anchorMin = (root2.anchorMax = val2);
			_root.sizeDelta = new Vector2(200f, 90f);
			_text = val.AddComponent<TextMeshProUGUI>();
			((TMP_Text)_text).font = ((TMP_Text)fontStyle).font;
			((TMP_Text)_text).fontSharedMaterial = ((TMP_Text)fontStyle).fontSharedMaterial;
			((TMP_Text)_text).fontSize = 64f;
			((TMP_Text)_text).alignment = (TextAlignmentOptions)514;
			((TMP_Text)_text).textWrappingMode = (TextWrappingModes)0;
			((Graphic)_text).raycastTarget = false;
			((Graphic)_text).color = Color.white;
			((TMP_Text)_text).outlineWidth = 0.2f;
			((TMP_Text)_text).outlineColor = new Color32((byte)20, (byte)30, (byte)45, byte.MaxValue);
			val.SetActive(false);
		}

		public void Update(GUIManager gui)
		{
			//IL_00a6: 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_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: 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_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: 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_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: 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)
			//IL_0130: 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_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_0236: Unknown result type (might be due to invalid IL or missing references)
			Character localCharacter = Character.localCharacter;
			bool flag = _onCooldown() && (Object)(object)localCharacter != (Object)null && _forRole(localCharacter) && !localCharacter.data.dead;
			if (((Component)_root).gameObject.activeSelf != flag)
			{
				((Component)_root).gameObject.SetActive(flag);
			}
			if (!flag)
			{
				_lastShown = -1;
				return;
			}
			int num = ItemSlotIndex();
			RectTransform val = SlotRect(gui, num) ?? SlotRect(gui, (gui.items != null) ? (gui.items.Length / 2) : (-1));
			Rect rect = _overlay.rect;
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(0f, (0f - ((Rect)(ref rect)).height) * 0.5f + 220f);
			if ((Object)(object)val != (Object)null)
			{
				val.GetWorldCorners(_corners);
				Vector3 val3 = (_corners[1] + _corners[2]) * 0.5f;
				Canvas componentInParent = ((Component)val).GetComponentInParent<Canvas>();
				Camera val4 = (((Object)(object)componentInParent != (Object)null && (int)componentInParent.renderMode != 0) ? componentInParent.worldCamera : null);
				Vector2 val5 = RectTransformUtility.WorldToScreenPoint(val4, val3);
				Vector2 val6 = default(Vector2);
				if (RectTransformUtility.ScreenPointToLocalPointInRectangle(_overlay, val5, (Camera)null, ref val6))
				{
					val2 = val6 + new Vector2(0f, 45f);
				}
			}
			_root.anchoredPosition = val2;
			int num2 = Mathf.CeilToInt(_secondsLeft());
			if (num2 != _lastShown)
			{
				_lastShown = num2;
				((TMP_Text)_text).text = num2.ToString();
				ShortcutExtensions.DOKill((Component)(object)_root, false);
				((Transform)_root).localScale = Vector3.one * 1.2f;
				TweenSettingsExtensions.SetEase<TweenerCore<Vector3, Vector3, VectorOptions>>(ShortcutExtensions.DOScale((Transform)(object)_root, 1f, 0.2f), (Ease)27);
			}
			if (!_logged)
			{
				_logged = true;
				Plugin.Log.LogInfo((object)string.Format("[OTL][UI] {0} cooldown shown (slot {1}, above {2}, at {3}).", _label, num, ((Object)(object)val != (Object)null) ? ((Object)val).name : "screen bottom", val2));
			}
		}

		private static RectTransform? SlotRect(GUIManager gui, int slot)
		{
			if (gui.items == null || slot < 0 || slot >= gui.items.Length || !((Object)(object)gui.items[slot] != (Object)null))
			{
				return null;
			}
			Transform transform = ((Component)gui.items[slot]).transform;
			return (RectTransform?)(object)((transform is RectTransform) ? transform : null);
		}

		private int ItemSlotIndex()
		{
			Player localPlayer = Player.localPlayer;
			if ((Object)(object)localPlayer == (Object)null || localPlayer.itemSlots == null)
			{
				return -1;
			}
			for (int i = 0; i < localPlayer.itemSlots.Length; i++)
			{
				ItemSlot val = localPlayer.itemSlots[i];
				if (val != null && !val.IsEmpty() && (Object)(object)val.prefab != (Object)null && _isItem(val.prefab))
				{
					return i;
				}
			}
			return -1;
		}

		public void Destroy()
		{
			if ((Object)(object)_root != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)_root).gameObject);
			}
		}
	}
	internal sealed class CaptureIndicator : MonoBehaviour
	{
		private const float BarWidth = 420f;

		private const float BarHeight = 18f;

		private static readonly Color FillColor;

		private static float s_StartedAt;

		private static float s_Duration;

		private static int s_Chaser;

		private Canvas? _canvas;

		private RectTransform? _fill;

		private TextMeshProUGUI? _label;

		static CaptureIndicator()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			FillColor = new Color(0.95f, 0.15f, 0.12f, 0.95f);
			s_StartedAt = -1f;
			RoundManager.FreshStart += delegate
			{
				s_StartedAt = -1f;
			};
		}

		public static void OnProgress(int chaserActor, int startServerTime, int durationMs)
		{
			if (durationMs <= 0)
			{
				if (chaserActor == s_Chaser)
				{
					s_StartedAt = -1f;
				}
			}
			else
			{
				s_Chaser = chaserActor;
				s_Duration = (float)durationMs / 1000f;
				s_StartedAt = Time.time - Mathf.Max(0f, (float)(Net.Now - startServerTime) / 1000f);
			}
		}

		private void Update()
		{
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			Character localCharacter = Character.localCharacter;
			float num = ((s_StartedAt < 0f) ? (-1f) : ((Time.time - s_StartedAt) / Mathf.Max(0.1f, s_Duration)));
			if (!(num >= 0f) || !(num <= 1.15f) || !((Object)(object)localCharacter != (Object)null) || localCharacter.data.dead || !RoleManager.IsRunner(localCharacter))
			{
				if (num > 1.15f)
				{
					s_StartedAt = -1f;
				}
				if ((Object)(object)_canvas != (Object)null && ((Component)_canvas).gameObject.activeSelf)
				{
					((Component)_canvas).gameObject.SetActive(false);
				}
			}
			else if (!((Object)(object)_canvas == (Object)null) || Build())
			{
				if (!((Component)_canvas).gameObject.activeSelf)
				{
					((Component)_canvas).gameObject.SetActive(true);
				}
				_fill.sizeDelta = new Vector2(420f * Mathf.Clamp01(num), 18f);
				((TMP_Text)_label).text = Net.NameOf(s_Chaser).ToUpperInvariant() + " IS CAPTURING YOU!";
			}
		}

		private bool Build()
		{
			//IL_0059: 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)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Expected O, but got Unknown
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: 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_00f3: 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_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			GUIManager instance = GUIManager.instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)instance.interactNameText == (Object)null)
			{
				return false;
			}
			_canvas = PeakMenuKit.CreateCanvas("OTL_CaptureIndicator", ((Component)this).transform, instance, 30);
			((Behaviour)((Component)_canvas).GetComponent<GraphicRaycaster>()).enabled = false;
			RectTransform val = NewImage("Back", (RectTransform)((Component)_canvas).transform, new Color(0.05f, 0.05f, 0.08f, 0.7f), new Vector2(428f, 26f));
			val.anchoredPosition = new Vector2(0f, -120f);
			_fill = NewImage("Fill", val, FillColor, new Vector2(0f, 18f));
			RectTransform? fill = _fill;
			RectTransform? fill2 = _fill;
			RectTransform? fill3 = _fill;
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(0f, 0.5f);
			fill3.pivot = val2;
			Vector2 anchorMin = (fill2.anchorMax = val2);
			fill.anchorMin = anchorMin;
			_fill.anchoredPosition = new Vector2(4f, 0f);
			_label = PeakMenuKit.AddText((Transform)(object)val, "", instance.interactNameText, 28f, new Color(1f, 0.35f, 0.3f, 1f), 40f);
			RectTransform rectTransform = ((TMP_Text)_label).rectTransform;
			((Vector2)(ref val2))..ctor(0.5f, 0f);
			rectTransform.pivot = val2;
			anchorMin = (rectTransform.anchorMax = val2);
			rectTransform.anchorMin = anchorMin;
			rectTransform.sizeDelta = new Vector2(900f, 40f);
			rectTransform.anchoredPosition = new Vector2(0f, 28f);
			((TMP_Text)_label).outlineWidth = 0.15f;
			((TMP_Text)_label).outlineColor = new Color32((byte)10, (byte)12, (byte)20, byte.MaxValue);
			return true;
		}

		private static RectTransform NewImage(string name, RectTransform parent, Color color, Vector2 size)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			//IL_0042: 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_004b: 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_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) });
			RectTransform val2 = (RectTransform)val.transform;
			((Transform)val2).SetParent((Transform)(object)parent, false);
			Vector2 val3 = default(Vector2);
			((Vector2)(ref val3))..ctor(0.5f, 0.5f);
			val2.pivot = val3;
			Vector2 anchorMin = (val2.anchorMax = val3);
			val2.anchorMin = anchorMin;
			val2.sizeDelta = size;
			Image val5 = val.AddComponent<Image>();
			((Graphic)val5).color = color;
			((Graphic)val5).raycastTarget = false;
			return val2;
		}
	}
	internal static class CaptureSfx
	{
		private static List<SFX_Instance>? s_Sfx;

		private static List<AudioClip>? s_Clips;

		public static void Play(Vector3 position)
		{
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			if (s_Sfx == null)
			{
				Load();
			}
			List<SFX_Instance> list = s_Sfx;
			if (list != null && list.Count > 0 && (Object)(object)SFX_Player.instance != (Object)null)
			{
				foreach (SFX_Instance item in s_Sfx)
				{
					item.Play(position);
				}
				return;
			}
			List<AudioClip> list2 = s_Clips;
			if (list2 == null || list2.Count <= 0)
			{
				return;
			}
			foreach (AudioClip s_Clip in s_Clips)
			{
				AudioSource.PlayClipAtPoint(s_Clip, position, 1f);
			}
		}

		private static void Load()
		{
			s_Sfx = new List<SFX_Instance>();
			s_Clips = new List<AudioClip>();
			try
			{
				Dynamite val = SingletonAsset<ItemDatabase>.Instance?.itemLookup.Values.Select((Item i) => (!((Object)(object)i != (Object)null)) ? null : ((Component)i).GetComponentInChildren<Dynamite>(true)).FirstOrDefault((Func<Dynamite, bool>)((Dynamite d) => (Object)(object)d != (Object)null));
				GameObject val2 = (((Object)(object)val != (Object)null) ? val.explosionPrefab : null);
				if ((Object)(object)val2 == (Object)null)
				{
					Plugin.Log.LogWarning((object)"[OTL][UI] dynamite explosion prefab not found; capture sound disabled.");
					return;
				}
				MonoBehaviour[] componentsInChildren = val2.GetComponentsInChildren<MonoBehaviour>(true);
				foreach (MonoBehaviour val3 in componentsInChildren)
				{
					if ((Object)(object)val3 == (Object)null)
					{
						continue;
					}
					FieldInfo[] fields = ((object)val3).GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					foreach (FieldInfo fieldInfo in fields)
					{
						object value = fieldInfo.GetValue(val3);
						SFX_Instance val4 = (SFX_Instance)((value is SFX_Instance) ? value : null);
						if (val4 != null && (Object)(object)val4 != (Object)null)
						{
							s_Sfx.Add(val4);
						}
						else
						{
							if (!(value is IEnumerable enumerable) || enumerable is string)
							{
								continue;
							}
							foreach (object item in enumerable)
							{
								SFX_Instance val5 = (SFX_Instance)((item is SFX_Instance) ? item : null);
								if (val5 != null && (Object)(object)val5 != (Object)null)
								{
									s_Sfx.Add(val5);
								}
							}
						}
					}
				}
				s_Clips.AddRange(from a in val2.GetComponentsInChildren<AudioSource>(true)
					select a.clip into c
					where (Object)(object)c != (Object)null
					select c);
				s_Sfx = s_Sfx.Distinct().ToList();
				Plugin.Log.LogInfo((object)$"[OTL][UI] capture sound: {s_Sfx.Count} SFX asset(s), {s_Clips.Count} clip(s) from {((Object)val2).name}.");
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("[OTL][UI] couldn't load capture sound: " + ex.Message));
			}
		}
	}
	internal sealed class ChaseEffects : MonoBehaviour
	{
		private static readonly Color ChaserGlow = new Color(1f, 0.08f, 0.05f);

		private bool _fearChecked;

		private void LateUpdate()
		{
			UpdateChaserGlow();
			UpdateChaseMusic();
		}

		private void UpdateChaserGlow()
		{
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			if (!RoundManager.IsActive || !Plugin.ModConfig.ChaserRedOutline.Synced<bool>())
			{
				return;
			}
			float num = Mathf.Clamp(Plugin.ModConfig.ChaserGlowIntensity.Synced<float>(), 0f, 2f);
			foreach (Character allCharacter in Character.AllCharacters)
			{
				if (!((Object)(object)allCharacter == (Object)null) && !allCharacter.data.dead && RoleManager.IsChaser(allCharacter) && !allCharacter.data.isInvincible && !FreezeState.IsFrozen(Net.Actor(allCharacter)))
				{
					allCharacter.refs.customization.PulseStatus(ChaserGlow, num);
				}
			}
		}

		private void UpdateChaseMusic()
		{
			//IL_0079: 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)
			if (!RoundManager.IsChasing || !Plugin.ModConfig.ScoutmasterChaseMusic.Synced<bool>())
			{
				return;
			}
			Character localCharacter = Character.localCharacter;
			if ((Object)(object)localCharacter == (Object)null || localCharacter.data.dead || !RoleManager.IsRunner(localCharacter))
			{
				return;
			}
			float num = float.MaxValue;
			foreach (Character allCharacter in Character.AllCharacters)
			{
				if (!((Object)(object)allCharacter == (Object)null) && !allCharacter.data.dead && RoleManager.IsChaser(allCharacter))
				{
					num = Mathf.Min(num, Vector3.Distance(allCharacter.Center, localCharacter.Center));
				}
			}
			if (num != float.MaxValue)
			{
				if (!_fearChecked)
				{
					_fearChecked = true;
					Plugin.Log.LogInfo((object)$"[OTL][Effects] chase music: MyresAmbience on the local character = {(Object)(object)((Component)localCharacter).GetComponentInChildren<MyresAmbience>(true) != (Object)null}.");
				}
				localCharacter.data.myersDistance = Mathf.Max(0.1f, num);
			}
		}
	}
	internal sealed class ChaserOddsMenu : MonoBehaviour
	{
		private static readonly Color Selected = new Color(1f, 0.84f, 0.2f);

		private Canvas? _canvas;

		private RectTransform? _panel;

		private Canvas? _hintCanvas;

		private TextMeshProUGUI? _hint;

		private RectTransform? _hintPlate;

		private readonly Dictionary<ChaserPref, (TextMeshProUGUI Label, string Text)> _options = new Dictionary<ChaserPref, (TextMeshProUGUI, string)>();

		public static bool IsOpen { get; private set; }

		private void Update()
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			ChaserPreference.LocalTick();
			bool flag = ChaserPreference.Available && (Object)(object)GUIManager.instance != (Object)null;
			if (IsOpen && !flag)
			{
				Close();
			}
			UpdateHint(flag);
			if (!flag)
			{
				return;
			}
			Keyboard current = Keyboard.current;
			if (current == null)
			{
				return;
			}
			if (((ButtonControl)current[Plugin.ModConfig.KeyChaserOdds.Value]).wasPressedThisFrame)
			{
				if (IsOpen)
				{
					Close();
				}
				else
				{
					Open();
				}
			}
			else if (IsOpen && ((ButtonControl)current.escapeKey).wasPressedThisFrame)
			{
				Close();
			}
		}

		private void UpdateHint(bool available)
		{
			bool flag = available && !IsOpen && !HostMenu.IsOpen;
			if (flag && (Object)(object)_hintCanvas == (Object)null)
			{
				BuildHint();
			}
			if ((Object)(object)_hintCanvas != (Object)null && ((Component)_hintCanvas).gameObject.activeSelf != flag)
			{
				((Component)_hintCanvas).gameObject.SetActive(flag);
			}
			if (flag && (Object)(object)_hint != (Object)null)
			{
				string text = "PRESS HOTKEY (" + KeyName() + ") TO SELECT YOUR ROLE: " + ((ChaserPreference.Local == ChaserPref.Chaser) ? "CHASER" : "RUNNER");
				if (((TMP_Text)_hint).text != text)
				{
					((TMP_Text)_hint).text = text;
					FitHintPlate();
				}
			}
		}

		private void BuildHint()
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Expected O, but got Unknown
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Expected O, but got Unknown
			//IL_0099: 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_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: 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_00e7: 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_0144: 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_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: 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)
			GUIManager instance = GUIManager.instance;
			_hintCanvas = PeakMenuKit.CreateCanvas("OTL_ChaserOddsHint", ((Component)this).transform, instance, 20);
			((Behaviour)((Component)_hintCanvas).GetComponent<GraphicRaycaster>()).enabled = false;
			GameObject val = new GameObject("Plate", new Type[1] { typeof(RectTransform) });
			val.transform.SetParent(((Component)_hintCanvas).transform, false);
			_hintPlate = (RectTransform)val.transform;
			RectTransform? hintPlate = _hintPlate;
			RectTransform? hintPlate2 = _hintPlate;
			RectTransform? hintPlate3 = _hintPlate;
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(0.5f, 0f);
			hintPlate3.pivot = val2;
			Vector2 anchorMin = (hintPlate2.anchorMax = val2);
			hintPlate.anchorMin = anchorMin;
			_hintPlate.anchoredPosition = new Vector2(0f, 36f);
			Image val4 = val.AddComponent<Image>();
			((Graphic)val4).color = new Color(0.04f, 0.05f, 0.08f, 0.72f);
			((Graphic)val4).raycastTarget = false;
			_hint = PeakMenuKit.AddText((Transform)(object)_hintPlate, "", instance.interactNameText, 34f, new Color(1f, 0.84f, 0.2f, 1f), 50f);
			RectTransform rectTransform = ((TMP_Text)_hint).rectTransform;
			rectTransform.anchorMin = Vector2.zero;
			rectTransform.anchorMax = Vector2.one;
			anchorMin = (rectTransform.offsetMax = Vector2.zero);
			rectTransform.offsetMin = anchorMin;
		}

		private void FitHintPlate()
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_hint == (Object)null) && !((Object)(object)_hintPlate == (Object)null))
			{
				_hintPlate.sizeDelta = new Vector2(((TMP_Text)_hint).preferredWidth + 48f, ((TMP_Text)_hint).preferredHeight + 16f);
			}
		}

		private static string KeyName()
		{
			//IL_001b: 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)
			Keyboard current = Keyboard.current;
			string text = ((current != null) ? ((InputControl)current[Plugin.ModConfig.KeyChaserOdds.Value]).displayName : "");
			if (!string.IsNullOrWhiteSpace(text))
			{
				return text.ToUpperInvariant();
			}
			return ((object)Plugin.ModConfig.KeyChaserOdds.Value/*cast due to .constrained prefix*/).ToString().ToUpperInvariant();
		}

		private void Open()
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			if (Build())
			{
				IsOpen = true;
				((Component)_canvas).gameObject.SetActive(true);
				RefreshSelection();
				RectTransform panel = _panel;
				ShortcutExtensions.DOKill((Component)(object)panel, false);
				((Transform)panel).localScale = Vector3.one * 0.9f;
				TweenSettingsExtensions.SetEase<TweenerCore<Vector3, Vector3, VectorOptions>>(ShortcutExtensions.DOScale((Transform)(object)panel, 1f, 0.2f), (Ease)27);
			}
		}

		private void Close()
		{
			IsOpen = false;
			if ((Object)(object)_canvas != (Object)null)
			{
				((Component)_canvas).gameObject.SetActive(false);
			}
		}

		private bool Build()
		{
			//IL_0062: 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)
			//IL_00d9: 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_0131: Expected O, but got Unknown
			if ((Object)(object)_canvas != (Object)null)
			{
				return true;
			}
			GUIManager instance = GUIManager.instance;
			Button val = PeakMenuKit.ButtonTemplate(instance);
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogWarning((object)"[OTL][Roles] PEAK's pause menu button not found; can't build the menu.");
				return false;
			}
			_canvas = PeakMenuKit.CreateCanvas("OTL_ChaserOdds", ((Component)this).transform, instance, 50);
			_panel = PeakMenuKit.CreatePanel(_canvas, val, new Vector2(720f, 520f));
			TextMeshProUGUI style = (((Object)(object)instance.heroText != (Object)null) ? instance.heroText : instance.interactNameText);
			PeakMenuKit.AddText((Transform)(object)_panel, "YOUR ROLE", style, 64f, Color.white, 80f);
			PeakMenuKit.AddText((Transform)(object)_panel, "ONLY YOU CAN SEE THIS  -  CHASERS ARE DRAWN FROM VOLUNTEERS", instance.interactNameText, 22f, new Color(1f, 1f, 1f, 0.7f), 32f);
			AddOption(val, ChaserPref.Runner, "I WANT TO BE A RUNNER");
			AddOption(val, ChaserPref.Chaser, "I WANT TO BE A CHASER");
			Button item = PeakMenuKit.CloneButton((Transform)(object)_panel, val, "CLOSE").Button;
			((UnityEvent)item.onClick).AddListener(new UnityAction(Close));
			((Component)_canvas).gameObject.SetActive(false);
			return true;
		}

		private void AddOption(Button template, ChaserPref pref, string text)
		{
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Expected O, but got Unknown
			var (val, item) = PeakMenuKit.CloneButton((Transform)(object)_panel, template, text);
			_options[pref] = (item, text);
			((UnityEvent)val.onClick).AddListener((UnityAction)delegate
			{
				ChaserPreference.SetLocal(pref);
				RefreshSelection();
			});
		}

		private void RefreshSelection()
		{
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			foreach (KeyValuePair<ChaserPref, (TextMeshProUGUI, string)> option in _options)
			{
				bool flag = option.Key == ChaserPreference.Local;
				((TMP_Text)option.Value.Item1).text = (flag ? ("> " + option.Value.Item2 + " <") : option.Value.Item2);
				((Graphic)option.Value.Item1).color = (flag ? Selected : Color.white);
			}
		}
	}
	internal sealed class GhostVisibility : MonoBehaviour
	{
		private const float Interval = 0.25f;

		private readonly Dictionary<PlayerGhost, List<Renderer>> _hiddenRenderers = new Dictionary<PlayerGhost, List<Renderer>>();

		private readonly Dictionary<PlayerGhost, bool> _hiddenThirdEye = new Dictionary<PlayerGhost, bool>();

		private float _next;

		private static bool ShouldHide()
		{
			Character localCharacter = Character.localCharacter;
			if (!Plugin.ModConfig.ChasersSeeGhosts.Synced<bool>() && (Object)(object)localCharacter != (Object)null && !localCharacter.data.dead)
			{
				return RoleManager.IsChaser(localCharacter);
			}
			return false;
		}

		private void Update()
		{
			if (Time.time < _next)
			{
				return;
			}
			_next = Time.time + 0.25f;
			bool flag = ShouldHide();
			if (!flag && _hiddenRenderers.Count == 0)
			{
				return;
			}
			PlayerGhost[] array = Object.FindObjectsByType<PlayerGhost>((FindObjectsSortMode)0);
			foreach (PlayerGhost val in array)
			{
				if (!((Object)(object)val == (Object)null) && (!((Object)(object)val.m_owner != (Object)null) || !val.m_owner.IsLocal))
				{
					if (flag)
					{
						Hide(val);
					}
					else
					{
						Show(val);
					}
				}
			}
			foreach (PlayerGhost item in new List<PlayerGhost>(_hiddenRenderers.Keys))
			{
				if ((Object)(object)item == (Object)null)
				{
					_hiddenRenderers.Remove(item);
					_hiddenThirdEye.Remove(item);
				}
			}
		}

		private void Hide(PlayerGhost ghost)
		{
			if (_hiddenRenderers.ContainsKey(ghost))
			{
				return;
			}
			List<Renderer> list = new List<Renderer>();
			foreach (Renderer item in AllRenderers(ghost))
			{
				if ((Object)(object)item != (Object)null && item.enabled)
				{
					item.enabled = false;
					list.Add(item);
				}
			}
			_hiddenRenderers[ghost] = list;
			bool flag = (Object)(object)ghost.thirdEye != (Object)null && ghost.thirdEye.activeSelf;
			if (flag)
			{
				ghost.thirdEye.SetActive(false);
			}
			_hiddenThirdEye[ghost] = flag;
		}

		private void Show(PlayerGhost ghost)
		{
			if (!_hiddenRenderers.TryGetValue(ghost, out List<Renderer> value))
			{
				return;
			}
			foreach (Renderer item in value)
			{
				if ((Object)(object)item != (Object)null)
				{
					item.enabled = true;
				}
			}
			if (_hiddenThirdEye.TryGetValue(ghost, out var value2) && value2 && (Object)(object)ghost.thirdEye != (Object)null)
			{
				ghost.thirdEye.SetActive(true);
			}
			_hiddenRenderers.Remove(ghost);
			_hiddenThirdEye.Remove(ghost);
		}

		private static IEnumerable<Renderer> AllRenderers(PlayerGhost ghost)
		{
			if (ghost.PlayerRenderers != null)
			{
				Renderer[] playerRenderers = ghost.PlayerRenderers;
				for (int i = 0; i < playerRenderers.Length; i++)
				{
					yield return playerRenderers[i];
				}
			}
			if (ghost.EyeRenderers != null)
			{
				Renderer[] playerRenderers = ghost.EyeRenderers;
				for (int i = 0; i < playerRenderers.Length; i++)
				{
					yield return playerRenderers[i];
				}
			}
			yield return ghost.mouthRenderer;
			yield return ghost.accessoryRenderer;
		}
	}
	internal sealed class HostMenu : MonoBehaviour
	{
		private sealed class SettingRow
		{
			public string Label = "";

			public Func<ConfigEntry<float>> Entry;

			public float Step;

			public float Min;

			public float Max;

			public bool Seconds = true;

			public TextMeshProUGUI? Text;
		}

		private const float ConfirmSeconds = 3f;

		private Canvas? _canvas;

		private RectTransform? _panel;

		private TextMeshProUGUI? _debugLabel;

		private readonly Dictionary<TextMeshProUGUI, string> _labels = new Dictionary<TextMeshProUGUI, string>();

		private TextMeshProUGUI? _pendingLabel;

		private Action? _pendingAction;

		private float _pendingUntil;

		private Canvas? _hintCanvas;

		private RectTransform? _hintPlate;

		private TextMeshProUGUI? _hint;

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

		private readonly List<GameObject> _mainPage = new List<GameObject>();

		private readonly List<GameObject> _settingsPage = new List<GameObject>();

		private readonly List<SettingRow> _settings = new List<SettingRow>();

		public static bool IsOpen { get; private set; }

		public static bool Install(Harmony harmony)
		{
			return SafePatch.Postfix(harmony, typeof(GUIManager), "UpdateWindowStatus", typeof(HostMenu), "WindowStatusPostfix", "HostMenu");
		}

		public static void WindowStatusPostfix(GUIManager __instance)
		{
			if (IsOpen || ChaserOddsMenu.IsOpen)
			{
				__instance.windowShowingCursor = true;
				__instance.windowBlockingInput = true;
			}
		}

		private void Update()
		{
			//IL_006d: 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)
			//IL_0074: 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_0084: Invalid comparison between Unknown and I4
			Keyboard current = Keyboard.current;
			bool flag = Net.InRoom && Net.IsHost && (Object)(object)GUIManager.instance != (Object)null && (Object)(object)Character.localCharacter != (Object)null;
			UpdateHint(flag && !IsOpen && !ChaserOddsMenu.IsOpen);
			if (IsOpen && !flag)
			{
				Close();
			}
			else
			{
				if (current == null || !flag)
				{
					return;
				}
				Key value = Plugin.ModConfig.KeyHostMenu.Value;
				if (((ButtonControl)current[value]).wasPressedThisFrame || ((int)value == 14 && ((ButtonControl)current.numpadPlusKey).wasPressedThisFrame))
				{
					if (IsOpen)
					{
						Close();
					}
					else
					{
						Open();
					}
				}
				else if (IsOpen && ((ButtonControl)current.escapeKey).wasPressedThisFrame)
				{
					Close();
				}
				if ((Object)(object)_pendingLabel != (Object)null && Time.time > _pendingUntil)
				{
					ClearPending();
				}
			}
		}

		private void UpdateHint(bool show)
		{
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//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_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Expected O, but got Unknown
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			GUIManager instance = GUIManager.instance;
			RectTransform val = (((Object)(object)instance != (Object)null && (Object)(object)instance.bar != (Object)null) ? instance.bar.fullBar : null);
			show &= (Object)(object)val != (Object)null && ((Component)val).gameObject.activeInHierarchy;
			if (show && (Object)(object)_hintCanvas == (Object)null)
			{
				BuildHint(instance);
			}
			if ((Object)(object)_hintCanvas == (Object)null)
			{
				return;
			}
			if (((Component)_hintCanvas).gameObject.activeSelf != show)
			{
				((Component)_hintCanvas).gameObject.SetActive(show);
			}
			if (show)
			{
				string text = "PRESS HOTKEY (" + HostKeyName() + ") FOR HOST CONTROLS";
				if (((TMP_Text)_hint).text != text)
				{
					((TMP_Text)_hint).text = text;
					_hintPlate.sizeDelta = new Vector2(((TMP_Text)_hint).preferredWidth + 28f, ((TMP_Text)_hint).preferredHeight + 10f);
				}
				val.GetWorldCorners(_corners);
				Canvas componentInParent = ((Component)val).GetComponentInParent<Canvas>();
				Camera val2 = (((Object)(object)componentInParent != (Object)null && (int)componentInParent.renderMode != 0) ? componentInParent.worldCamera : null);
				Vector2 val3 = RectTransformUtility.WorldToScreenPoint(val2, _corners[1]);
				Vector2 val4 = default(Vector2);
				if (RectTransformUtility.ScreenPointToLocalPointInRectangle((RectTransform)((Component)_hintCanvas).transform, val3, (Camera)null, ref val4))
				{
					_hintPlate.anchoredPosition = val4 + new Vector2(0f, 12f);
				}
			}
		}

		private void BuildHint(GUIManager gui)
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Expected O, but got Unknown
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Expected O, but got Unknown
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: 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_00cf: 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_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: 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_0149: 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)
			_hintCanvas = PeakMenuKit.CreateCanvas("OTL_HostHint", ((Component)this).transform, gui, 19);
			((Behaviour)((Component)_hintCanvas).GetComponent<GraphicRaycaster>()).enabled = false;
			GameObject val = new GameObject("Plate", new Type[1] { typeof(RectTransform) });
			val.transform.SetParent(((Component)_hintCanvas).transform, false);
			_hintPlate = (RectTransform)val.transform;
			RectTransform? hintPlate = _hintPlate;
			RectTransform? hintPlate2 = _hintPlate;
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(0.5f, 0.5f);
			hintPlate2.anchorMax = val2;
			hintPlate.anchorMin = val2;
			_hintPlate.pivot = new Vector2(0f, 0f);
			Image val3 = val.AddComponent<Image>();
			((Graphic)val3).color = new Color(0.04f, 0.05f, 0.08f, 0.45f);
			((Graphic)val3).raycastTarget = false;
			_hint = PeakMenuKit.AddText((Transform)(object)_hintPlate, "", gui.interactNameText, 18f, new Color(1f, 0.84f, 0.2f, 1f), 30f);
			RectTransform rectTransform = ((TMP_Text)_hint).rectTransform;
			rectTransform.anchorMin = Vector2.zero;
			rectTransform.anchorMax = Vector2.one;
			val2 = (rectTransform.offsetMin = (rectTransform.offsetMax = Vector2.zero));
		}

		private unsafe static string HostKeyName()
		{
			//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_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Invalid comparison between Unknown and I4
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Invalid comparison between Unknown and I4
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			Key value = Plugin.ModConfig.KeyHostMenu.Value;
			if (((int)value == 14 || (int)value == 80) ? true : false)
			{
				return "+";
			}
			Keyboard current = Keyboard.current;
			string text = ((current != null) ? ((InputControl)current[value]).displayName : "");
			if (!string.IsNullOrWhiteSpace(text))
			{
				return text.ToUpperInvariant();
			}
			return ((object)(*(Key*)(&value))/*cast due to .constrained prefix*/).ToString().ToUpperInvariant();
		}

		private void Open()
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			if (Build())
			{
				IsOpen = true;
				((Component)_canvas).gameObject.SetActive(true);
				RefreshDebugLabel();
				RectTransform panel = _panel;
				ShortcutExtensions.DOKill((Component)(object)panel, false);
				((Transform)panel).localScale = Vector3.one * 0.9f;
				TweenSettingsExtensions.SetEase<TweenerCore<Vector3, Vector3, VectorOptions>>(ShortcutExtensions.DOScale((Transform)(object)panel, 1f, 0.2f), (Ease)27);
			}
		}

		private void Close()
		{
			IsOpen = false;
			ClearPending();
			if ((Object)(object)_panel != (Object)null)
			{
				ShowPage(settings: false);
			}
			if ((Object)(object)_canvas != (Object)null)
			{
				((Component)_canvas).gameObject.SetActive(false);
			}
		}

		private bool Build()
		{
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			GUIManager instance = GUIManager.instance;
			if ((Object)(object)_canvas != (Object)null)
			{
				return true;
			}
			Button val = PeakMenuKit.ButtonTemplate(instance);
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogWarning((object)"[OTL][HostMenu] PEAK's pause menu button not found; can't build the menu.");
				return false;
			}
			_canvas = PeakMenuKit.CreateCanvas("OTL_HostMenu", ((Component)this).transform, instance, 50);
			_panel = PeakMenuKit.CreatePanel(_canvas, val, new Vector2(760f, 640f));
			((Component)_panel).gameObject.AddComponent<ContentSizeFitter>().verticalFit = (FitMode)2;
			TextMeshProUGUI style = (((Object)(object)instance.heroText != (Object)null) ? instance.heroText : instance.interactNameText);
			PeakMenuKit.AddText((Transform)(object)_panel, "HOST MENU", style, 64f, Color.white, 80f);
			PeakMenuKit.AddText((Transform)(object)_panel, "ON THE LOOKOUT", instance.interactNameText, 26f, new Color(1f, 0.84f, 0.2f), 36f);
			int childCount = ((Transform)_panel).childCount;
			AddButton(val, "RESTART AT THE AIRPORT", confirm: true, AdminRestart.HostReturnToAirport);
			AddButton(val, "RESTART AT PREVIOUS CAMPFIRE", confirm: true, AdminRestart.HostRestartFromCampfire);
			AddButton(val, "TELEPORT EVERYONE TO NEXT CAMPFIRE", confirm: false, AdminRestart.HostTeleportToNextCampfire);
			AddButton(val, "SETTINGS", confirm: false, delegate
			{
				ShowPage(settings: true);
			}, closeAfter: false);
			_debugLabel = AddButton(val, "", confirm: false, ToggleDebugKeys, closeAfter: false);
			AddButton(val, "CLOSE", confirm: false, delegate
			{
			});
			CollectPage(_mainPage, childCount);
			childCount = ((Transform)_panel).childCount;
			BuildSettingsPage(instance, val);
			CollectPage(_settingsPage, childCount);
			ShowPage(settings: false);
			((Component)_canvas).gameObject.SetActive(false);
			Plugin.Log.LogInfo((object)"[OTL][HostMenu] built.");
			return true;
		}

		private TextMeshProUGUI AddButton(Button template, string label, bool confirm, Action action, bool closeAfter = true)
		{
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Expected O, but got Unknown
			var (val, text) = PeakMenuKit.CloneButton((Transform)(object)_panel, template, label);
			_labels[text] = label;
			((UnityEvent)val.onClick).AddListener((UnityAction)delegate
			{
				if (confirm && (Object)(object)_pendingLabel != (Object)(object)text)
				{
					ClearPending();
					_pendingLabel = text;
					_pendingAction = action;
					_pendingUntil = Time.time + 3f;
					((TMP_Text)text).text = "CLICK AGAIN TO CONFIRM";
				}
				else
				{
					ClearPending();
					try
					{
						action();
					}
					catch (Exception arg)
					{
						Plugin.Log.LogError((object)$"[OTL][HostMenu] '{label}' failed: {arg}");
					}
					if (closeAfter)
					{
						Close();
					}
				}
			});
			return text;
		}

		private void ClearPending()
		{
			if ((Object)(object)_pendingLabel != (Object)null && _labels.TryGetValue(_pendingLabel, out string value))
			{
				((TMP_Text)_pendingLabel).text = value;
			}
			_pendingLabel = null;
			_pendingAction = null;
		}

		private void CollectPage(List<GameObject> page, int first)
		{
			for (int i = first; i < ((Transform)_panel).childCount; i++)
			{
				page.Add(((Component)((Transform)_panel).GetChild(i)).gameObject);
			}
		}

		private void ShowPage(bool settings)
		{
			ClearPending();
			foreach (GameObject item in _mainPage)
			{
				item.SetActive(!settings);
			}
			foreach (GameObject item2 in _settingsPage)
			{
				item2.SetActive(settings);
			}
			if (settings)
			{
				RefreshSettings();
			}
		}

		private void BuildSettingsPage(GUIManager gui, Button template)
		{
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			ModConfig cfg = Plugin.ModConfig;
			_settings.Clear();
			_settings.Add(new SettingRow
			{
				Label = "HEAD START",
				Entry = () => cfg.HeadStartSeconds,
				Step = 5f,
				Min = 0f,
				Max = 120f
			});
			_settings.Add(new SettingRow
			{
				Label = "HEAD-START SPEED BOOST",
				Entry = () => cfg.HeadStartBoostSeconds,
				Step = 1f,
				Min = 0f,
				Max = 20f
			});
			_settings.Add(new SettingRow
			{
				Label = "RUNNERS PER CHASER",
				Entry = () => cfg.RunnersPerChaser,
				Step = 1f,
				Min = 1f,
				Max = 10f,
				Seconds = false
			});
			_settings.Add(new SettingRow
			{
				Label = "ZOMBIES START AFTER",
				Entry = () => cfg.ZombieStartDelaySeconds,
				Step = 30f,
				Min = 0f,
				Max = 1200f
			});
			_settings.Add(new SettingRow
			{
				Label = "ZOMBIE WAVE COOLDOWN",
				Entry = () => cfg.ZombieWaveDelaySeconds,
				Step = 15f,
				Min = 0f,
				Max = 600f
			});
			_settings.Add(new SettingRow
			{
				Label = "ZOMBIE LIFETIME",
				Entry = () => cfg.ZombieLifetimeSeconds,
				Step = 15f,
				Min = 15f,
				Max = 600f
			});
			PeakMenuKit.AddText((Transform)(object)_panel, "SETTINGS  (FROM THE NEXT LEG ON)", gui.interactNameText, 22f, new Color(1f, 1f, 1f, 0.7f), 30f);
			foreach (SettingRow setting in _settings)
			{
				AddSettingRow(gui, template, setting);
			}
			AddButton(template, "RESET TO DEFAULTS", confirm: true, ResetSettings, closeAfter: false);
			AddButton(template, "BACK", confirm: false, delegate
			{
				ShowPage(settings: false);
			}, closeAfter: false);
		}

		private void AddSettingRow(GUIManager gui, Button template, SettingRow row)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: 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)
			//IL_0125: Expected O, but got Unknown
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Expected O, but got Unknown
			RectTransform val = PeakMenuKit.NewRect("OTL_SettingRow", (Transform)(object)_panel);
			val.sizeDelta = new Vector2(0f, 64f);
			HorizontalLayoutGroup val2 = ((Component)val).gameObject.AddComponent<HorizontalLayoutGroup>();
			((HorizontalOrVerticalLayoutGroup)val2).spacing = 12f;
			((LayoutGroup)val2).childAlignment = (TextAnchor)4;
			((HorizontalOrVerticalLayoutGroup)val2).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)val2).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)val2).childForceExpandWidth = false;
			((HorizontalOrVerticalLayoutGroup)val2).childForceExpandHeight = true;
			Button item = PeakMenuKit.CloneButton((Transform)(object)val, template, "-").Button;
			((Component)item).gameObject.AddComponent<LayoutElement>().preferredWidth = 90f;
			row.Text = PeakMenuKit.AddText((Transform)(object)val, "", gui.interactNameText, 26f, Color.white, 64f);
			((Component)row.Text).gameObject.AddComponent<LayoutElement>().flexibleWidth = 1f;
			Button item2 = PeakMenuKit.CloneButton((Transform)(object)val, template, "+").Button;
			((Component)item2).gameObject.AddComponent<LayoutElement>().preferredWidth = 90f;
			((UnityEvent)item.onClick).AddListener((UnityAction)delegate
			{
				ChangeSetting(row, 0f - row.Step);
			});
			((UnityEvent)item2.onClick).AddListener((UnityAction)delegate
			{
				ChangeSetting(row, row.Step);
			});
		}

		private void ChangeSetting(SettingRow row, float delta)
		{
			ConfigEntry<float> val = row.Entry();
			float num = Mathf.Clamp(Mathf.Round((val.Value + delta) / row.Step) * row.Step, row.Min, row.Max);
			if (!Mathf.Approximately(num, val.Value))
			{
				val.Value = num;
				Plugin.Log.LogInfo((object)$"[OTL][HostMenu] {((ConfigEntryBase)val).Definition.Key} = {num:0.##}.");
				RefreshSettings();
			}
		}

		private void ResetSettings()
		{
			foreach (SettingRow setting in _settings)
			{
				ConfigEntry<float> val = setting.Entry();
				val.Value = (float)((ConfigEntryBase)val).DefaultValue;
			}
			Plugin.Log.LogInfo((object)"[OTL][HostMenu] settings reset to the defaults.");
			RefreshSettings();
		}

		private void RefreshSettings()
		{
			foreach (SettingRow setting in _settings)
			{
				if (!((Object)(object)setting.Text == (Object)null))
				{
					float value = setting.Entry().Value;
					((TMP_Text)setting.Text).text = setting.Label + ": " + (setting.Seconds ? FormatSeconds(value) : value.ToString("0"));
				}
			}
		}

		private static string FormatSeconds(float seconds)
		{
			if (!(seconds >= 60f))
			{
				return $"{seconds:0} S";
			}
			return $"{Mathf.FloorToInt(seconds / 60f)}:{Mathf.RoundToInt(seconds % 60f):00} MIN";
		}

		private void ToggleDebugKeys()
		{
			Plugin.ModConfig.DebugKeys.Value = !Plugin.ModConfig.DebugKeys.Value;
			RefreshDebugLabel();
			Plugin.Log.LogInfo((object)("[OTL][HostMenu] debug hotkeys " + (Plugin.ModConfig.DebugKeys.Value ? "enabled" : "disabled") + "."));
		}

		private void RefreshDebugLabel()
		{
			if (!((Object)(object)_debugLabel == (Object)null))
			{
				string text = "DEBUG HOTKEYS: " + (Plugin.ModConfig.DebugKeys.Value ? "ON" : "OFF");
				((TMP_Text)_debugLabel).text = text;
				_labels[_debugLabel] = text;
			}
		}
	}
	internal sealed class Hud : MonoBehaviour
	{
		private static readonly Color ChaserRed = new Color(0.93f, 0.22f, 0.2f);

		private static readonly Color RunnerYellow = new Color(1f, 0.84f, 0.2f);

		private static readonly Color Warm = new Color(1f, 0.78f, 0.36f);

		private static readonly Color ZombieGreen = new Color(0.62f, 0.9f, 0.38f);

		private const string IceHex = "#9FDCFF";

		private Canvas? _overlay;

		private CanvasScaler? _overlayScaler;

		private Image? _blind;

		private TextMeshProUGUI? _centerMain;

		private TextMeshProUGUI? _centerSub;

		private string _lastCenter = "";

		private bool _overlayFontSet;

		private Canvas? _hudCanvas;

		private BlowgunCooldownUI? _blowgunCooldown;

		private BlowgunCooldownUI? _gemCooldown;

		private BlowgunCooldownUI? _dashCooldown;

		private TextMeshProUGUI? _chaserList;

		private TextMeshProUGUI? _toast;

		private CanvasGroup? _toastGroup;

		private float _nextListRefresh;

		private string _announce = "";

		private string _announceSub = "";

		private Color _announceColor = Color.white;

		private float _announceUntil;

		private float _nextFreezeWarning;

		private void Awake()
		{
			BuildOverlay();
		}

		private void OnEnable()
		{
			RoundManager.LegStarted += OnLegStarted;
			RoundManager.LegCompleted += OnLegCompleted;
			RoundManager.RoundEnded += OnRoundEnded;
			ModNetwork.NoticeReceived += OnNotice;
			ItemRules.LocalDenied += Toast;
		}

		private void OnDisable()
		{
			RoundManager.LegStarted -= OnLegStarted;
			RoundManager.LegCompleted -= OnLegCompleted;
			RoundManager.RoundEnded -= OnRoundEnded;
			ModNetwork.NoticeReceived -= OnNotice;
			ItemRules.LocalDenied -= Toast;
		}

		private void BuildOverlay()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: 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_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("OTL_Overlay", new Type[1] { typeof(RectTransform) });
			val.transform.SetParent(((Component)this).transform, false);
			_overlay = val.AddComponent<Canvas>();
			_overlay.renderMode = (RenderMode)0;
			_overlay.sortingOrder = 100;
			_overlayScaler = val.AddComponent<CanvasScaler>();
			_overlayScaler.uiScaleMode = (ScaleMode)1;
			_overlayScaler.referenceResolution = new Vector2(1920f, 1080f);
			_overlayScaler.matchWidthOrHeight = 0.5f;
			RectTransform val2 = NewRect("OTL_Blind", val.transform);
			Stretch(val2);
			_blind = ((Component)val2).gameObject.AddComponent<Image>();
			((Graphic)_blind).color = new Color(0f, 0f, 0f, 0f);
			((Graphic)_blind).raycastTarget = false;
			_centerMain = NewText("OTL_CenterMain", val.transform, null, 150f, (TextAlignmentOptions)514);
			((TMP_Text)_centerMain).rectTransform.sizeDelta = new Vector2(1800f, 220f);
			((TMP_Text)_centerMain).rectTransform.anchoredPosition = new Vector2(0f, 40f);
			_centerSub = NewText("OTL_CenterSub", val.transform, null, 46f, (TextAlignmentOptions)514);
			((TMP_Text)_centerSub).rectTransform.sizeDelta = new Vector2(1800f, 80f);
			((TMP_Text)_centerSub).rectTransform.anchoredPosition = new Vector2(0f, 170f);
		}

		private void StyleOverlay(GUIManager gui)
		{
			//IL_006b: 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_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: 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_00e2: Unknown result type (might be due to invalid IL or missing references)
			if (_overlayFontSet || (Object)(object)_centerMain == (Object)null || (Object)(object)_centerSub == (Object)null)
			{
				return;
			}
			TextMeshProUGUI style = (((Object)(object)gui.heroText != (Object)null) ? gui.heroText : gui.interactNameText);
			ApplyFont(_centerMain, style);
			ApplyFont(_centerSub, gui.interactNameText);
			TextMeshProUGUI? centerMain = _centerMain;
			Color color = (((Graphic)_centerSub).color = Color.white);
			((Graphic)centerMain).color = color;
			if ((Object)(object)gui.hudCanvas != (Object)null)
			{
				CanvasScaler component = ((Component)gui.hudCanvas).GetComponent<CanvasScaler>();
				if (component != null && (Object)(object)_overlayScaler != (Object)null)
				{
					_overlayScaler.uiScaleMode = component.uiScaleMode;
					_overlayScaler.referenceResolution = component.referenceResolution;
					_overlayScaler.matchWidthOrHeight = component.matchWidthOrHeight;
					_overlayScaler.screenMatchMode = component.screenMatchMode;
				}
			}
			if ((Object)(object)gui.hudCanvas != (Object)null && (Object)(object)_overlay != (Object)null)
			{
				_overlay.sortingOrder = gui.hudCanvas.sortingOrder + 10;
			}
			_overlayFontSet = true;
		}

		private bool EnsureHud()
		{
			GUIManager instance = GUIManager.instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)instance.hudCanvas == (Object)null)
			{
				return false;
			}
			StyleOverlay(instance);
			if ((Object)(object)_hudCanvas == (Object)(object)instance.hudCanvas && (Object)(object)_toast != (Object)null)
			{
				if ((Object)(object)_chaserList == (Object)null)
				{
					BuildChaserList(((Component)_hudCanvas).transform, instance.interactNameText);
				}
				return true;
			}
			_hudCanvas = instance.hudCanvas;
			BuildChaserList(((Component)_hudCanvas).transform, instance.interactNameText);
			BuildToast(((Component)_hudCanvas).transform, instance.interactNameText);
			_blowgunCooldown?.Destroy();
			_gemCooldown?.Destroy();
			_dashCooldown?.Destroy();
			if ((Object)(object)_overlay != (Object)null)
			{
				TextMeshProUGUI fontStyle = (((Object)(object)instance.heroText != (Object)null) ? instance.heroText : instance.interactNameText);
				_blowgunCooldown = new BlowgunCooldownUI(_overlay, fontStyle);
				_gemCooldown = new BlowgunCooldownUI(_overlay, fontStyle, "Gem", () => ChaserKit.GemOnCooldown, () => ChaserKit.GemCooldownLeft, (Item item) => ChaserKit.IsGem(item), RoleManager.IsChaser);
				_dashCooldown = new BlowgunCooldownUI(_overlay, fontStyle, "Dash", () => RunnerDash.OnCooldown, () => RunnerDash.CooldownLeft, (Item item) => RunnerDash.IsRunnerGem(item), RoleManager.IsRunner);
			}
			Plugin.Log.LogInfo((object)$"[OTL][UI] HUD built on '{((Object)_hudCanvas).name}' (stamina bar found: {(Object)(object)instance.bar != (Object)null}).");
			return true;
		}

		private void BuildChaserList(Transform canvas, TextMeshProUGUI fallbackStyle)
		{
			//IL_015c: 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_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: 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_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: 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)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: 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_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			AscentUI val = Object.FindFirstObjectByType<AscentUI>((FindObjectsInactive)1);
			TextMeshProUGUI val2 = (((Object)(object)val != (Object)null) ? val.text : null);
			if ((Object)(object)val2 != (Object)null && ((Component)val2).gameObject.activeInHierarchy)
			{
				RectTransform rectTransform = ((TMP_Text)val2).rectTransform;
				_chaserList = NewText("OTL_ChaserList", ((Transform)rectTransform).parent, val2, ((TMP_Text)val2).fontSize * 0.7f, ((TMP_Text)val2).alignment);
				RectTransform rectTransform2 = ((TMP_Text)_chaserList).rectTransform;
				rectTransform2.anchorMin = rectTransform.anchorMin;
				rectTransform2.anchorMax = rectTransform.anchorMax;
				rectTransform2.pivot = new Vector2(rectTransform.pivot.x, 1f);
				Rect rect = rectTransform.rect;
				rectTransform2.sizeDelta = new Vector2(Mathf.Max(((Rect)(ref rect)).width, 420f), 400f);
				Vector2 anchoredPosition = rectTransform.anchoredPosition;
				rect = rectTransform.rect;
				rectTransform2.anchoredPosition = anchoredPosition - new Vector2(0f, ((Rect)(ref rect)).height * (1f - rectTransform.pivot.y) + 6f);
			}
			else
			{
				_chaserList = NewText("OTL_ChaserList", canvas, fallbackStyle, ((TMP_Text)fallbackStyle).fontSize * 0.8f, (TextAlignmentOptions)260);
				RectTransform rectTransform3 = ((TMP_Text)_chaserList).rectTransform;
				Vector2 val3 = default(Vector2);
				((Vector2)(ref val3))..ctor(1f, 1f);
				rectTransform3.pivot = val3;
				Vector2 anchorMin = (rectTransform3.anchorMax = val3);
				rectTransform3.anchorMin = anchorMin;
				rectTransform3.sizeDelta = new Vector2(420f, 400f);
				rectTransform3.anchoredPosition = new Vector2(-40f, -90f);
			}
			((TMP_Text)_chaserList).verticalAlignment = (VerticalAlignmentOptions)256;
			((TMP_Text)_chaserList).text = "";
		}

		private void BuildToast(Transform canvas, TextMeshProUGUI style)
		{
			//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_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)
			//IL_004b: 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_0071: Unknown result type (might be due to invalid IL or missing references)
			_toast = NewText("OTL_Toast", canvas, style, ((TMP_Text)style).fontSize, (TextAlignmentOptions)514);
			RectTransform rectTransform = ((TMP_Text)_toast).rectTransform;
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(0.5f, 1f);
			rectTransform.pivot = val;
			Vector2 anchorMin = (rectTransform.anchorMax = val);
			rectTransform.anchorMin = anchorMin;
			rectTransform.sizeDelta = new Vector2(1400f, 80f);
			rectTransform.anchoredPosition = new Vector2(0f, -230f);
			_toastGroup = ((Component)_toast).gameObject.AddComponent<CanvasGroup>();
			_toastGroup.alpha = 0f;
		}

		private static RectTransform NewRect(string name, Transform parent)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) });
			val.transform.SetParent(parent, false);
			return (RectTransform)val.transform;
		}

		private static void Stretch(RectTransform rt)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: 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)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: 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)
			rt.anchorMin = Vector2.zero;
			rt.anchorMax = Vector2.one;
			Vector2 offsetMin = (rt.offsetMax = Vector2.zero);
			rt.offsetMin = offsetMin;
		}

		private static TextMeshProUGUI NewText(string name, Transform parent, TextMeshProUGUI? style, float size, TextAlignmentOptions align)
		{
			//IL_0013: 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)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			RectTransform val = NewRect(name, parent);
			val.sizeDelta = new Vector2(800f, 80f);
			TextMeshProUGUI val2 = ((Component)val).gameObject.AddComponent<TextMeshProUGUI>();
			if ((Object)(object)style != (Object)null)
			{
				ApplyFont(val2, style);
				((Graphic)val2).color = ((Graphic)style).color;
			}
			((TMP_Text)val2).fontSize = size;
			((TMP_Text)val2).alignment = align;
			((TMP_Text)val2).textWrappingMode = (TextWrappingModes)0;
			((TMP_Text)val2).richText = true;
			((Graphic)val2).raycastTarget = false;
			return val2;
		}

		private static void ApplyFont(TextMeshProUGUI target, TextMeshProUGUI style)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			((TMP_Text)target).font = ((TMP_Text)style).font;
			((TMP_Text)target).fontSharedMaterial = ((TMP_Text)style).fontSharedMaterial;
			((TMP_Text)target).fontStyle = ((TMP_Text)style).fontStyle;
		}

		private void Update()
		{
			UpdateCenter();
			ChaserKit.LocalTick();
			if (EnsureHud())
			{
				BlowgunCooldownUI blowgunCooldown = _blowgunCooldown;
				if (blowgunCooldown != null && blowgunCooldown.IsValid)
				{
					_blowgunCooldown.Update(GUIManager.instance);
				}
				blowgunCooldown = _gemCooldown;
				if (blowgunCooldown != null && blowgunCooldown.IsValid)
				{
					_gemCooldown.Update(GUIManager.instance);
				}
				blowgunCooldown = _dashCooldown;
				if (blowgunCooldown != null && blowgunCooldown.IsValid)
				{
					_dashCooldown.Update(GUIManager.instance);
				}
				if (Time.time >= _nextListRefresh)
				{
					_nextListRefresh = Time.time + 0.25f;
					UpdateChaserList();
				}
			}
		}

		private void UpdateCenter()
		{
			//IL_005f: 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_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: 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_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: 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_01ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: 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_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: 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_0131: 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_0134: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_centerMain == (Object)null || (Object)(object)_centerSub == (Object)null || (Object)(object)_blind == (Object)null)
			{
				return;
			}
			Character localCharacter = Character.localCharacter;
			bool flag = (Object)(object)localCharacter != (Object)null && RoundManager.IsActive && RoleManager.RoleOf(Net.Actor(localCharacter)) == Role.Chaser;
			string text = "";
			string text2 = "";
			Color val = Color.white;
			Color val2 = Color.white;
			float num = 1f;
			if (Time.time < _announceUntil)
			{
				text = _announce;
				text2 = _announceSub;
				val = _announceColor;
			}
			else if ((Object)(object)localCharacter != (Object)null && RoundManager.InReveal)
			{
				text = (flag ? "CHASER" : "RUNNER");
				text2 = "YOU ARE A...";
				val = (flag ? ChaserRed : RunnerYellow);
			}
			else if ((Object)(object)localCharacter != (Object)null && RoundManager.InCountdown)
			{
				text = Mathf.CeilToInt(RoundManager.HoldSecondsLeft).ToString();
				text2 = (flag ? "THE HUNT BEGINS IN" : "YOU HAVE A HEADSTART... RUN!");
				num = (flag ? 1f : Mathf.Clamp01(Plugin.ModConfig.CountdownOpacity.Value));
				if (!flag)
				{
					val = (val2 = RunnerYellow);
				}
			}
			if (text != _lastCenter)
			{
				_lastCenter = text;
				ShortcutExtensions.DOKill((Component)(object)((TMP_Text)_centerMain).rectTransform, false);
				((Transform)((TMP_Text)_centerMain).rectTransform).localScale = Vector3.one * 1.25f;
				TweenSettingsExtensions.SetEase<TweenerCore<Vector3, Vector3, VectorOptions>>(ShortcutExtensions.DOScale((Transform)(object)((TMP_Text)_centerMain).rectTransform, 1f, 0.25f), (Ease)27);
			}
			((TMP_Text)_centerMain).text = text;
			((TMP_Text)_centerSub).text = text2;
			((Graphic)_centerMain).color = new Color(val.r, val.g, val.b, num);
			((Graphic)_centerSub).color = new Color(val2.r, val2.g, val2.b, num * 0.85f);
			float num2 = 0f;
			if (flag && RoundManager.InHold)
			{
				float num3 = Mathf.Max(0.1f, RoundManager.HoldTotalSeconds);
				num2 = Mathf.Clamp01(RoundManager.HoldSecondsLeft / (num3 * 0.4f));
			}
			((Graphic)_blind).color = new Color(0f, 0f, 0f, num2);
		}

		private void UpdateChaserList()
		{
			if ((Object)(object)_chaserList == (Object)null)
			{
				return;
			}
			if (!Plugin.ModConfig.ShowChaserList.Value || !RoundManager.IsActive)
			{
				((TMP_Text)_chaserList).text = "";
				return;
			}
			StringBuilder stringBuilder = new StringBuilder("<size=75%><alpha=#B0>CHASERS</size><alpha=#FF>\n");
			int num = (((Object)(object)Character.localCharacter != (Object)null) ? Net.Actor(Character.localCharacter) : (-1));
			foreach (int item in RoleManager.Chasers.OrderBy(Net.NameOf))
			{
				Character val = Net.CharacterOf(item);
				string text = Net.NameOf(item) + ((item == num) ? " (you)" : "");
				if ((Object)(object)val != (Object)null && val.data.dead)
				{
					stringBuilder.Append("<alpha=#60><s>" + text + "</s><alpha=#FF>\n");
				}
				else if (FreezeState.IsFrozen(item))
				{
					stringBuilder.Append(string.Format("<color={0}>{1}  {2}s</color>\n", "#9FDCFF", text, FrozenSecondsShown(item)));
				}
				else
				{
					stringBuilder.Append(text).Append('\n');
				}
			}
			((TMP_Text)_chaserList).text = stringBuilder.ToString();
		}

		private int FrozenSecondsShown(int actor)
		{
			float num = Mathf.Max(0.1f, Plugin.ModConfig.FreezeDuration.Synced<float>());
			float num2 = FreezeState.FrozenSecondsLeft(actor);
			if (num2 > num + 0.5f && Time.time >= _nextFreezeWarning)
			{
				_nextFreezeWarning = Time.time + 5f;
				Plugin.Log.LogWarning((object)$"[OTL][UI] chaser list: {Net.NameOf(actor)} shows {num2:0.0}s of freeze left, more than FreezeDuration {num:0.#}s.");
			}
			return Mathf.Clamp(Mathf.CeilToInt(num2), 0, Mathf.CeilToInt(num));
		}

		private void OnLegStarted(bool newRound)
		{
			if (newRound)
			{
				if ((Object)(object)_chaserList != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)_chaserList).gameObject);
				}
				_chaserList = null;
			}
		}

		private void OnLegCompleted()
		{
			//IL_0052: 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)
			int num = Mathf.CeilToInt(Mathf.Max(1f, Plugin.ModConfig.RoleWindowSeconds.Synced<float>()));
			string sub = $"YOU HAVE {num} SECONDS TO CHOOSE YOUR ROLE FOR THE NEXT LEG";
			if (RoundManager.ChasersWonLeg)
			{
				Announce("THE CHASERS WIN THIS LEG", sub, ChaserRed, num);
			}
			else
			{
				Announce("THE RUNNERS WIN THIS LEG", sub, RunnerYellow, num);
			}
		}

		private void OnRoundEnded(RoundState result)
		{
			//IL_002a: 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)
			if (result == RoundState.RunnersWon)
			{
				Announce("THE RUNNERS ESCAPED", "EVERY RUNNER REACHED THE PEAK", RunnerYellow, 6f);
			}
			else
			{
				Announce("THE CHASERS WIN", "EVERY RUNNER WAS CAUGHT", ChaserRed, 6f);
			}
		}

		private void OnNotice(Notice notice, int a, int b)
		{
			//IL_00b2: 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_013a: Unknown result type (might be due to invalid IL or missing references)
			int num = (((Object)(object)Character.localCharacter != (Object)null) ? Net.Actor(Character.localCharacter) : (-1));
			switch (notice)
			{
			case Notice.Captured:
				Toast(Net.NameOf(b) + " was caught by " + Net.NameOf(a) + "!");
				if (Plugin.ModConfig.CaptureSound.Value)
				{
					Character val = Net.CharacterOf(b);
					if (val != null)
					{
						CaptureSfx.Play(val.Center);
					}
				}
				break;
			case Notice.Converted:
				Toast(Net.NameOf(a) + " has joined the chasers");
				if (a == num)
				{
					Announce("CHASER", "YOU HAVE JOINED THE CHASERS", ChaserRed, 4f);
				}
				break;
			case Notice.Rewarded:
				Toast(Net.NameOf(a) + " reached the safe zone first - energy drink!");
				break;
			case Notice.Restarted:
				Toast("The host restarted from the last campfire");
				AdminRestart.OnRestartNotice();
				break;
			case Notice.ZombieHunt:
			{
				bool flag = _announceSub == "IT'S COMING FOR YOU" && Time.time < _announceUntil;
				if (a == num || !flag)
				{
					Announce("A ZOMBIE IS ON THE HUNT", (a == num) ? "IT'S COMING FOR YOU" : ("IT'S AFTER " + Net.NameOf(a).ToUpperInvariant()), ZombieGreen, 5f);
				}
				LavaAlert.Play();
				break;
			}
			case Notice.MissingMod:
				Toast(Net.NameOf(a) + " doesn't have OnTheLookout " + Plugin.Version);
				break;
			}
		}

		private void Announce(string main, string sub, Color color, float seconds)
		{
			//IL_000f: 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)
			_announce = main;
			_announceSub = sub;
			_announceColor = color;
			_announceUntil = Time.time + seconds;
		}

		private void Toast(string text)
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			if (EnsureHud() && !((Object)(object)_toast == (Object)null) && !((Object)(object)_toastGroup == (Object)null))
			{
				((TMP_Text)_toast).text = text;
				ShortcutExtensions.DOKill((Component)(object)_toastGroup, false);
				ShortcutExtensions.DOKill((Component)(object)((TMP_Text)_toast).rectTransform, false);
				((Transform)((TMP_Text)_toast).rectTransform).localScale = Vector3.one * 0.85f;
				TweenSettingsExtensions.SetEase<TweenerCore<Vector3, Vector3, VectorOptions>>(ShortcutExtensions.DOScale((Transform)(object)((TMP_Text)_toast).rectTransform, 1f, 0.3f), (Ease)27);
				TweenSettingsExtensions.SetTarget<Sequence>(TweenSettingsExtensions.Append(TweenSettingsExtensions.AppendInterval(TweenSettingsExtensions.Append(DOTween.Sequence(), (Tween)(object)DOTweenModuleUI.DOFade(_toastGroup, 1f, 0.2f)), 3.5f), (Tween)(object)DOTweenModuleUI.DOFade(_toastGroup, 0f, 0.6f)), (object)_toastGroup);
			}
		}
	}
	internal static class LavaAlert
	{
		private static List<SFX_Instance>? s_Sfx;

		private static List<AudioClip>? s_Clips;

		private static float s_LastPlayed = -10f;

		public static void Play()
		{
			//IL_0047: 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_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: 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)
			if (Time.time - s_LastPlayed < 2f)
			{
				return;
			}
			s_LastPlayed = Time.time;
			if (s_Sfx == null)
			{
				Load();
			}
			Vector3 val = (((Object)(object)MainCamera.instance != (Object)null) ? ((Component)MainCamera.instance).transform.position : Vector3.zero);
			List<SFX_Instance> list = s_Sfx;
			if (list != null && list.Count > 0 && (Object)(object)SFX_Player.instance != (Object)null)
			{
				foreach (SFX_Instance item in s_Sfx)
				{
					item.Play(val);
				}
			}
			else
			{
				List<AudioClip> list2 = s_Clips;
				if (list2 != null && list2.Count > 0)
				{
					foreach (AudioClip s_Clip in s_Clips)
					{
						AudioSource.PlayClipAtPoint(s_Clip, val, 1f);
					}
				}
			}
			if ((Object)(object)GamefeelHandler.instance != (Object)null)
			{
				GamefeelHandler.instance.AddPerlinShake(5f, 1.2f, 20f);
			}
		}

		private static void Load()
		{
			s_Sfx = new List<SFX_Instance>();
			s_Clips = new List<AudioClip>();
			GameObject val = (((Object)(object)GUIManager.instance != (Object)null) ? GUIManager.instance.lavaRises : null);
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogWarning((object)"[OTL][UI] lava-rises popup not found; zombie alert has no sound.");
				return;
			}
			s_Clips.AddRange(from a in val.GetComponentsInChildren<AudioSource>(true)
				select a.clip into c
				where (Object)(object)c != (Object)null
				select c);
			MonoBehaviour[] componentsInChildren = val.GetComponentsInChildren<MonoBehaviour>(true);
			foreach (MonoBehaviour val2 in componentsInChildren)
			{
				if ((Object)(object)val2 == (Object)null)
				{
					continue;
				}
				FieldInfo[] fields = ((object)val2).GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (FieldInfo fieldInfo in fields)
				{
					object value;
					try
					{
						value = fieldInfo.GetValue(val2);
					}
					catch
					{
						continue;
					}
					SFX_Instance val3 = (SFX_Instance)((value is SFX_Instance) ? value : null);
					if (val3 != null && (Object)(object)val3 != (Object)null)
					{
						s_Sfx.Add(val3);
					}
					else
					{
						if (!(value is IEnumerable enumerable) || enumerable is string)
						{
							continue;
						}
						foreach (object item in enumerable)
						{
							SFX_Instance val4 = (SFX_Instance)((item is SFX_Instance) ? item : null);
							if (val4 != null && (Object)(object)val4 != (Object)null)
							{
								s_Sfx.Add(val4);
							}
						}
					}
				}
			}
			s_Sfx = s_Sfx.Distinct().ToList();
			Plugin.Log.LogInfo((object)$"[OTL][UI] zombie alert sound: {s_Sfx.Count} SFX asset(s), {s_Clips.Count} clip(s) from {((Object)val).name}.");
		}
	}
	internal static class NameTags
	{
		public static bool Install(Harmony harmony)
		{
			return SafePatch.Prefix(harmony, typeof(UIPlayerNames), "UpdateName", typeof(NameTags), "UpdateNamePrefix", "NameTags");
		}

		public static void UpdateNamePrefix(UIPlayerNames __instance, int index, ref bool visible)
		{
			if (!visible || Plugin.ModConfig.ChasersSeeRunnerNames.Synced<bool>() || !RoundManager.IsActive)
			{
				return;
			}
			Character localCharacter = Character.localCharacter;
			if (!((Object)(object)localCharacter == (Object)null) && RoleManager.IsChaser(localCharacter) && __instance.playerNameText != null && index >= 0 && index < __instance.playerNameText.Length)
			{
				Character val = __instance.playerNameText[index]?.characterInteractable?.character;
				if ((Object)(object)val != (Object)null && RoleManager.IsRunner(val))
				{
					visible = false;
				}
			}
		}
	}
	internal static class PeakMenuKit
	{
		public static Button? ButtonTemplate(GUIManager gui)
		{
			if (!((Object)(object)gui.pauseMenuMainPage != (Object)null))
			{
				return null;
			}
			return gui.pauseMenuMainPage.resumeButton;
		}

		public static RectTransform NewRect(string name, Transform parent)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) });
			val.transform.SetParent(parent, false);
			return (RectTransform)val.transform;
		}

		public static Canvas CreateCanvas(string name, Transform parent, GUIManager gui, int sortingOffset)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			//IL_00c1: 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_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) });
			val.transform.SetParent(parent, false);
			Canvas val2 = val.AddComponent<Canvas>();
			val2.renderMode = (RenderMode)0;
			val2.sortingOrder = (((Object)(object)gui.hudCanvas != (Object)null) ? gui.hudCanvas.sortingOrder : 0) + sortingOffset;
			CanvasScaler val3 = val.AddComponent<CanvasScaler>();
			if ((Object)(object)gui.hudCanvas != (Object)null)
			{
				CanvasScaler component = ((Component)gui.hudCanvas).GetComponent<CanvasScaler>();
				if (component != null)
				{
					val3.uiScaleMode = component.uiScaleMode;
					val3.referenceResolution = component.referenceResolution;
					val3.matchWidthOrHeight = component.matchWidthOrHeight;
					val3.screenMatchMode = component.screenMatchMode;
					goto IL_00d6;
				}
			}
			val3.uiScaleMode = (ScaleMode)1;
			val3.referenceResolution = new Vector2(1920f, 1080f);
			val3.matchWidthOrHeight = 0.5f;
			goto IL_00d6;
			IL_00d6:
			val.AddComponent<GraphicRaycaster>();
			return val2;
		}

		public static RectTransform CreatePanel(Canvas canvas, Button template, Vector2 size)
		{
			//IL_0012: 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_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: 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_0036: 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_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: 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_00fb: Expected O, but got Unknown
			RectTransform val = NewRect("Dim", ((Component)canvas).transform);
			val.anchorMin = Vector2.zero;
			val.anchorMax = Vector2.one;
			Vector2 offsetMin = (val.offsetMax = Vector2.zero);
			val.offsetMin = offsetMin;
			((Graphic)((Component)val).gameObject.AddComponent<Image>()).color = new Color(0f, 0f, 0f, 0.45f);
			RectTransform val2 = NewRect("Panel", ((Component)canvas).transform);
			val2.sizeDelta = size;
			Image val3 = ((Component)val2).gameObject.AddComponent<Image>();
			Image component = ((Component)template).GetComponent<Image>();
			if (component != null && component.sprite != null)
			{
				val3.sprite = component.sprite;
				val3.type = (Type)1;
				val3.pixelsPerUnitMultiplier = component.pixelsPerUnitMultiplier;
			}
			((Graphic)val3).color = new Color(0.13f, 0.11f, 0.09f, 0.96f);
			VerticalLayoutGroup val4 = ((Component)val2).gameObject.AddComponent<VerticalLayoutGroup>();
			((LayoutGroup)val4).padding = new RectOffset(40, 40, 30, 30);
			((HorizontalOrVerticalLayoutGroup)val4).spacing = 14f;
			((LayoutGroup)val4).childAlignment = (TextAnchor)1;
			((HorizontalOrVerticalLayoutGroup)val4).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)val4).childControlHeight = false;
			((HorizontalOrVerticalLayoutGroup)val4).childForceExpandWidth = true;
			((HorizontalOrVerticalLayoutGroup)val4).childForceExpandHeight = false;
			return val2;
		}

		public static TextMeshProUGUI AddText(Transform parent, string text, TextMeshProUGUI style, float size, Color color, float height)
		{
			//IL_0014: 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)
			RectTransform val = NewRect("Text", parent);
			val.sizeDelta = new Vector2(0f, height);
			TextMeshProUGUI val2 = ((Component)val).gameObject.AddComponent<TextMeshProUGUI>();
			((TMP_Text)val2).font = ((TMP_Text)style).font;
			((TMP_Text)val2).fontSharedMaterial = ((TMP_Text)style).fontSharedMaterial;
			((TMP_Text)val2).fontSize = size;
			((Graphic)val2).color = color;
			((TMP_Text)val2).alignment = (TextAlignmentOptions)514;
			((TMP_Text)val2).textWrappingMode = (TextWrappingModes)0;
			((Graphic)val2).raycastTarget = false;
			((TMP_Text)val2).text = text;
			return val2;
		}

		public static (Button Button, TextMeshProUGUI Label) CloneButton(Transform parent, Button template, string label)
		{
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Expected O, but got Unknown
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Expected O, but got Unknown
			//IL_00cf: 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)
			GameObject val = Object.Instantiate<GameObject>(((Component)template).gameObject, parent);
			((Object)val).name = "OTL_Button";
			val.SetActive(true);
			MonoBehaviour[] componentsInChildren = val.GetComponentsInChildren<MonoBehaviour>(true);
			foreach (MonoBehaviour val2 in componentsInChildren)
			{
				string text = ((object)val2).GetType().Namespace ?? "";
				if (!text.StartsWith("UnityEngine", StringComparison.Ordinal) && !text.StartsWith("TMPro", StringComparison.Ordinal))
				{
					Object.DestroyImmediate((Object)(object)val2);
				}
			}
			Button component = val.GetComponent<Button>();
			component.onClick = new ButtonClickedEvent();
			Navigation navigation = default(Navigation);
			((Navigation)(ref navigation)).mode = (Mode)0;
			((Selectable)component).navigation = navigation;
			TextMeshProUGUI componentInChildren = val.GetComponentInChildren<TextMeshProUGUI>(true);
			((TMP_Text)componentInChildren).text = label;
			RectTransform val3 = (RectTransform)val.transform;
			val3.sizeDelta = new Vector2(0f, Mathf.Max(64f, val3.sizeDelta.y));
			return (Button: component, Label: componentInChildren);
		}
	}
	internal sealed class SafeZoneWall : MonoBehaviour
	{
		private sealed class Wall
		{
			public GameObject Go;

			public Vector3 Centre;

			public float Radius;

			public bool Complete;

			public float RetryAt;
		}

		private const int Segments = 96;

		private const float WallHeight = 3.5f;

		private const float RimHeight = 0.12f;

		private const float RetrySeconds = 5f;

		private static readonly Color Yellow = new Color(1f, 0.84f, 0.2f);

		private readonly Dictionary<Campfire, Wall> _walls = new Dictionary<Campfire, Wall>();

		private readonly Dictionary<Campfire, int> _attempts = new Dictionary<Campfire, int>();

		private const int MaxAttempts = 3;

		private readonly List<Campfire> _gone = new List<Campfire>();

		private Material? _material;

		private bool _failed;

		private float _nextScan;

		private void Update()
		{
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			if (!RoundManager.IsActive || !Plugin.ModConfig.EnableSafeZones.Value || _failed)
			{
				HideAll();
				return;
			}
			if (Time.time >= _nextScan)
			{
				_nextScan = Time.time + 1f;
				Refresh();
			}
			if ((Object)(object)_material != (Object)null)
			{
				float num = 0.85f + 0.15f * Mathf.Sin(Time.time * 2.2f);
				_material.color = new Color(num, num, num, 1f);
			}
		}

		private void Refresh()
		{
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Max(1f, Plugin.ModConfig.CampfireSafeRadius.Synced<float>());
			bool requireLit = Plugin.ModConfig.SafeZoneRequiresLit.Synced<bool>();
			HashSet<Campfire> hashSet = new HashSet<Campfire>(SafeZoneSystem.Campfires.Where((Campfire f) => (Object)(object)f != (Object)null && ((Behaviour)f).isActiveAndEnabled && (!requireLit || (int)f.state == 1)));
			_gone.Clear();
			foreach (KeyValuePair<Campfire, Wall> wall in _walls)
			{
				Wall value = wall.Value;
				if (!((Object)(object)wall.Key == (Object)null) && hashSet.Contains(wall.Key) && !((Object)(object)value.Go == (Object)null) && Mathf.Approximately(value.Radius, num))
				{
					Vector3 val = ((Component)wall.Key).transform.position - value.Centre;
					if (!(((Vector3)(ref val)).sqrMagnitude > 0.01f) && (value.Complete || !(Time.time >= value.RetryAt)))
					{
						continue;
					}
				}
				_gone.Add(wall.Key);
			}
			foreach (Campfire item in _gone)
			{
				Remove(item);
			}
			foreach (Campfire item2 in hashSet)
			{
				if (!_walls.ContainsKey(item2))
				{
					Build(item2, num);
				}
			}
		}

		private void Build(Campfire fire, float radius)
		{
			//IL_002f: 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_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Expected O, but got Unknown
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: 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)
			if (_material == null)
			{
				_material = CreateMaterial();
			}
			if ((Object)(object)_material == (Object)null)
			{
				_failed = true;
				return;
			}
			Vector3 position = ((Component)fire).transform.position;
			GameObject val = new GameObject("OTL_SafeZoneWall");
			val.transform.position = position;
			val.AddComponent<MeshFilter>().sharedMesh = BuildMesh(position, radius, out var misses);
			MeshRenderer val2 = val.AddComponent<MeshRenderer>();
			((Renderer)val2).sharedMaterial = _material;
			((Renderer)val2).shadowCastingMode = (ShadowCastingMode)0;
			((Renderer)val2).receiveShadows = false;
			int value;
			int num = ((!_attempts.TryGetValue(fire, out value)) ? 1 : (value + 1));
			_attempts[fire] = num;
			bool flag = misses == 0 || num >= 3;
			_walls[fire] = new Wall
			{
				Go = val,
				Centre = position,
				Radius = radius,
				Complete = flag,
				RetryAt = Time.time + 5f
			};
			if (num == 1 || flag)
			{
				Plugin.Log.LogInfo((object)string.Format("[OTL][SafeZone] wall around the campfire at {0} ({1:0.#} m){2}.", position, radius, (misses > 0) ? $", {misses} direction(s) without ground yet" : ""));
			}
		}

		private void Remove(Campfire fire)
		{
			if (_walls.TryGetValue(fire, out Wall value) && (Object)(object)value.Go != (Object)null)
			{
				Object.Destroy((Object)(object)value.Go.GetComponent<