Decompiled source of Lakis MiniGames v1.0.0

LakisPlayRoom.dll

Decompiled 19 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Logging;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.UI;
using WKMapLoader;

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace LakisPlayRoom
{
	internal static class GameProps
	{
		private static readonly string[] SourceLevels = new string[2] { "Training_Level_01", "M3_Habitation_Pier_03" };

		private static readonly List<GameObject> sources = new List<GameObject>();

		private static readonly List<AsyncOperationHandle<GameObject>> handles = new List<AsyncOperationHandle<GameObject>>();

		private static bool sourcesTried;

		private static readonly Dictionary<string, MeshFilter> cache = new Dictionary<string, MeshFilter>();

		public static bool TryGet(string meshName, out Mesh mesh, out Material[] mats, out CL_Button button)
		{
			mesh = null;
			mats = null;
			button = null;
			if (!cache.TryGetValue(meshName, out var value) || (Object)(object)value == (Object)null)
			{
				LoadSources();
				value = sources.SelectMany((GameObject s) => s.GetComponentsInChildren<MeshFilter>(true)).FirstOrDefault((Func<MeshFilter, bool>)((MeshFilter m) => (Object)(object)m.sharedMesh != (Object)null && ((Object)m.sharedMesh).name == meshName)) ?? ((IEnumerable<MeshFilter>)Resources.FindObjectsOfTypeAll<MeshFilter>()).FirstOrDefault((Func<MeshFilter, bool>)((MeshFilter m) => (Object)(object)m.sharedMesh != (Object)null && ((Object)m.sharedMesh).name == meshName));
				if ((Object)(object)value == (Object)null)
				{
					return false;
				}
				cache[meshName] = value;
			}
			mesh = value.sharedMesh;
			MeshRenderer component = ((Component)value).GetComponent<MeshRenderer>();
			mats = (Material[])(((object)((component != null) ? ((Renderer)component).sharedMaterials : null)) ?? ((object)new Material[0]));
			button = ((Component)value).GetComponent<CL_Button>();
			return true;
		}

		public static MeshFilter FindTree(string meshName)
		{
			LoadSources();
			return (from m in sources.SelectMany((GameObject s) => s.GetComponentsInChildren<MeshFilter>(true))
				where (Object)(object)m.sharedMesh != (Object)null && ((Object)m.sharedMesh).name == meshName
				orderby ((Component)m).GetComponentsInChildren<CL_Button>(true).Length != 0 descending
				select m).FirstOrDefault();
		}

		private static void LoadSources()
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Invalid comparison between Unknown and I4
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			if (sourcesTried)
			{
				return;
			}
			sourcesTried = true;
			string[] sourceLevels = SourceLevels;
			foreach (string text in sourceLevels)
			{
				try
				{
					LevelAssetHolder levelAsset = CL_AssetManager.GetLevelAsset(text, "");
					if (levelAsset?.levelAssetReference == null)
					{
						PlayRoomPlugin.Log.LogWarning((object)("Prop source level '" + text + "' not in the game's database."));
						continue;
					}
					AsyncOperationHandle<GameObject> item = Addressables.LoadAssetAsync<GameObject>(((AssetReference)levelAsset.levelAssetReference).RuntimeKey);
					GameObject val = item.WaitForCompletion();
					if ((int)item.Status == 1 && (Object)(object)val != (Object)null)
					{
						handles.Add(item);
						sources.Add(val);
					}
					else
					{
						PlayRoomPlugin.Log.LogWarning((object)("Prop source level '" + text + "' failed to load: " + item.OperationException?.Message));
					}
				}
				catch (Exception ex)
				{
					PlayRoomPlugin.Log.LogWarning((object)("Prop source level '" + text + "': " + ex.Message));
				}
			}
		}
	}
	internal static class Kits
	{
		public static void Register()
		{
			MapApi.RegisterTag("stand", (Action<MapPartInfo>)delegate(MapPartInfo part)
			{
				Build(part, "stand");
			});
			MapApi.RegisterTag("arrow", (Action<MapPartInfo>)delegate(MapPartInfo part)
			{
				Build(part, "arrow");
			});
			MapApi.RegisterTag("monitor", (Action<MapPartInfo>)delegate(MapPartInfo part)
			{
				Build(part, "monitor");
			});
		}

		private static void Build(MapPartInfo part, string word)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: 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)
			GameObject gameObject = part.GameObject;
			if ((Object)(object)gameObject.GetComponent<MeshFilter>() != (Object)null)
			{
				return;
			}
			int layer = gameObject.layer;
			if ((Object)(object)gameObject.GetComponent<CL_Button>() == (Object)null)
			{
				gameObject.layer = part.SolidLayer;
			}
			gameObject.transform.localScale = part.Scale;
			Quaternion localRotation = gameObject.transform.localRotation;
			bool flag;
			if (!(word == "stand"))
			{
				if (word == "arrow")
				{
					string[] array = part.Args("arrow");
					string text = ((array.Length != 0) ? array[0].ToLowerInvariant() : "left");
					float num = ((text == "up") ? 90f : ((text == "down") ? (-90f) : 0f));
					flag = Mesh((text == "right") ? "Prop_Button_Arrow_Right" : "Prop_Button_Arrow_Left", gameObject, localRotation * Quaternion.Euler(0f, 0f, num));
				}
				else
				{
					flag = Mesh("L_Blackboard", gameObject, localRotation);
					if (flag)
					{
						MapScreen mapScreen = gameObject.AddComponent<MapScreen>();
						string[] array2 = part.Args("monitor");
						mapScreen.id = ((array2.Length != 0) ? array2[0] : "");
						mapScreen.color = new Color(0.55f, 1f, 0.55f);
					}
				}
			}
			else
			{
				flag = Tree("L_ButtonStand_01", gameObject, localRotation * Quaternion.Euler(0f, 90f, 0f), part.SolidLayer, layer);
			}
			if (!flag)
			{
				PlayRoomPlugin.Log.LogWarning((object)("'" + word + "' on '" + part.Name + "': game mesh not found."));
			}
		}

		private static bool Mesh(string meshName, GameObject go, Quaternion rot)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			if (!GameProps.TryGet(meshName, out var mesh, out var mats, out var button))
			{
				return false;
			}
			go.AddComponent<MeshFilter>().sharedMesh = mesh;
			((Renderer)go.AddComponent<MeshRenderer>()).sharedMaterials = mats;
			go.transform.localRotation = rot;
			go.AddComponent<BoxCollider>();
			CL_Button component = go.GetComponent<CL_Button>();
			if (component != null)
			{
				CopyLook(component, button);
			}
			return true;
		}

		private static bool Tree(string meshName, GameObject go, Quaternion rot, int solidLayer, int pressLayer)
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: 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_0076: Unknown result type (might be due to invalid IL or missing references)
			MeshFilter val = GameProps.FindTree(meshName);
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			go.AddComponent<MeshFilter>().sharedMesh = val.sharedMesh;
			MeshRenderer obj = go.AddComponent<MeshRenderer>();
			MeshRenderer component = ((Component)val).GetComponent<MeshRenderer>();
			((Renderer)obj).sharedMaterials = (Material[])(((object)((component != null) ? ((Renderer)component).sharedMaterials : null)) ?? ((object)new Material[0]));
			go.transform.localRotation = rot * (Quaternion.Inverse(((Component)val).transform.root.rotation) * ((Component)val).transform.rotation);
			go.AddComponent<BoxCollider>();
			go.layer = solidLayer;
			CopyChildren(((Component)val).transform, go.transform, solidLayer, pressLayer);
			return true;
		}

		private static void CopyChildren(Transform src, Transform dst, int solidLayer, int pressLayer)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Expected O, but got Unknown
			//IL_0063: 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_0085: Unknown result type (might be due to invalid IL or missing references)
			foreach (Transform item in src)
			{
				Transform val = item;
				MeshFilter component = ((Component)val).GetComponent<MeshFilter>();
				if (!((Object)(object)component == (Object)null) && !((Object)(object)component.sharedMesh == (Object)null))
				{
					GameObject val2 = new GameObject(((Object)val).name);
					val2.layer = solidLayer;
					val2.transform.SetParent(dst, false);
					val2.transform.localPosition = val.localPosition;
					val2.transform.localRotation = val.localRotation;
					val2.transform.localScale = val.localScale;
					val2.AddComponent<MeshFilter>().sharedMesh = component.sharedMesh;
					MeshRenderer obj = val2.AddComponent<MeshRenderer>();
					MeshRenderer component2 = ((Component)val).GetComponent<MeshRenderer>();
					((Renderer)obj).sharedMaterials = (Material[])(((object)((component2 != null) ? ((Renderer)component2).sharedMaterials : null)) ?? ((object)new Material[0]));
					val2.AddComponent<BoxCollider>();
					CL_Button component3 = ((Component)val).GetComponent<CL_Button>();
					if ((Object)(object)component3 != (Object)null)
					{
						val2.layer = pressLayer;
						val2.AddComponent<ObjectTagger>().AddTag("Button");
						CL_Button obj2 = val2.AddComponent<CL_Button>();
						obj2.pressCooldown = 0.25f;
						CopyLook(obj2, component3);
					}
					CopyChildren(val, val2.transform, solidLayer, pressLayer);
				}
			}
		}

		private static void CopyLook(CL_Button btn, CL_Button source)
		{
			if (!((Object)(object)source == (Object)null))
			{
				btn.pressSound = source.pressSound;
				btn.activeMaterial = source.activeMaterial;
				btn.inactiveMaterial = source.inactiveMaterial;
				btn.materialIndex = source.materialIndex;
				btn.inactiveMaterialOnCooldown = source.inactiveMaterialOnCooldown;
			}
		}
	}
	public class MapScreen : MonoBehaviour
	{
		public string id = "";

		public Color color = Color.white;

		internal static readonly List<MapScreen> All = new List<MapScreen>();

		private static readonly Dictionary<string, string> texts = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);

		private static float nextTick;

		private TextMeshPro tmp;

		private const float PanelW = 0.88f;

		private const float PanelH = 0.8f;

		private void OnEnable()
		{
			All.Add(this);
		}

		private void OnDisable()
		{
			All.Remove(this);
		}

		public static void Set(string id, string text)
		{
			texts[id ?? ""] = text ?? "";
			foreach (MapScreen item in All)
			{
				if (string.Equals(item.id, id, StringComparison.OrdinalIgnoreCase))
				{
					item.Refresh();
				}
			}
		}

		public static bool Any(string id)
		{
			return All.Any((MapScreen s) => string.Equals(s.id, id, StringComparison.OrdinalIgnoreCase));
		}

		public static void Reset()
		{
			texts.Clear();
			foreach (MapScreen item in All)
			{
				item.Refresh();
			}
		}

		public static void Tick()
		{
			if (Time.time < nextTick)
			{
				return;
			}
			nextTick = Time.time + 0.2f;
			foreach (MapScreen item in All)
			{
				item.Refresh();
			}
		}

		private IEnumerator Start()
		{
			yield return (object)new WaitForSeconds(0.5f);
			TMP_FontAsset val = HudFont();
			if ((Object)(object)val == (Object)null)
			{
				PlayRoomPlugin.Log.LogWarning((object)"Screen: no font found");
				yield break;
			}
			MeshFilter component = ((Component)this).GetComponent<MeshFilter>();
			Bounds? obj;
			if (component == null)
			{
				obj = null;
			}
			else
			{
				Mesh sharedMesh = component.sharedMesh;
				obj = ((sharedMesh != null) ? new Bounds?(sharedMesh.bounds) : ((Bounds?)null));
			}
			Bounds mb = (Bounds)(((??)obj) ?? new Bounds(Vector3.zero, new Vector3(4f, 2f, 0.5f)));
			MakeBlackPanel(mb);
			GameObject val2 = new GameObject("screen_text");
			val2.transform.SetParent(((Component)this).transform, false);
			val2.transform.localPosition = new Vector3(((Bounds)(ref mb)).center.x, ((Bounds)(ref mb)).center.y, ((Bounds)(ref mb)).max.z + 0.04f);
			val2.transform.localRotation = Quaternion.Euler(0f, 180f, 0f);
			tmp = val2.AddComponent<TextMeshPro>();
			((TMP_Text)tmp).font = val;
			((TMP_Text)tmp).rectTransform.sizeDelta = new Vector2(((Bounds)(ref mb)).size.x * 0.88f * 0.97f, ((Bounds)(ref mb)).size.y * 0.8f * 0.97f);
			((TMP_Text)tmp).enableAutoSizing = true;
			((TMP_Text)tmp).fontSizeMin = 1f;
			((TMP_Text)tmp).fontSizeMax = 12f;
			((TMP_Text)tmp).alignment = (TextAlignmentOptions)514;
			((Graphic)tmp).color = color;
			((TMP_Text)tmp).richText = true;
			Refresh();
		}

		private void Refresh()
		{
			if (!((Object)(object)tmp == (Object)null))
			{
				string value;
				string text = MapApi.Expand(texts.TryGetValue(id ?? "", out value) ? value : "");
				if (((TMP_Text)tmp).text != text)
				{
					((TMP_Text)tmp).text = text;
				}
			}
		}

		private void MakeBlackPanel(Bounds mb)
		{
			//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_00dd: 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_010a: 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_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Expected O, but got Unknown
			//IL_012b: 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_013f: 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_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: 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_018b: 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_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0215: Unknown result type (might be due to invalid IL or missing references)
			//IL_021a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_0226: Unknown result type (might be due to invalid IL or missing references)
			//IL_022d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0232: Unknown result type (might be due to invalid IL or missing references)
			//IL_0239: Unknown result type (might be due to invalid IL or missing references)
			//IL_023e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0245: Unknown result type (might be due to invalid IL or missing references)
			//IL_024a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0279: Unknown result type (might be due to invalid IL or missing references)
			//IL_027e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0290: Unknown result type (might be due to invalid IL or missing references)
			List<Material> source = (from r in ((Component)((Component)this).transform.root).GetComponentsInChildren<Renderer>()
				select r.sharedMaterial into m
				where (Object)(object)m != (Object)null
				select m).ToList();
			Material val = MatTools.Tint(((IEnumerable<Material>)source).FirstOrDefault((Func<Material, bool>)((Material m) => ((Object)m).name.StartsWith("WKMap_Tint_"))) ?? ((IEnumerable<Material>)source).FirstOrDefault((Func<Material, bool>)((Material m) => ((Object)m).name.StartsWith("WKMap_"))), Color.black, false);
			if (!((Object)(object)val == (Object)null))
			{
				float num = ((Bounds)(ref mb)).size.x * 0.88f / 2f;
				float num2 = ((Bounds)(ref mb)).size.y * 0.8f / 2f;
				float num3 = ((Bounds)(ref mb)).max.z + 0.02f;
				Vector3 center = ((Bounds)(ref mb)).center;
				Mesh val2 = new Mesh
				{
					name = "screen_panel"
				};
				Vector3[] array = (Vector3[])(object)new Vector3[4]
				{
					new Vector3(center.x - num, center.y - num2, num3),
					new Vector3(center.x + num, center.y - num2, num3),
					new Vector3(center.x + num, center.y + num2, num3),
					new Vector3(center.x - num, center.y + num2, num3)
				};
				val2.vertices = array.Concat(array).ToArray();
				val2.normals = Enumerable.Repeat<Vector3>(Vector3.forward, 4).Concat(Enumerable.Repeat<Vector3>(Vector3.back, 4)).ToArray();
				val2.uv = (Vector2[])(object)new Vector2[8]
				{
					Vector2.zero,
					Vector2.right,
					Vector2.one,
					Vector2.up,
					Vector2.zero,
					Vector2.right,
					Vector2.one,
					Vector2.up
				};
				val2.triangles = new int[12]
				{
					0, 2, 1, 0, 3, 2, 4, 5, 6, 4,
					6, 7
				};
				val2.RecalculateBounds();
				GameObject val3 = new GameObject("screen_panel");
				val3.transform.SetParent(((Component)this).transform, false);
				val3.AddComponent<MeshFilter>().sharedMesh = val2;
				((Renderer)val3.AddComponent<MeshRenderer>()).sharedMaterial = val;
			}
		}

		private static TMP_FontAsset HudFont()
		{
			TMP_Text[] array = Object.FindObjectsByType<TMP_Text>((FindObjectsSortMode)0);
			foreach (TMP_Text val in array)
			{
				if ((Object)(object)val != (Object)null && (Object)(object)val.font != (Object)null && ((Behaviour)val).isActiveAndEnabled)
				{
					return val.font;
				}
			}
			return null;
		}
	}
	public class MapGlowHold : MonoBehaviour
	{
		public int lane = 1;

		public int variant = -1;

		internal bool lit;

		internal Vector3 home;

		internal int owner;

		internal float litAt;

		internal float litUntil;

		private CL_Handhold hold;

		private Renderer rend;

		private Material gray;

		private GameObject lamp;

		internal static readonly List<MapGlowHold> All = new List<MapGlowHold>();

		internal bool Held
		{
			get
			{
				if ((Object)(object)hold != (Object)null)
				{
					return hold.GetHolding();
				}
				return false;
			}
		}

		internal bool HasLamp => (Object)(object)lamp != (Object)null;

		private void OnEnable()
		{
			All.Add(this);
		}

		private void OnDisable()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			All.Remove(this);
			SetLit(on: false);
		}

		private void Awake()
		{
			//IL_0007: 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)
			home = ((Component)this).transform.localPosition;
		}

		private void Start()
		{
			hold = ((Component)this).GetComponent<CL_Handhold>();
			rend = ((Component)this).GetComponent<Renderer>();
		}

		private void Update()
		{
			if (!lit && (Object)(object)rend != (Object)null)
			{
				gray = rend.sharedMaterial;
			}
			if (lit && Held)
			{
				GlowGame.OnGrab(this);
			}
		}

		internal void SetLit(bool on, Color color = default(Color))
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: 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_00d1: 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_00e5: 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_00f4: 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)
			if ((Object)(object)rend == (Object)null)
			{
				rend = ((Component)this).GetComponent<Renderer>();
			}
			if ((Object)(object)rend == (Object)null || lit == on)
			{
				lit = on;
				return;
			}
			if ((Object)(object)gray == (Object)null)
			{
				gray = rend.sharedMaterial;
			}
			lit = on;
			if (color == default(Color))
			{
				color = GlowGame.PlayerColors[0];
			}
			rend.sharedMaterial = (on ? MatTools.Tint(gray, color, true) : gray);
			if (on && (Object)(object)lamp == (Object)null && GlowGame.LampCount < 6)
			{
				lamp = MatTools.Lamp(((Component)this).transform, ((Component)this).transform.position + ((Component)this).transform.forward * 0.4f + Vector3.up * 0.01f, color, 2.5f);
			}
			if (!on && (Object)(object)lamp != (Object)null)
			{
				Object.Destroy((Object)(object)lamp);
				lamp = null;
			}
		}
	}
	public class MapLane : MonoBehaviour
	{
		public int lane = 1;

		public int variant = -1;

		public bool spin;

		public bool axis;

		private Vector3 basePos;

		private Quaternion baseRot;

		private float dx;

		private bool started;

		internal static readonly List<MapLane> All = new List<MapLane>();

		private static readonly Dictionary<int, Vector3> axes = new Dictionary<int, Vector3>();

		private const float SpinPeriod = 15f;

		private void Start()
		{
			//IL_0007: 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_0036: Unknown result type (might be due to invalid IL or missing references)
			basePos = ((Component)this).transform.localPosition;
			baseRot = ((Component)this).transform.localRotation;
			if (axis)
			{
				axes[lane] = basePos;
			}
			if (spin)
			{
				CarryPlayer();
			}
			started = true;
			All.Add(this);
			GlowGame.PlaceLane(this);
		}

		private void OnDestroy()
		{
			All.Remove(this);
		}

		private void CarryPlayer()
		{
			//IL_0013: Expected O, but got Unknown
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				((Component)this).gameObject.tag = "Platform";
			}
			catch (UnityException ex)
			{
				UnityException ex2 = ex;
				PlayRoomPlugin.Log.LogWarning((object)("Drum can't carry the player: " + ((Exception)(object)ex2).Message));
				return;
			}
			ENT_Player playerObject = ENT_Player.playerObject;
			if ((Object)(object)playerObject != (Object)null)
			{
				playerObject.parentMask = LayerMask.op_Implicit(LayerMask.op_Implicit(playerObject.parentMask) | (1 << ((Component)this).gameObject.layer));
			}
		}

		internal void Place(float dx, bool show)
		{
			if (started)
			{
				this.dx = dx;
				show &= GlowGame.OnMap(variant);
				Pose();
				if (((Component)this).gameObject.activeSelf != show)
				{
					((Component)this).gameObject.SetActive(show);
				}
			}
		}

		private void Update()
		{
			if (spin)
			{
				Pose();
			}
		}

		private void Pose()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: 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_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = basePos;
			Quaternion localRotation = baseRot;
			if (spin && axes.TryGetValue(lane, out var value))
			{
				Quaternion val2 = Quaternion.AngleAxis(Time.time * 360f / 15f, Vector3.right);
				val = value + val2 * (basePos - value);
				localRotation = val2 * baseRot;
			}
			((Component)this).transform.localPosition = val + Vector3.right * dx;
			((Component)this).transform.localRotation = localRotation;
		}
	}
	public class MapBarrier : MonoBehaviour
	{
		public int lane = 1;

		public bool front;

		internal static readonly List<MapBarrier> All = new List<MapBarrier>();

		private void Start()
		{
			All.Add(this);
			Set(!GlowGame.IsOpen(lane));
		}

		private void OnDestroy()
		{
			All.Remove(this);
		}

		internal void Set(bool on)
		{
			Collider[] components = ((Component)this).GetComponents<Collider>();
			for (int i = 0; i < components.Length; i++)
			{
				components[i].enabled = on;
			}
		}
	}
	internal static class GlowGame
	{
		private enum State
		{
			Idle,
			Countdown,
			Running,
			Result
		}

		private class Lane
		{
			public int id;

			public State state;

			public float countEnd;

			public float endTime;

			public float nextLight;

			public int lastCount;

			public bool warned10;

			public Random rng = new Random();
		}

		private class Score
		{
			public int pressed;

			public int missed;

			public bool newBest;

			public readonly List<float> reactions = new List<float>();
		}

		private class Item
		{
			public string label;

			public string value;

			public Action<int> change;

			public Color? color;
		}

		private static readonly string[] MapNames = new string[2] { "Flat Wall", "Cylinder" };

		public static bool Multiplayer;

		public static bool Coop;

		public static bool SharedTrail;

		public static int Players = 2;

		public static float Lifespan = 3f;

		public static float Interval = 1f;

		public static float Duration = 60f;

		private const float LifeStep = 0.5f;

		private const float LifeMin = 0.5f;

		private const float LifeMax = 10f;

		private const float IntStep = 0.25f;

		private const float IntMin = 0.25f;

		private const float IntMax = 5f;

		private const float DurStep = 15f;

		private const float DurMin = 15f;

		private const float DurMax = 600f;

		public const float LaneOffset = 10.75f;

		internal const int MaxLamps = 6;

		internal static readonly Color[] PlayerColors = (Color[])(object)new Color[4]
		{
			new Color(0.2f, 1f, 0.3f),
			new Color(0.25f, 0.55f, 1f),
			new Color(1f, 0.55f, 0.1f),
			new Color(1f, 0.3f, 0.8f)
		};

		private static readonly string[] ColorNames = new string[4] { "green", "blue", "orange", "pink" };

		private static readonly Lane[] lanes = new Lane[3]
		{
			null,
			new Lane
			{
				id = 1
			},
			new Lane
			{
				id = 2
			}
		};

		private static readonly Score[] scores = new Score[5]
		{
			null,
			new Score(),
			new Score(),
			new Score(),
			new Score()
		};

		private static int tab;

		private static int row;

		private static int map;

		private static float nextScreen;

		private static readonly Dictionary<string, int> best = new Dictionary<string, int>();

		public const string ScreenId = "glow";

		private const string Dim = "#6FBF6F";

		private const string Bright = "#C8FFC8";

		private const string Hi = "#FFFFFF";

		private static bool TwoWalls
		{
			get
			{
				if (Multiplayer && !Coop)
				{
					return !SharedTrail;
				}
				return false;
			}
		}

		private static bool ColoredHolds
		{
			get
			{
				if (Multiplayer && !Coop)
				{
					return SharedTrail;
				}
				return false;
			}
		}

		private static int WallCount
		{
			get
			{
				if (!TwoWalls)
				{
					return 1;
				}
				return 2;
			}
		}

		private static IEnumerable<Lane> Active => lanes.Skip(1).Take(WallCount);

		private static int Scorers
		{
			get
			{
				if (Multiplayer && !Coop)
				{
					if (!TwoWalls)
					{
						return Players;
					}
					return 2;
				}
				return 1;
			}
		}

		private static bool Busy => Active.Any((Lane l) => l.state == State.Countdown || l.state == State.Running);

		public static bool Running => Active.Any((Lane l) => l.state == State.Running);

		internal static int LampCount => MapGlowHold.All.Count((MapGlowHold h) => h.HasLamp);

		private static string ModeText
		{
			get
			{
				if (Multiplayer)
				{
					if (!Coop)
					{
						if (!SharedTrail)
						{
							return "comp, wall each";
						}
						return $"comp x{Players}, shared wall";
					}
					return $"co-op x{Players}";
				}
				return "1 player";
			}
		}

		private static string Settings => $"{MapNames[map]}, {ModeText}, lifespan {Lifespan:0.#} s, every {Interval:0.##} s, {Duration:0} s";

		internal static int VariantOf(MapPartInfo part)
		{
			string[] array = part.Args("variant");
			if (array.Length != 0)
			{
				return array[0].ToLowerInvariant().StartsWith("cyl") ? 1 : 0;
			}
			return -1;
		}

		internal static int LaneOf(MapPartInfo part)
		{
			if (part.Args("lane").Length == 0 || !int.TryParse(part.Args("lane")[0], out var result))
			{
				return 1;
			}
			return result;
		}

		internal static bool OnMap(int variant)
		{
			if (variant >= 0)
			{
				return variant == map;
			}
			return true;
		}

		internal static bool InPlay(MapGlowHold h, int lane)
		{
			if (h.lane == lane)
			{
				return OnMap(h.variant);
			}
			return false;
		}

		private static IEnumerable<int> PlayersOn(int lane)
		{
			if (!TwoWalls)
			{
				if (!ColoredHolds)
				{
					return new int[1] { 1 };
				}
				return Enumerable.Range(1, Players);
			}
			return new int[1] { lane };
		}

		private static string ScorerName(int p)
		{
			if (Multiplayer)
			{
				if (!Coop)
				{
					return $"P{p}";
				}
				return "Team";
			}
			return "You";
		}

		internal static bool IsOpen(int lane)
		{
			if (lane >= 1 && lane <= 2)
			{
				return lanes[lane].state == State.Running;
			}
			return false;
		}

		private static string Who(Lane l)
		{
			if (!TwoWalls)
			{
				return "";
			}
			return $"P{l.id} ";
		}

		internal static void PlaceLane(MapLane l)
		{
			float dx = ((!TwoWalls) ? 0f : ((l.lane == 1) ? (-10.75f) : 10.75f));
			l.Place(dx, l.lane == 1 || TwoWalls);
		}

		private static void ApplyLayout()
		{
			foreach (MapLane item in MapLane.All.ToList())
			{
				if ((Object)(object)item != (Object)null)
				{
					PlaceLane(item);
				}
			}
		}

		private static List<Item> Items()
		{
			//IL_033b: Unknown result type (might be due to invalid IL or missing references)
			List<Item> list = new List<Item> { null };
			if (tab == 0)
			{
				list.Add(new Item
				{
					label = "Map",
					value = MapNames[map],
					change = delegate(int d)
					{
						map = (map + d + MapNames.Length) % MapNames.Length;
					}
				});
				list.Add(new Item
				{
					label = "Multiplayer",
					value = (Multiplayer ? "ON" : "OFF"),
					change = delegate
					{
						Multiplayer = !Multiplayer;
					}
				});
				if (Multiplayer)
				{
					list.Add(new Item
					{
						label = "Mode",
						value = (Coop ? "Co-op" : "Comp"),
						change = delegate
						{
							Coop = !Coop;
						}
					});
					if (!Coop)
					{
						list.Add(new Item
						{
							label = "Trails",
							value = (SharedTrail ? "1 shared" : "1 per player"),
							change = delegate
							{
								SharedTrail = !SharedTrail;
							}
						});
					}
					if (Coop || SharedTrail)
					{
						list.Add(new Item
						{
							label = "Player count",
							value = Players.ToString(),
							change = delegate(int d)
							{
								Players = Mathf.Clamp(Players + d, 2, 4);
							}
						});
					}
				}
				list.Add(new Item
				{
					label = "Btn lifespan",
					value = $"{Lifespan:0.0} s",
					change = delegate(int d)
					{
						Lifespan = Mathf.Clamp(Lifespan + (float)d * 0.5f, 0.5f, 10f);
					}
				});
				list.Add(new Item
				{
					label = "Interval",
					value = $"{Interval:0.00} s",
					change = delegate(int d)
					{
						Interval = Mathf.Clamp(Interval + (float)d * 0.25f, 0.25f, 5f);
					}
				});
				list.Add(new Item
				{
					label = "Duration",
					value = $"{Duration:0} s",
					change = delegate(int d)
					{
						Duration = Mathf.Clamp(Duration + (float)d * 15f, 15f, 600f);
					}
				});
			}
			else
			{
				for (int num = 0; num < PowerUps.Names.Length; num++)
				{
					int k = num;
					list.Add(new Item
					{
						label = PowerUps.Shapes[k] + " - " + PowerUps.Names[k],
						value = (PowerUps.Enabled[k] ? "ON" : "OFF"),
						color = PowerUps.Colors[k],
						change = delegate
						{
							PowerUps.Enabled[k] = !PowerUps.Enabled[k];
						}
					});
				}
				list.Add(new Item
				{
					label = "Max at once",
					value = PowerUps.MaxAtOnce.ToString(),
					change = delegate(int d)
					{
						PowerUps.MaxAtOnce = Mathf.Clamp(PowerUps.MaxAtOnce + d, 1, 10);
					}
				});
				list.Add(new Item
				{
					label = "Spawn every",
					value = $"{PowerUps.SpawnEvery:0} s",
					change = delegate(int d)
					{
						PowerUps.SpawnEvery = Mathf.Clamp(PowerUps.SpawnEvery + (float)d * 5f, 5f, 60f);
					}
				});
			}
			return list;
		}

		public static void Menu(string key)
		{
			if (Busy)
			{
				return;
			}
			foreach (Lane item in Active)
			{
				if (item.state == State.Result)
				{
					item.state = State.Idle;
				}
			}
			List<Item> list = Items();
			row = Mathf.Clamp(row, 0, list.Count - 1);
			int num = ((key == "left") ? (-1) : ((key == "right") ? 1 : 0));
			if (key == "up")
			{
				row = (row + list.Count - 1) % list.Count;
			}
			else if (key == "down")
			{
				row = (row + 1) % list.Count;
			}
			else if (num != 0 && row == 0)
			{
				tab = 1 - tab;
			}
			else if (num != 0)
			{
				list[row].change(num);
				ApplyLayout();
			}
			RefreshScreens(force: true);
		}

		public static void StandPressed(int lane)
		{
			if (lane >= 1 && lane <= WallCount)
			{
				Lane lane2 = lanes[lane];
				if (lane2.state != State.Countdown && lane2.state != State.Running)
				{
					BeginCountdown(lane);
				}
			}
		}

		public static void BeginCountdown(int lane, float seconds = 0f)
		{
			if (seconds > 0f)
			{
				Duration = seconds;
			}
			if (!MapGlowHold.All.Any((MapGlowHold h) => InPlay(h, lane)))
			{
				MapApi.ShowTitle("No glow holds here");
				return;
			}
			Lane lane2 = lanes[lane];
			foreach (Lane item in Active)
			{
				if (item.state == State.Result)
				{
					item.state = State.Idle;
				}
			}
			lane2.state = State.Countdown;
			lane2.countEnd = Time.time + 3f;
			lane2.lastCount = 4;
			RefreshScreens(force: true);
		}

		private static void Go(Lane l)
		{
			l.state = State.Running;
			foreach (int item in PlayersOn(l.id))
			{
				Score obj = scores[item];
				obj.pressed = (obj.missed = 0);
				obj.reactions.Clear();
				obj.newBest = false;
			}
			l.warned10 = false;
			l.endTime = Time.time + Duration;
			l.nextLight = Time.time + 0.3f;
			l.rng = new Random(StableHash(Settings));
			foreach (MapBarrier item2 in MapBarrier.All)
			{
				if (item2.lane == l.id)
				{
					item2.Set(on: false);
				}
			}
			PowerUps.StartLane(l.id);
			MapApi.ShowTitle(Who(l) + "GO!");
			MapApi.Say("Glow wall " + Who(l) + ": " + Settings);
			RefreshScreens(force: true);
		}

		public static void Stop(bool showScore)
		{
			foreach (Lane item in Active.ToList())
			{
				if (item.state == State.Running && showScore)
				{
					Finish(item);
				}
				else if (item.state == State.Running || item.state == State.Countdown)
				{
					EndRound(item);
				}
			}
			RefreshScreens(force: true);
		}

		public static void Reset()
		{
			foreach (Lane item in lanes.Skip(1))
			{
				item.state = State.Idle;
			}
			PowerUps.Reset();
			RefreshScreens(force: true);
		}

		private static void EndRound(Lane l)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			l.state = State.Idle;
			foreach (MapGlowHold item in MapGlowHold.All.ToList())
			{
				if (item.lane == l.id)
				{
					item.SetLit(on: false);
				}
			}
			foreach (MapBarrier item2 in MapBarrier.All)
			{
				if (item2.lane == l.id)
				{
					item2.Set(on: true);
				}
			}
			PowerUps.ClearLane(l.id);
			MoveOutOfLane(l.id);
		}

		private static void MoveOutOfLane(int lane)
		{
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: 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_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: 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)
			ENT_Player playerObject = ENT_Player.playerObject;
			if ((Object)(object)playerObject == (Object)null)
			{
				return;
			}
			foreach (MapBarrier item in MapBarrier.All)
			{
				if (!((Object)(object)item == (Object)null) && item.lane == lane && item.front && ((Component)item).gameObject.activeInHierarchy && !((Object)(object)((Component)item).transform.parent == (Object)null))
				{
					Transform parent = ((Component)item).transform.parent;
					Vector3 val = parent.InverseTransformPoint(((Component)playerObject).transform.position);
					Vector3 localPosition = ((Component)item).transform.localPosition;
					if (!(val.z > localPosition.z) && !(Mathf.Abs(val.x - localPosition.x) > 11.75f))
					{
						((GameEntity)playerObject).Teleport(parent.TransformPoint(new Vector3(localPosition.x, 1.2f, localPosition.z + 4f)), ((Component)playerObject).transform.rotation, false);
						break;
					}
				}
			}
		}

		private static void Finish(Lane l)
		{
			EndRound(l);
			l.state = State.Result;
			string settings = Settings;
			foreach (int item in PlayersOn(l.id))
			{
				Score score = scores[item];
				score.newBest = !best.TryGetValue(settings, out var value) || score.pressed > value;
				if (score.newBest)
				{
					best[settings] = score.pressed;
				}
				MapApi.Say($"Glow wall {ScorerName(item)}: {score.pressed} pressed, {score.missed} missed, {Pct(score)}, {Rate(score)}, avg reaction {AvgRx(score)}, fastest {BestRx(score)}" + (score.newBest ? ", new best" : ""));
			}
			MapApi.ShowTitle("GAME OVER...");
			if (Scorers == 1)
			{
				ScoreTitle.After($"Score: {scores[1].pressed}" + (scores[1].newBest ? "  NEW BEST!" : ""));
				return;
			}
			foreach (int item2 in PlayersOn(l.id))
			{
				ScoreTitle.After($"{ScorerName(item2)}: {scores[item2].pressed}");
			}
		}

		public static void OnGrab(MapGlowHold h)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			Lane l = lanes[Mathf.Clamp(h.lane, 1, 2)];
			int owner = h.owner;
			h.SetLit(on: false);
			if (l.state != State.Running)
			{
				return;
			}
			int num = ((Coop || !Multiplayer) ? 1 : Mathf.Clamp(owner, 1, 4));
			Score score = scores[num];
			score.pressed++;
			score.reactions.Add(Time.time - h.litAt);
			MapApi.ShowTitle((Scorers > 1) ? $"{ScorerName(num)}: {score.pressed}" : score.pressed.ToString());
			if (!MapGlowHold.All.Any((MapGlowHold x) => x.lane == l.id && x.lit && x.owner == owner))
			{
				LightNext(l, Time.time, owner);
				if (!ColoredHolds)
				{
					l.nextLight = Time.time + Interval;
				}
			}
			RefreshScreens(force: true);
		}

		public static void Tick()
		{
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			float time = Time.time;
			bool flag = false;
			foreach (Lane item in Active.ToList())
			{
				if (item.state == State.Countdown)
				{
					flag = true;
					int num = Mathf.CeilToInt(item.countEnd - time);
					if (num != item.lastCount && num > 0)
					{
						item.lastCount = num;
						MapApi.ShowTitle(Who(item) + num);
						RefreshScreens(force: true);
					}
					if (time >= item.countEnd)
					{
						Go(item);
					}
				}
				else
				{
					if (item.state != State.Running)
					{
						continue;
					}
					flag = true;
					foreach (MapGlowHold item2 in MapGlowHold.All.ToList())
					{
						if (item2.lane == item.id && item2.lit && time >= item2.litUntil)
						{
							int num2 = ((Coop || !Multiplayer) ? 1 : Mathf.Clamp(item2.owner, 1, 4));
							item2.SetLit(on: false);
							scores[num2].missed++;
						}
					}
					if (time >= item.endTime)
					{
						Finish(item);
						RefreshScreens(force: true);
						continue;
					}
					if (!item.warned10 && Duration > 15f && item.endTime - time <= 10f)
					{
						item.warned10 = true;
						MapApi.ShowTitle(Who(item) + "10 s left");
					}
					if (time < item.nextLight)
					{
						continue;
					}
					item.nextLight += Interval;
					if (item.nextLight < time)
					{
						item.nextLight = time + Interval;
					}
					foreach (int item3 in PlayersOn(item.id))
					{
						LightNext(item, time, ColoredHolds ? item3 : item.id);
					}
				}
			}
			PowerUps.Tick((from x in Active
				where x.state == State.Running
				select x.id).ToList());
			if (flag)
			{
				RefreshScreens(force: false);
			}
		}

		private static void LightNext(Lane l, float now, int owner)
		{
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			List<MapGlowHold> list = (from h in MapGlowHold.All
				where InPlay(h, l.id)
				orderby Mathf.Round(h.home.y * 100f), Mathf.Round(h.home.x * 100f), Mathf.Round(h.home.z * 100f)
				select h).ToList();
			if (list.Count == 0)
			{
				return;
			}
			int num = l.rng.Next(list.Count);
			Color color = (ColoredHolds ? PlayerColors[Mathf.Clamp(owner - 1, 0, 3)] : PlayerColors[0]);
			for (int num2 = 0; num2 < list.Count; num2++)
			{
				MapGlowHold mapGlowHold = list[(num + num2) % list.Count];
				if (!mapGlowHold.lit && !mapGlowHold.Held)
				{
					mapGlowHold.owner = owner;
					mapGlowHold.SetLit(on: true, color);
					mapGlowHold.litAt = now;
					mapGlowHold.litUntil = now + Lifespan;
					break;
				}
			}
		}

		private static int StableHash(string s)
		{
			int num = -2128831035;
			foreach (char c in s)
			{
				num = (num ^ c) * 16777619;
			}
			return num & 0x7FFFFFFF;
		}

		private static string Clock(float t)
		{
			return $"{(int)(t / 60f)}:{t % 60f:00.0}";
		}

		public static void RefreshScreens(bool force)
		{
			if (MapScreen.Any("glow") && (force || !(Time.time < nextScreen)))
			{
				nextScreen = Time.time + 0.1f;
				MapScreen.Set("glow", "<align=left>" + ScreenText());
			}
		}

		private static string Hex(Color c)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			return "#" + ColorUtility.ToHtmlStringRGB(c);
		}

		private static string Title(string s)
		{
			return "<align=center><size=130%><b>" + s + "</b></size></align>\n";
		}

		private static string Hint(string s)
		{
			return "\n<align=center><size=65%><color=#6FBF6F>" + s + "</color></size></align>";
		}

		private static string Row(string label, params string[] values)
		{
			StringBuilder stringBuilder = new StringBuilder("<pos=4%><color=#6FBF6F>" + label + "</color><color=#C8FFC8>");
			float num = ((values.Length <= 1) ? 52f : 40f);
			float num2 = ((values.Length <= 1) ? 0f : (58f / (float)values.Length));
			for (int i = 0; i < values.Length; i++)
			{
				stringBuilder.Append($"<pos={num + (float)i * num2:0}%>{values[i]}");
			}
			return stringBuilder.Append("</color>\n").ToString();
		}

		private static string Pct(Score s)
		{
			int num = s.pressed + s.missed;
			if (num <= 0)
			{
				return "-";
			}
			return $"{100f * (float)s.pressed / (float)num:0}%";
		}

		private static string Rate(Score s)
		{
			return $"{(float)s.pressed / Duration * 60f:0.0}/min";
		}

		private static string AvgRx(Score s)
		{
			if (s.reactions.Count <= 0)
			{
				return "-";
			}
			return $"{s.reactions.Average():0.00} s";
		}

		private static string BestRx(Score s)
		{
			if (s.reactions.Count <= 0)
			{
				return "-";
			}
			return $"{s.reactions.Min():0.00} s";
		}

		private static string TabBar()
		{
			return "<align=center><size=90%>" + T(0, "GAME") + "      " + T(1, "POWER-UPS") + "</size></align>\n";
			static string T(int i, string name)
			{
				if (i != tab)
				{
					return "<color=#6FBF6F>" + name + "</color>";
				}
				if (row != 0)
				{
					return "<color=#FFFFFF><b>" + name + "</b></color>";
				}
				return "<color=#FFFFFF><u><b>" + name + "</b></u></color>";
			}
		}

		private static string ScreenText()
		{
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			StringBuilder stringBuilder = new StringBuilder();
			List<Lane> source = Active.ToList();
			if (source.All((Lane l) => l.state == State.Idle))
			{
				stringBuilder.Append(TabBar());
				stringBuilder.Append(Title((tab == 0) ? "GLOW WALL" : "POWER-UPS"));
				List<Item> list = Items();
				row = Mathf.Clamp(row, 0, list.Count - 1);
				for (int num = 1; num < list.Count; num++)
				{
					Item item = list[num];
					string text = (item.color.HasValue ? ("<color=" + Hex(item.color.Value) + ">" + item.label + "</color>") : item.label);
					stringBuilder.Append((num == row) ? ("<pos=4%><color=#FFFFFF><u>" + text + "</u><pos=62%><u>" + item.value + "</u></color>\n") : ("<pos=4%><color=#6FBF6F>" + text + "</color><pos=62%><color=#C8FFC8>" + item.value + "</color>\n"));
				}
				if (tab == 0 && ColoredHolds)
				{
					stringBuilder.Append(Row("Colors", string.Join("  ", from i in Enumerable.Range(0, Players)
						select $"<color={Hex(PlayerColors[i])}>P{i + 1} {ColorNames[i]}</color>")));
				}
				string text2 = ((tab == 1) ? "fly through a power-up to use it" : (TwoWalls ? "each player presses the red btn at their wall" : "press the red btn at the wall to start"));
				stringBuilder.Append(Hint(text2 + "<br>up/down = row   left/right = change   top row = tabs"));
				return stringBuilder.ToString();
			}
			bool flag = source.All((Lane l) => l.state == State.Result || l.state == State.Idle);
			stringBuilder.Append(Title(flag ? "GAME OVER..." : "GLOW WALL"));
			int scorers = Scorers;
			List<int> cols = Enumerable.Range(1, scorers).ToList();
			if (scorers > 1)
			{
				stringBuilder.Append(Row("", V(Name)));
			}
			if (!flag)
			{
				stringBuilder.Append(Row("Time left", V(delegate(int p)
				{
					Lane lane = LaneOf(p);
					return (lane.state != State.Countdown) ? ((lane.state != State.Running) ? ((lane.state != State.Result) ? "press red btn" : "done") : Clock(Mathf.Max(0f, lane.endTime - Time.time))) : $"<b>{Mathf.Max(1, Mathf.CeilToInt(lane.countEnd - Time.time))}</b>";
				})));
			}
			stringBuilder.Append(Row("Missed", V((int p) => (!Played(p)) ? "-" : scores[p].missed.ToString())));
			if (source.Any((Lane l) => l.state == State.Result))
			{
				stringBuilder.Append(Row("Accuracy", V((int p) => (!Done(p)) ? "-" : Pct(scores[p]))));
				stringBuilder.Append(Row("Press rate", V((int p) => (!Done(p)) ? "-" : Rate(scores[p]))));
				stringBuilder.Append(Row("Avg reaction", V((int p) => (!Done(p)) ? "-" : AvgRx(scores[p]))));
				stringBuilder.Append(Row("Fastest", V((int p) => (!Done(p)) ? "-" : BestRx(scores[p]))));
				stringBuilder.Append(Row("Best", V((int p) => Done(p) ? ((!scores[p].newBest) ? ((!best.TryGetValue(Settings, out var value)) ? "-" : value.ToString()) : "NEW!") : "-")));
			}
			string text3 = ((scorers != 1) ? string.Join("   ", cols.Select((int p) => Name(p) + " " + (Played(p) ? scores[p].pressed.ToString() : "-"))) : ((Played(1) ? scores[1].pressed.ToString() : "-") ?? ""));
			stringBuilder.Append("\n<align=center><size=140%><color=#FFFFFF>Pressed btns - " + text3 + "</color></size></align>\n");
			if (flag && scorers > 1 && cols.All(Done) && !Coop)
			{
				int top = cols.Max((int p) => scores[p].pressed);
				List<int> list2 = cols.Where((int p) => scores[p].pressed == top).ToList();
				stringBuilder.Append("<align=center><b>" + ((list2.Count > 1) ? "Draw!" : (ScorerName(list2[0]) + " wins!")) + "</b></align>\n");
			}
			stringBuilder.Append(Hint(Settings + ((!Busy) ? "<br>red btn = play again   arrows = settings" : "")));
			return stringBuilder.ToString();
			static bool Done(int p)
			{
				return LaneOf(p).state == State.Result;
			}
			static Lane LaneOf(int p)
			{
				if (!TwoWalls)
				{
					return lanes[1];
				}
				return lanes[p];
			}
			static string Name(int p)
			{
				//IL_002a: Unknown result type (might be due to invalid IL or missing references)
				if (!ColoredHolds)
				{
					return "<b>" + ScorerName(p) + "</b>";
				}
				return $"<color={Hex(PlayerColors[p - 1])}><b>P{p}</b></color>";
			}
			static bool Played(int p)
			{
				return LaneOf(p).state != State.Idle;
			}
			string[] V(Func<int, string> f)
			{
				return cols.Select(f).ToArray();
			}
		}
	}
	internal static class Plates
	{
		public static void Register()
		{
			MapApi.RegisterPreset("redpad", (Func<string[], string>)((string[] a) => "pad; color red; " + ((a.Length != 0) ? string.Join(" ", a) : "timer start")));
			MapApi.RegisterPreset("bluepad", (Func<string[], string>)((string[] a) => "pad; color blue; teleport" + ((a.Length != 0) ? (" " + a[0]) : "")));
			MapApi.RegisterPreset("greenpad", (Func<string[], string>)((string[] a) => "pad; color green; checkpoint"));
			MapApi.RegisterPreset("yellowpad", (Func<string[], string>)((string[] a) => "pad; color yellow; launch " + ((a.Length != 0) ? a[0] : "10")));
			MapApi.RegisterTag("color", (Action<MapPartInfo>)delegate(MapPartInfo part)
			{
				string[] array = part.Args("color");
				if (array.Length == 0 || !TryColor(array[0], out var c))
				{
					PlayRoomPlugin.Log.LogWarning((object)("'color' on '" + part.Name + "': unknown colour."));
				}
				else
				{
					MeshRenderer[] components = part.GameObject.GetComponents<MeshRenderer>();
					foreach (MeshRenderer obj in components)
					{
						((Renderer)obj).sharedMaterials = ((Renderer)obj).sharedMaterials.Select((Material m) => MatTools.Tint(m, c, false) ?? m).ToArray();
					}
				}
			});
		}

		private static bool TryColor(string s, out Color c)
		{
			//IL_004d: 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_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			switch (s.ToLowerInvariant())
			{
			case "red":
				c = new Color(0.85f, 0.12f, 0.1f);
				return true;
			case "blue":
				c = new Color(0.12f, 0.35f, 0.9f);
				return true;
			case "green":
				c = new Color(0.12f, 0.75f, 0.2f);
				return true;
			case "yellow":
				c = new Color(0.95f, 0.8f, 0.1f);
				return true;
			default:
				return ColorUtility.TryParseHtmlString("#" + s.TrimStart('#'), ref c);
			}
		}
	}
	[BepInPlugin("lazar.lakisplayroom", "Laki's MiniGames", "1.0.0")]
	[BepInDependency("lazar.wkmaploader", "1.1.0")]
	public class PlayRoomPlugin : BaseUnityPlugin
	{
		internal static ManualLogSource Log;

		private void Awake()
		{
			Log = ((BaseUnityPlugin)this).Logger;
			Kits.Register();
			Plates.Register();
			MapApi.RegisterTag("glow", (Action<MapPartInfo>)delegate(MapPartInfo part)
			{
				MapGlowHold mapGlowHold = part.GameObject.AddComponent<MapGlowHold>();
				mapGlowHold.lane = GlowGame.LaneOf(part);
				mapGlowHold.variant = GlowGame.VariantOf(part);
			});
			MapApi.RegisterTag("lane", (Action<MapPartInfo>)delegate(MapPartInfo part)
			{
				MapLane mapLane = part.GameObject.AddComponent<MapLane>();
				mapLane.lane = GlowGame.LaneOf(part);
				mapLane.variant = GlowGame.VariantOf(part);
				mapLane.spin = mapLane.variant == 1 && !part.Has("still");
				mapLane.axis = part.Has("drumaxis");
			});
			MapApi.RegisterTag("glowbarrier", (Action<MapPartInfo>)delegate(MapPartInfo part)
			{
				MapBarrier mapBarrier = part.GameObject.AddComponent<MapBarrier>();
				mapBarrier.lane = GlowGame.LaneOf(part);
				mapBarrier.front = part.Find("glowbarrier").Contains("front");
			});
			MapApi.RegisterTag("variant", (Action<MapPartInfo>)delegate
			{
			});
			MapApi.RegisterTag("drumaxis", (Action<MapPartInfo>)delegate
			{
			});
			MapApi.RegisterTag("still", (Action<MapPartInfo>)delegate
			{
			});
			MapApi.RegisterTag("rangeroom", (Action<MapPartInfo>)delegate(MapPartInfo part)
			{
				//IL_0011: Unknown result type (might be due to invalid IL or missing references)
				//IL_0016: Unknown result type (might be due to invalid IL or missing references)
				part.GameObject.AddComponent<MapRangeRoom>().size = ((Bounds)(ref part.LocalBounds)).size;
			});
			MapApi.RegisterAction("rangestart", (Action<string[]>)delegate
			{
				ShootGame.StandPressed();
			});
			MapApi.RegisterAction("rangemenu", (Action<string[]>)delegate(string[] a)
			{
				if (a.Length != 0)
				{
					ShootGame.Menu(a[0].ToLowerInvariant());
				}
			});
			MapApi.RegisterCommand("rangegame", (Action<string[]>)delegate(string[] args)
			{
				if (args.Length != 0 && args[0] == "stop")
				{
					ShootGame.Stop(showScore: true);
				}
				else
				{
					int waves = -1;
					if (args.Length != 0)
					{
						waves = ((!args[0].StartsWith("inf")) ? (int.TryParse(args[0], out var result) ? result : (-1)) : 0);
					}
					ShootGame.BeginCountdown(waves);
				}
			});
			MapApi.RegisterCommand("rangeenemies", (Action<string[]>)delegate(string[] args)
			{
				ShootGame.ListEnemies((args.Length != 0) ? args[0] : "");
			});
			MapApi.RegisterAction("glowstart", (Action<string[]>)delegate(string[] a)
			{
				GlowGame.StandPressed((a.Length == 0 || !int.TryParse(a[0], out var result)) ? 1 : result);
			});
			MapApi.RegisterAction("glowmenu", (Action<string[]>)delegate(string[] a)
			{
				if (a.Length != 0)
				{
					GlowGame.Menu(a[0].ToLowerInvariant());
				}
			});
			MapApi.RegisterCommand("glowgame", (Action<string[]>)delegate(string[] args)
			{
				if (args.Length != 0 && args[0] == "stop")
				{
					GlowGame.Stop(showScore: true);
				}
				else
				{
					float result = 0f;
					if (args.Length != 0)
					{
						float.TryParse(args[0], NumberStyles.Float, CultureInfo.InvariantCulture, out result);
					}
					GlowGame.BeginCountdown(1, result);
				}
			});
			MapApi.MapReset += MapScreen.Reset;
			MapApi.MapReset += GlowGame.Reset;
			MapApi.MapReset += ShootGame.Reset;
			MapApi.Tick += MapScreen.Tick;
			MapApi.Tick += GlowGame.Tick;
			MapApi.Tick += ShootGame.Tick;
			MapApi.MapReset += ScoreTitle.Reset;
			MapApi.Tick += ScoreTitle.Tick;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Laki's Play Room: glow wall ready.");
		}
	}
	internal static class ScoreTitle
	{
		private const float Delay = 2.5f;

		private static string text;

		private static float at;

		public static void After(string score)
		{
			text = ((text == null) ? score : (text + "   " + score));
			at = Time.time + 2.5f;
		}

		public static void Tick()
		{
			if (text != null && !(Time.time < at))
			{
				MapApi.ShowTitle(text);
				text = null;
			}
		}

		public static void Reset()
		{
			text = null;
		}
	}
	internal static class PowerUps
	{
		public enum Kind
		{
			Stamina,
			Speed,
			Jump,
			Elastic,
			Grub
		}

		private class Pickup
		{
			public GameObject go;

			public Kind kind;

			public int lane;

			public float born;

			public Vector3 home;
		}

		public static readonly string[] Names = new string[5] { "Stamina", "Speed boost", "Air jumps", "Elastic limbs", "Grab anything" };

		public static readonly string[] Shapes = new string[5] { "blue blob", "green triangle", "yellow block", "purple tube", "green diamond" };

		public static readonly Color[] Colors = (Color[])(object)new Color[5]
		{
			new Color(0.25f, 0.55f, 1f),
			new Color(0.3f, 1f, 0.3f),
			new Color(1f, 0.85f, 0.15f),
			new Color(0.7f, 0.3f, 1f),
			new Color(0.1f, 0.9f, 0.6f)
		};

		public static readonly bool[] Enabled = new bool[5] { true, true, true, true, true };

		public static int MaxAtOnce = 3;

		public static float SpawnEvery = 10f;

		private const float PickupRange = 2.2f;

		private const float Life = 20f;

		private static readonly List<Pickup> live = new List<Pickup>();

		private static readonly Dictionary<int, float> nextSpawn = new Dictionary<int, float>();

		private static readonly Dictionary<Kind, Mesh> meshes = new Dictionary<Kind, Mesh>();

		private static readonly string[][] Effect = new string[5][]
		{
			new string[1] { "effect refill" },
			new string[1] { "perk velocity 10" },
			new string[2] { "effect temp_jump 5", "effect jump_boost 10" },
			new string[1] { "perk elastic 10" },
			new string[1] { "effect sticky_hands 10" }
		};

		public static bool AnyEnabled => Enabled.Any((bool e) => e);

		public static void StartLane(int lane)
		{
			nextSpawn[lane] = Time.time + Mathf.Min(SpawnEvery, 5f);
		}

		public static void ClearLane(int lane)
		{
			foreach (Pickup item in live.Where((Pickup x) => x.lane == lane).ToList())
			{
				if ((Object)(object)item.go != (Object)null)
				{
					Object.Destroy((Object)(object)item.go);
				}
				live.Remove(item);
			}
		}

		public static void Reset()
		{
			foreach (Pickup item in live)
			{
				if ((Object)(object)item.go != (Object)null)
				{
					Object.Destroy((Object)(object)item.go);
				}
			}
			live.Clear();
			nextSpawn.Clear();
		}

		public static void Tick(IEnumerable<int> runningLanes)
		{
			//IL_00e5: 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)
			//IL_00ef: 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)
			//IL_00f4: 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_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_0211: Unknown result type (might be due to invalid IL or missing references)
			//IL_021e: Unknown result type (might be due to invalid IL or missing references)
			float time = Time.time;
			ENT_Player playerObject = ENT_Player.playerObject;
			foreach (int lane in runningLanes)
			{
				if (!AnyEnabled)
				{
					break;
				}
				if (!nextSpawn.TryGetValue(lane, out var value))
				{
					float num = (nextSpawn[lane] = time + SpawnEvery);
					value = num;
				}
				if (!(time < value))
				{
					nextSpawn[lane] = time + SpawnEvery;
					if (live.Count((Pickup x) => x.lane == lane) < MaxAtOnce)
					{
						Spawn(lane);
					}
				}
			}
			Vector3 val = (((Object)(object)playerObject != (Object)null) ? (((Component)playerObject).transform.position + Vector3.up) : Vector3.zero);
			Vector3 val2 = (((Object)(object)Camera.main != (Object)null) ? ((Component)Camera.main).transform.position : val);
			foreach (Pickup item in live.ToList())
			{
				if ((Object)(object)item.go == (Object)null || time - item.born > 20f)
				{
					if ((Object)(object)item.go != (Object)null)
					{
						Object.Destroy((Object)(object)item.go);
					}
					live.Remove(item);
					continue;
				}
				float num3 = time - item.born;
				item.go.transform.position = item.home + Vector3.up * Mathf.Sin(num3 * 2f) * 0.12f;
				item.go.transform.rotation = Quaternion.Euler(0f, num3 * 90f, 0f);
				if ((Object)(object)playerObject != (Object)null && Mathf.Min(Vector3.Distance(val, item.go.transform.position), Vector3.Distance(val2, item.go.transform.position)) < 2.2f)
				{
					Apply(item.kind, playerObject);
					Object.Destroy((Object)(object)item.go);
					live.Remove(item);
				}
			}
		}

		private static void Spawn(int lane)
		{
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Expected O, but got Unknown
			//IL_00e8: 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_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			List<int> list = (from i in Enumerable.Range(0, Names.Length)
				where Enabled[i]
				select i).ToList();
			List<MapGlowHold> list2 = MapGlowHold.All.Where((MapGlowHold h) => GlowGame.InPlay(h, lane) && !h.lit).ToList();
			if (list.Count != 0 && list2.Count != 0)
			{
				MapGlowHold mapGlowHold = list2[Random.Range(0, list2.Count)];
				Kind kind = (Kind)list[Random.Range(0, list.Count)];
				Renderer component = ((Component)mapGlowHold).GetComponent<Renderer>();
				Material val = ((component != null) ? component.sharedMaterial : null);
				GameObject val2 = new GameObject("powerup_" + kind);
				val2.transform.SetParent(((Component)mapGlowHold).transform.parent, true);
				Vector3 val3 = ((Component)mapGlowHold).transform.position + ((Component)mapGlowHold).transform.forward * 1.6f;
				val2.transform.position = val3;
				Transform transform = val2.transform;
				transform.localScale *= 3f;
				val2.AddComponent<MeshFilter>().sharedMesh = MeshFor(kind);
				((Renderer)val2.AddComponent<MeshRenderer>()).sharedMaterial = MatTools.Tint(val, Colors[(int)kind], false);
				live.Add(new Pickup
				{
					go = val2,
					kind = kind,
					lane = lane,
					born = Time.time,
					home = val3
				});
			}
		}

		private static void Apply(Kind kind, ENT_Player p)
		{
			string[] array = Effect[(int)kind];
			for (int i = 0; i < array.Length; i++)
			{
				MapApi.RunAction(array[i]);
			}
			MapApi.ShowTitle(kind switch
			{
				Kind.Jump => "+5 air jumps!", 
				Kind.Stamina => "Stamina refilled!", 
				_ => Names[(int)kind] + " 10 s!", 
			});
		}

		private static Mesh MeshFor(Kind k)
		{
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: 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_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: 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_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0242: Unknown result type (might be due to invalid IL or missing references)
			//IL_0247: Unknown result type (might be due to invalid IL or missing references)
			//IL_025d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0262: Unknown result type (might be due to invalid IL or missing references)
			//IL_0278: Unknown result type (might be due to invalid IL or missing references)
			//IL_027d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0289: Unknown result type (might be due to invalid IL or missing references)
			//IL_0293: Unknown result type (might be due to invalid IL or missing references)
			//IL_029c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0304: Unknown result type (might be due to invalid IL or missing references)
			//IL_0309: Unknown result type (might be due to invalid IL or missing references)
			//IL_0318: Unknown result type (might be due to invalid IL or missing references)
			//IL_0325: Unknown result type (might be due to invalid IL or missing references)
			//IL_032a: Unknown result type (might be due to invalid IL or missing references)
			//IL_032f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0334: Unknown result type (might be due to invalid IL or missing references)
			//IL_0338: Unknown result type (might be due to invalid IL or missing references)
			//IL_033d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0437: Unknown result type (might be due to invalid IL or missing references)
			//IL_043c: Unknown result type (might be due to invalid IL or missing references)
			//IL_045a: Expected O, but got Unknown
			//IL_0065: 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_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_036f: Unknown result type (might be due to invalid IL or missing references)
			//IL_039a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0389: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03da: Unknown result type (might be due to invalid IL or missing references)
			if (meshes.TryGetValue(k, out var value) && (Object)(object)value != (Object)null)
			{
				return value;
			}
			List<Vector3> tris = new List<Vector3>();
			switch (k)
			{
			case Kind.Stamina:
			{
				int seg = 8;
				int rings = 5;
				for (int num = 0; num < rings; num++)
				{
					for (int num2 = 0; num2 < seg; num2++)
					{
						Q(P(num, num2), P(num, num2 + 1), P(num + 1, num2 + 1), P(num + 1, num2));
					}
				}
				break;
			}
			case Kind.Speed:
				Prism((Vector3[])(object)new Vector3[3]
				{
					new Vector3(0f, 0.3f, 0f),
					new Vector3(0.28f, -0.2f, 0f),
					new Vector3(-0.28f, -0.2f, 0f)
				}, 0.08f);
				break;
			case Kind.Jump:
				Prism((Vector3[])(object)new Vector3[4]
				{
					new Vector3(-0.28f, -0.16f, 0f),
					new Vector3(-0.28f, 0.16f, 0f),
					new Vector3(0.28f, 0.16f, 0f),
					new Vector3(0.28f, -0.16f, 0f)
				}, 0.1f);
				break;
			case Kind.Elastic:
				Prism(Enumerable.Range(0, 10).Select((Func<int, Vector3>)((int num7) => new Vector3(Mathf.Cos((float)num7 * MathF.PI / 5f) * 0.12f, Mathf.Sin((float)num7 * MathF.PI / 5f) * 0.12f, 0f))).ToArray(), 0.3f);
				break;
			case Kind.Grub:
			{
				Vector3 a = Vector3.up * 0.38f;
				Vector3 a2 = Vector3.down * 0.38f;
				Vector3[] array = (Vector3[])(object)new Vector3[4]
				{
					new Vector3(0.24f, 0f, 0f),
					new Vector3(0f, 0f, 0.24f),
					new Vector3(-0.24f, 0f, 0f),
					new Vector3(0f, 0f, -0.24f)
				};
				for (int i = 0; i < 4; i++)
				{
					T(a, array[(i + 1) % 4], array[i]);
					T(a2, array[i], array[(i + 1) % 4]);
				}
				break;
			}
			}
			List<Vector3> list = new List<Vector3>();
			List<Vector3> list2 = new List<Vector3>();
			List<int> list3 = new List<int>();
			for (int num3 = 0; num3 < tris.Count; num3 += 3)
			{
				Vector3 val = Vector3.Cross(tris[num3 + 1] - tris[num3], tris[num3 + 2] - tris[num3]);
				Vector3 normalized = ((Vector3)(ref val)).normalized;
				int[] array2 = new int[2] { 1, -1 };
				foreach (int num5 in array2)
				{
					int count = list.Count;
					list.Add(tris[num3]);
					list.Add((num5 > 0) ? tris[num3 + 1] : tris[num3 + 2]);
					list.Add((num5 > 0) ? tris[num3 + 2] : tris[num3 + 1]);
					for (int num6 = 0; num6 < 3; num6++)
					{
						list2.Add(normalized * (float)num5);
					}
					list3.Add(count);
					list3.Add(count + 1);
					list3.Add(count + 2);
				}
			}
			value = new Mesh
			{
				name = "powerup_" + k
			};
			value.SetVertices(list);
			value.SetNormals(list2);
			value.SetTriangles(list3, 0);
			value.uv = ((IEnumerable<Vector3>)list).Select((Func<Vector3, Vector2>)((Vector3 v) => new Vector2(v.x + 0.5f, v.y + 0.5f))).ToArray();
			value.RecalculateBounds();
			return meshes[k] = value;
			void Prism(Vector3[] ring, float hz)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0015: Unknown result type (might be due to invalid IL or missing references)
				//IL_001a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0023: Unknown result type (might be due to invalid IL or missing references)
				//IL_0028: Unknown result type (might be due to invalid IL or missing references)
				//IL_0029: Unknown result type (might be due to invalid IL or missing references)
				//IL_002a: Unknown result type (might be due to invalid IL or missing references)
				//IL_002b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0030: Unknown result type (might be due to invalid IL or missing references)
				//IL_0031: Unknown result type (might be due to invalid IL or missing references)
				//IL_0032: Unknown result type (might be due to invalid IL or missing references)
				//IL_0037: Unknown result type (might be due to invalid IL or missing references)
				//IL_0038: Unknown result type (might be due to invalid IL or missing references)
				//IL_0039: Unknown result type (might be due to invalid IL or missing references)
				//IL_003e: Unknown result type (might be due to invalid IL or missing references)
				//IL_003f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0040: Unknown result type (might be due to invalid IL or missing references)
				//IL_0059: Unknown result type (might be due to invalid IL or missing references)
				//IL_005e: Unknown result type (might be due to invalid IL or missing references)
				//IL_005f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0068: Unknown result type (might be due to invalid IL or missing references)
				//IL_006d: Unknown result type (might be due to invalid IL or missing references)
				//IL_006e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0075: Unknown result type (might be due to invalid IL or missing references)
				//IL_007a: Unknown result type (might be due to invalid IL or missing references)
				//IL_007b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0088: Unknown result type (might be due to invalid IL or missing references)
				//IL_008d: Unknown result type (might be due to invalid IL or missing references)
				//IL_008e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0095: Unknown result type (might be due to invalid IL or missing references)
				//IL_009a: Unknown result type (might be due to invalid IL or missing references)
				//IL_009b: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a4: 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_00aa: Unknown result type (might be due to invalid IL or missing references)
				Vector3 val3 = Vector3.forward * hz;
				for (int j = 0; j < ring.Length; j++)
				{
					Vector3 val4 = ring[j];
					Vector3 val5 = ring[(j + 1) % ring.Length];
					Q(val4 - val3, val5 - val3, val5 + val3, val4 + val3);
					if (j > 0 && j < ring.Length - 1)
					{
						T(ring[0] + val3, ring[j + 1] + val3, ring[j] + val3);
						T(ring[0] - val3, ring[j] - val3, ring[j + 1] - val3);
					}
				}
			}
			void Q(Vector3 a3, Vector3 b, Vector3 c, Vector3 d)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				//IL_000a: Unknown result type (might be due to invalid IL or missing references)
				//IL_000b: 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)
				T(a3, b, c);
				T(a3, c, d);
			}
			void T(Vector3 item, Vector3 b, Vector3 c)
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_0012: Unknown result type (might be due to invalid IL or missing references)
				//IL_001e: Unknown result type (might be due to invalid IL or missing references)
				tris.Add(item);
				tris.Add(b);
				tris.Add(c);
			}
		}
	}
	public class MapRangeRoom : MonoBehaviour
	{
		public Vector3 size;

		internal static readonly List<MapRangeRoom> All = new List<MapRangeRoom>();

		private void OnEnable()
		{
			All.Add(this);
		}

		private void OnDisable()
		{
			All.Remove(this);
		}

		internal Vector3 RandomPoint(Random rng)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: 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)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = Vector3.Max(size / 2f - Vector3.one * 1.5f, Vector3.zero);
			return ((Component)this).transform.TransformPoint(new Vector3(R(0f - val.x, val.x), R(0f - val.y, val.y), R(0f - val.z, val.z)));
			float R(float a, float b)
			{
				return a + (float)rng.NextDouble() * (b - a);
			}
		}

		internal bool Contain(Transform t)
		{
			//IL_0007: 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_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: 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_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = ((Component)this).transform.InverseTransformPoint(t.position);
			Vector3 val2 = size / 2f - Vector3.one * 0.5f;
			Vector3 val3 = default(Vector3);
			((Vector3)(ref val3))..ctor(Mathf.Clamp(val.x, 0f - val2.x, val2.x), Mathf.Clamp(val.y, 0f - val2.y, val2.y), Mathf.Clamp(val.z, 0f - val2.z, val2.z));
			if (val3 == val)
			{
				return false;
			}
			t.position = ((Component)this).transform.TransformPoint(val3);
			return true;
		}
	}
	internal static class ShootGame
	{
		private class Kind
		{
			public string name;

			public string id;

			public bool flier;

			public bool on;

			public int points;

			public GameObject prefab;

			public bool looked;
		}

		private enum State
		{
			Idle,
			Countdown,
			Running,
			Result
		}

		private class Live
		{
			public GameObject go;

			public GameEntity ent;

			public Kind kind;
		}

		private class Item
		{
			public string label;

			public string value;

			public Action<int> change;
		}

		private static readonly string[] WeaponNames = new string[3] { "Handgun", "Flare gun", "Rho spear" };

		private static readonly string[] WeaponItems = new string[3] { "Item_Handgun", "Item_Flaregun", "Item_Artifact_Rebar_Return" };

		private static readonly Kind[] Kinds = new Kind[7]
		{
			new Kind
			{
				name = "Moth Whelp",
				id = "Denizen_Moth",
				flier = true,
				points = 30,
				on = true
			},
			new Kind
			{
				name = "Bloodbug",
				id = "Denizen_Bloodbug",
				flier = true,
				points = 25
			},
			new Kind
			{
				name = "Spitter Bloodbug",
				id = "Denizen_Bloodbug_Spitter",
				flier = true,
				points = 30
			},
			new Kind
			{
				name = "Gasbag",
				id = "Denizen_Gasbag",
				flier = true,
				points = 10,
				on = true
			},
			new Kind
			{
				name = "Buddy",
				id = "Denizen_Drone_Buddy",
				flier = true,
				points = 20
			},
			new Kind
			{
				name = "Grub Aunt",
				id = "Denizen_Grub_Aunt",
				points = 10
			},
			new Kind
			{
				name = "Hopper Roach",
				id = "Denizen_HopperRoach",
				points = 20
			}
		};

		public static int Weapon;

		public static int Waves = 5;

		private const int MaxWaves = 50;

		private const int FirstWave = 3;

		private const int PerWave = 2;

		private const float WaveBreak = 2f;

		private static State state = State.Idle;

		private static float countEnd;

		private static float startTime;

		private static float endTime;

		private static float nextWaveAt;

		private static float nextAmmo;

		private static float nextScreen;

		private static int lastCount;

		private static int wave;

		private static int cleared;

		private static int kills;

		private static int score;

		private static bool won;

		private static bool newTop;

		private static readonly List<Live> live = new List<Live>();

		private static Random rng = new Random();

		private static int tab;

		private static int row;

		private static readonly Dictionary<int, float> bestTime = new Dictionary<int, float>();

		private static int bestInfinite = -1;

		public const string ScreenId = "range";

		private const string Dim = "#6FBF6F";

		private const string Bright = "#C8FFC8";

		private const string Hi = "#FFFFFF";

		private static bool Busy
		{
			get
			{
				if (state != State.Countdown)
				{
					return state == State.Running;
				}
				return true;
			}
		}

		private static bool Infinite => Waves == 0;

		private static MapRangeRoom Room => MapRangeRoom.All.FirstOrDefault((MapRangeRoom r) => (Object)(object)r != (Object)null && ((Behaviour)r).isActiveAndEnabled);

		private static string WavesText
		{
			get
			{
				if (!Infinite)
				{
					return Waves.ToString();
				}
				return "Infinite";
			}
		}

		private static string Settings => WeaponNames[Weapon] + ", " + WavesText + " waves, " + string.Join("/", from k in Kinds
			where k.@on
			select k.name);

		private static string TopText
		{
			get
			{
				if (!Infinite)
				{
					if (!bestTime.TryGetValue(Waves, out var value))
					{
						return "-";
					}
					return Clock(value);
				}
				if (bestInfinite < 0)
				{
					return "-";
				}
				return $"{bestInfinite} waves";
			}
		}

		private static int WaveSize(int n)
		{
			return 3 + 2 * (n - 1);
		}

		private static List<Item> Items()
		{
			List<Item> list = new List<Item> { null };
			if (tab == 0)
			{
				list.Add(new Item
				{
					label = "Weapon",
					value = WeaponNames[Weapon],
					change = delegate(int d)
					{
						Weapon = (Weapon + d + WeaponNames.Length) % WeaponNames.Length;
					}
				});
				list.Add(new Item
				{
					label = "Waves",
					value = WavesText,
					change = delegate(int d)
					{
						Waves = (Waves + d + 50 + 1) % 51;
					}
				});
			}
			else
			{
				Kind[] kinds = Kinds;
				foreach (Kind kind in kinds)
				{
					Kind kk = kind;
					list.Add(new Item
					{
						label = $"{kind.name} ({kind.points})" + (kind.flier ? "" : " ground"),
						value = (kind.on ? "ON" : "OFF"),
						change = delegate
						{
							kk.on = !kk.on;
						}
					});
				}
			}
			return list;
		}

		public static void Menu(string key)
		{
			if (!Busy)
			{
				if (state == State.Result)
				{
					state = State.Idle;
				}
				List<Item> list = Items();
				row = Mathf.Clamp(row, 0, list.Count - 1);
				int num = ((key == "left") ? (-1) : ((key == "right") ? 1 : 0));
				if (key == "up")
				{
					row = (row + list.Count - 1) % list.Count;
				}
				else if (key == "down")
				{
					row = (row + 1) % list.Count;
				}
				else if (num != 0 && row == 0)
				{
					tab = 1 - tab;
				}
				else if (num != 0)
				{
					list[row].change(num);
				}
				RefreshScreens(force: true);
			}
		}

		public static void StandPressed()
		{
			if (state == State.Running)
			{
				Stop(showScore: true);
			}
			else if (state != State.Countdown)
			{
				BeginCountdown(-1);
			}
		}

		public static void BeginCountdown(int waves)
		{
			if (waves >= 0)
			{
				Waves = Mathf.Min(waves, 50);
			}
			if ((Object)(object)Room == (Object)null)
			{
				MapApi.ShowTitle("No range room here");
				return;
			}
			if (!Kinds.Any((Kind k) => k.on))
			{
				MapApi.ShowTitle("Turn on an enemy first");
				return;
			}
			state = State.Countdown;
			countEnd = Time.time + 3f;
			lastCount = 4;
			RefreshScreens(force: true);
		}

		private static void Go()
		{
			state = State.Running;
			wave = (cleared = (kills = (score = 0)));
			won = (newTop = false);
			startTime = Time.time;
			rng = new Random();
			MapApi.RunAction("clear");
			MapApi.RunAction("give " + WeaponItems[Weapon] + " 1");
			MapApi.Say("Shooting range: " + Settings);
			NextWave();
		}

		private static void NextWave()
		{
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			MapRangeRoom room = Room;
			List<Kind> list = Kinds.Where((Kind k) => k.on && (Object)(object)Prefab(k) != (Object)null).ToList();
			if ((Object)(object)room == (Object)null || list.Count == 0)
			{
				Stop(showScore: false);
				MapApi.ShowTitle("No enemies to spawn");
				return;
			}
			wave++;
			for (int num = 0; num < WaveSize(wave); num++)
			{
				Kind kind = list[rng.Next(list.Count)];
				Vector3 val = room.RandomPoint(rng);
				GameObject val2 = Object.Instantiate<GameObject>(kind.prefab, val, Quaternion.Euler(0f, (float)rng.NextDouble() * 360f, 0f), ((Component)room).transform);
				val2.SetActive(true);
				live.Add(new Live
				{
					go = val2,
					ent = val2.GetComponentInChildren<GameEntity>(),
					kind = kind
				});
			}
			nextWaveAt = 0f;
			MapApi.ShowTitle(Infinite ? $"Wave {wave}" : $"Wave {wave}/{Waves}");
			RefreshScreens(force: true);
		}

		private static void WaveCleared()
		{
			cleared = wave;
			if (!Infinite && wave >= Waves)
			{
				Finish(beat: true);
				return;
			}
			MapApi.ShowTitle($"Wave {wave} cleared!");
			nextWaveAt = Time.time + 2f;
		}

		private static void Finish(bool beat)
		{
			endTime = Time.time;
			EndRound();
			state = State.Result;
			won = beat;
			float num = endTime - startTime;
			if (Infinite)
			{
				newTop = cleared > bestInfinite;
				if (newTop)
				{
					bestInfinite = cleared;
				}
				MapApi.ShowTitle($"{cleared} waves cleared" + (newTop ? " - TOP SCORE!" : ""));
			}
			else if (won)
			{
				newTop = !bestTime.TryGetValue(Waves, out var value) || num < value;
				if (newTop)
				{
					bestTime[Waves] = num;
				}
				MapApi.ShowTitle($"All {Waves} waves in {Clock(num)}" + (newTop ? " - TOP SCORE!" : ""));
			}
			else
			{
				MapApi.ShowTitle($"Stopped at wave {wave}");
			}
			ScoreTitle.After($"Score: {score}");
			MapApi.Say($"Shooting range: {score} points, {cleared} waves cleared, {kills} kills, {Clock(num)}" + (newTop ? ", new top score" : ""));
		}

		private static void EndRound()
		{
			foreach (Live item in live)
			{
				if ((Object)(object)item.go != (Object)null)
				{
					Object.Destroy((Object)(object)item.go);
				}
			}
			live.Clear();
			nextWaveAt = 0f;
			MapApi.RunAction("clear");
		}

		public static void Stop(bool showScore)
		{
			if (state == State.Running && showScore)
			{
				Finish(beat: false);
			}
			else if (Busy)
			{
				EndRound();
				state = State.Idle;
			}
			RefreshScreens(force: true);
		}

		public static void Reset()
		{
			live.Clear();
			nextWaveAt = 0f;
			state = State.Idle;
			RefreshScreens(force: true);
		}

		public static void Tick()
		{
			float time = Time.time;
			if (state == State.Countdown)
			{
				int num = Mathf.CeilToInt(countEnd - time);
				if (num != lastCount && num > 0)
				{
					lastCount = num;
					MapApi.ShowTitle(num.ToString());
					RefreshScreens(force: true);
				}
				if (time >= countEnd)
				{
					Go();
				}
			}
			else
			{
				if (state != State.Running)
				{
					return;
				}
				MapRangeRoom room = Room;
				if ((Object)(object)room == (Object)null)
				{
					Stop(showScore: false);
					return;
				}
				for (int num2 = ShootGame.live.Count - 1; num2 >= 0; num2--)
				{
					Live live = ShootGame.live[num2];
					if ((Object)(object)live.go == (Object)null || ((Object)(object)live.ent != (Object)null && live.ent.dead))
					{
						ShootGame.live.RemoveAt(num2);
						kills++;
						score += live.kind.points;
						if ((Object)(object)live.go != (Object)null)
						{
							Object.Destroy((Object)(object)live.go, 3f);
						}
					}
					else
					{
						room.Contain(live.go.transform);
					}
				}
				if (nextWaveAt > 0f)
				{
					if (time >= nextWaveAt)
					{
						NextWave();
					}
				}
				else if (ShootGame.live.Count == 0)
				{
					WaveCleared();
				}
				if (state != State.Running)
				{
					RefreshScreens(force: true);
					return;
				}
				if (time >= nextAmmo)
				{
					nextAmmo = time + 0.1f;
					TopUpAmmo();
				}
				RefreshScreens(force: false);
			}
		}

		private static GameObject Prefab(Kind k)
		{
			if ((Object)(object)k.prefab != (Object)null || k.looked)
			{
				return k.prefab;
			}
			k.looked = true;
			try
			{
				k.prefab = CL_AssetManager.GetAssetGameObject(k.id, "");
				if ((Object)(object)k.prefab == (Object)null)
				{
					WKAssetDatabase fullCombinedAssetDatabase = CL_AssetManager.GetFullCombinedAssetDatabase();
					k.prefab = fullCombinedAssetDatabase.entityPrefabs.Concat(fullCombinedAssetDatabase.denizenPrefabs).FirstOrDefault((Func<GameObject, bool>)((GameObject p) => (Object)(object)p != (Object)null && ((Object)p).name.Equals(k.id, StringComparison.OrdinalIgnoreCase)));
				}
			}
			catch (Exception ex)
			{
				PlayRoomPlugin.Log.LogError((object)ex);
			}
			if ((Object)(object)k.prefab == (Object)null)
			{
				MapApi.Say("Shooting range: can't find '" + k.id + "' (" + k.name + ") in the game.");
			}
			return k.prefab;
		}

		private static void TopUpAmmo()
		{
			HandItem_Shoot[] array = Object.FindObjectsOfType<HandItem_Shoot>();
			foreach (HandItem_Shoot val in array)
			{
				if (!((Object)(object)val == (Object)null) && val.useAmmo && ((HandItem)val).item != null)
				{
					int.TryParse(((HandItem)val).item.GetFirstDataStringByType("ammo", false), out var result);
					if (result < val.GetMaxAmmo())
					{
						val.Recharge();
					}
				}
			}
		}

		public static void ListEnemies(string filter)
		{
			WKAssetDatabase fullCombinedAssetDatabase = CL_AssetManager.GetFullCombinedAssetDatabase();
			List<string> list = (from n in (from p in fullCombinedAssetDatabase.entityPrefabs.Concat(fullCombinedAssetDatabase.denizenPrefabs)
					where (Object)(object)p != (Object)null
					select ((Object)p).name).Distinct()
				where (!string.IsNullOrEmpty(filter)) ? (n.IndexOf(filter, StringComparison.OrdinalIgnoreCase) >= 0) : n.StartsWith("Denizen_")
				orderby n
				select n).ToList();
			MapApi.Say((list.Count == 0) ? "No matches." : string.Join(", ", list));
		}

		private static string Title(string s)
		{
			return "<align=center><size=130%><b>" + s + "</b></size></align>\n";
		}

		private static string Hint(string s)
		{
			return "\n<align=center><size=65%><color=#6FBF6F>" + s + "</color></size></align>";
		}

		private static string Row(string label, string value)
		{
			return "<pos=4%><color=#6FBF6F>" + label + "</color><pos=52%><color=#C8FFC8>" + value + "</color>\n";
		}

		private static string Clock(float t)
		{
			return $"{(int)(t / 60f)}:{t % 60f:00.0}";
		}

		public static void RefreshScreens(bool force)
		{
			if (MapScreen.Any("range") && (force || !(Time.time < nextScreen)))
			{
				nextScreen = Time.time + 0.1f;
				MapScreen.Set("range", "<align=left>" + ScreenText());
			}
		}

		private static string ScreenText()
		{
			StringBuilder stringBuilder = new StringBuilder();
			if (state == State.Idle)
			{
				stringBuilder.Append("<align=center><size=90%>" + T(0, "GAME") + "      " + T(1, "ENEMIES") + "</size></align>\n");
				stringBuilder.Append(Title((tab == 0) ? "SHOOTING RANGE" : "ENEMIES"));
				List<Item> list = Items();
				row = Mathf.Clamp(row, 0, list.Count - 1);
				for (int i = 1; i < list.Count; i++)
				{
					Item item = list[i];
					stringBuilder.Append((i == row) ? ("<pos=4%><color=#FFFFFF><u>" + item.label + "</u><pos=62%><u>" + item.value + "</u></color>\n") : ("<pos=4%><color=#6FBF6F>" + item.label + "</color><pos=62%><color=#C8FFC8>" + item.value + "</color>\n"));
				}
				if (tab == 0)
				{
					stringBuilder.Append(Row(Infinite ? "Top score" : "Best time", TopText));
				}
				stringBuilder.Append(Hint($"wave 1 = {3} enemies, +{2} each wave<br>red btn at the glass = start (press again to stop)<br>up/down = row   left/right = change   top row = tabs"));
				return stringBuilder.ToString();
			}
			float num = ((state == State.Result) ? endTime : ((state == State.Running) ? Time.time : startTime)) - startTime;
			stringBuilder.Append(Title((state != State.Result) ? "SHOOTING RANGE" : (won ? "ALL WAVES BEATEN!" : "GAME OVER...")));
			if (state == State.Countdown)
			{
				stringBuilder.Append(Row("Starting in", $"<b>{Mathf.Max(1, Mathf.CeilToInt(countEnd - Time.time))}</b>"));
			}
			else
			{
				stringBuilder.Append(Row("Wave", Infinite ? wave.ToString() : $"{wave} / {Waves}"));
				if (state == State.Running)
				{
					stringBuilder.Append(Row("Enemies left", (nextWaveAt > 0f) ? "next wave..." : live.Count.ToString()));
				}
				stringBuilder.Append(Row("Waves cleared", cleared.ToString()));
				stringBuilder.Append(Row("Kills", kills.ToString()));
				stringBuilder.Append(Row("Score", (state == State.Result) ? $"<b>{score}</b>" : score.ToString()));
				stringBuilder.Append(Row(Infinite ? "Top score" : "Best time", ne